diff --git a/README.md b/README.md index 0735ce8..0b0fd58 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,9 @@ react_node_version: 10.x # the version of node to install react_git_url: "https://github.com/onaio/kaznet-frontend.git" # the git repo of your django app which we are installing react_git_key: + +react_remote_js_build: # whether to compile the app on the target host or on the controlling host. +# When compiling the app on the controlling host, you will need to make sure that node and yarn is installed. ``` ### Custom environment variables diff --git a/defaults/main.yml b/defaults/main.yml index e05fe87..839c44b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,18 +1,9 @@ -# Yarn -yarn_download_url: "https://yarnpkg.com/{{ yarn_version }}" -yarn_install_destination: "" - # user react_system_user: "react" react_system_group: "www-data" react_system_user_home: "/home/{{ react_system_user }}" - -# NVM -react_nvm_node_version: "{{ react_node_version }}" -react_nvm_nvm_root: "{{ react_system_user_home }}/.nvm" -react_nvm_node_dir: "{{ react_nvm_nvm_root }}/versions/node/{{ react_nvm_node_version }}" -react_nvm_npm_path: "{{ react_node_dir }}/bin/npm" -react_nvm_version: "v0.34.0" +react_local_user_home: "{{ lookup('env', 'HOME') }}" +react_local_user: "{{ lookup('env','USER') }}" # git react_git_url: @@ -22,18 +13,26 @@ react_git_key_filename: "id_ed25519" react_remove_git_key: true # system-wide dependencies -react_system_wide_dependencies: +react_remote_system_wide_dependencies: - yarn + - git +react_local_system_wide_dependencies: + - git react_node_version: 10.x # app +react_remote_js_build: True +react_local_checkout_path: "/tmp/{{ react_local_user }}/reveal" react_env_name: "prod" react_app_name: "{{ react_system_user }}" react_codebase_path: "{{ react_system_user_home }}/app" react_versioned_path: "{{ react_codebase_path }}-versioned" react_checkout_path: "{{ react_versioned_path }}/{{ ansible_date_time['epoch'] }}" react_log_path: "/var/log/{{ react_app_name }}" +react_max_versioned_folders: 10 # app settings react_app_settings: - REACT_APP_WEBSITE_NAME: 'React Example App' \ No newline at end of file + REACT_APP_WEBSITE_NAME: 'React Example App' + GENERATE_SOURCEMAP: "false" + SKIP_PREFLIGHT_CHECK: "true" \ No newline at end of file diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml new file mode 100644 index 0000000..c7c7e13 --- /dev/null +++ b/molecule/default/converge.yml @@ -0,0 +1,16 @@ +--- +- name: Converge + hosts: all + roles: + - role: ansible-react + vars: + react_system_user: "react" + react_system_group: "www-data" + react_system_user_home: "/home/{{ react_system_user }}" + react_node_version: 10.x + react_git_url: "https://github.com/onaio/reveal-frontend" + react_git_version: "v0.6.2-rc1" + react_app_settings: + GENERATE_SOURCEMAP: "false" + SKIP_PREFLIGHT_CHECK: "true" + react_remote_js_build: False \ No newline at end of file diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index 29bdaa8..04bacef 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -3,19 +3,21 @@ dependency: name: galaxy driver: name: docker -lint: - name: yamllint platforms: - - name: ubuntu-16.04 - image: solita/ubuntu-systemd:16.04 + - name: ubuntu-18.04 + image: solita/ubuntu-systemd:18.04 privileged: true command: /sbin/init provisioner: name: ansible - lint: - name: ansible-lint - enabled: false + playbook: + prepare: prepare.yml + options: + verbose: True verifier: name: testinfra - lint: - name: flake8 +lint: | + set -e + yamllint . + ansible-lint + flake8 diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml deleted file mode 100644 index d511125..0000000 --- a/molecule/default/playbook.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -- name: Converge - hosts: all - roles: - - role: ansible-react diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml new file mode 100644 index 0000000..26c38d2 --- /dev/null +++ b/molecule/default/prepare.yml @@ -0,0 +1,13 @@ +--- +- hosts: all + become: true + become_user: root + tasks: + - name: Install prerequisites + apt: + name: " {{ item }} " + update_cache: true + state: present + loop: + - curl + - gpg-agent \ No newline at end of file diff --git a/tasks/cleanup.yml b/tasks/cleanup.yml index 77915b8..94bc8ce 100644 --- a/tasks/cleanup.yml +++ b/tasks/cleanup.yml @@ -2,11 +2,15 @@ - name: Get previous app deploy listing command: ls -tr1 chdir={{ react_versioned_path }} register: versioned_list - changed_when: "versioned_list.stdout_lines|length > 1" + changed_when: false -- name: Remove extra files from app directroy +- name: Remove extra files from app directory + when: "versioned_list.stdout_lines|length > react_max_versioned_folders" file: path: "{{ react_versioned_path }}/{{ versioned_list.stdout_lines[item|int] }}" state: absent - with_sequence: start=0 end={{ versioned_list.stdout_lines|length - 10 }} - ignore_errors: yes \ No newline at end of file + # end will be 0 if number of versioned folders is less than the max defined + with_sequence: > + start=0 + end="{{ versioned_list.stdout_lines|length - react_max_versioned_folders - 1 + if versioned_list.stdout_lines|length > react_max_versioned_folders else 0 }}" diff --git a/tasks/configure.yml b/tasks/configure.yml index 08b8398..d1f7556 100644 --- a/tasks/configure.yml +++ b/tasks/configure.yml @@ -1,24 +1,78 @@ --- -- name: Copy environment variables file - template: - src: env.j2 - dest: "{{ react_checkout_path }}/.env" - mode: 0644 - owner: "{{ react_system_user }}" - group: "{{ react_system_group }}" +- name: configure build locally + block: + - name: Copy environment variables file locally + template: + src: env.j2 + dest: "{{ react_local_checkout_path }}/.env" + mode: 0644 + delegate_to: localhost + become: True + become_user: "{{ react_local_user }}" + + - name: Install Javascript requirements locally + yarn: + path: "{{ react_local_checkout_path }}" + production: false + delegate_to: localhost + become: True + become_user: "{{ react_local_user }}" + + - name: Compile Javascript locally + command: yarn build + args: + chdir: "{{ react_local_checkout_path }}" + delegate_to: localhost + become: True + become_user: "{{ react_local_user }}" + + - name: Remove node_modules before compression + file: + path: "{{ react_local_checkout_path }}/node_modules" + state: absent + delegate_to: localhost + become: True + become_user: "{{ react_local_user }}" + + - name: Compress Build folder locally + archive: + path: "{{ react_local_checkout_path }}/" + dest: "{{ react_local_checkout_path }}.tgz" + delegate_to: localhost + become: True + become_user: "{{ react_local_user }}" + + - name: UnCompress Build folder to remote host + unarchive: + src: "{{ react_local_checkout_path }}.tgz" + dest: "{{ react_checkout_path }}" + become: True + become_user: "{{ react_system_user }}" + when: "not react_remote_js_build|bool" + +- name: configure build remotely + block: + - name: Copy environment variables file + template: + src: env.j2 + dest: "{{ react_checkout_path }}/.env" + mode: 0644 + + - name: Install Javascript requirements + yarn: + path: "{{ react_checkout_path }}" + production: false + become: True + become_user: "{{ react_system_user }}" + + - name: Compile Javascript + command: yarn build + args: + chdir: "{{ react_checkout_path }}" + become: True + become_user: "{{ react_system_user }}" -- name: Install Javascript requirements - yarn: - path: "{{ react_checkout_path }}" - become: True - become_user: "{{ react_system_user }}" - -- name: Compile Javascript - command: yarn build - args: - chdir: "{{ react_checkout_path }}" - become: True - become_user: "{{ react_system_user }}" + when: "react_remote_js_build|bool" - name: Make the new codebase current file: diff --git a/tasks/install.yml b/tasks/install.yml index 794cfe6..be9494d 100644 --- a/tasks/install.yml +++ b/tasks/install.yml @@ -1,26 +1,11 @@ --- -- name: Install NVM - include_role: - name: onai.nvm - delegate_to: 127.0.0.1 - become_user: "{{ react_system_user }}" - vars: - nvm_user: "{{ react_system_user }}" - nvm_group: "{{ react_system_group }}" - nvm_node_version: "{{ react_nvm_node_version }}" - nvm_install_path: "{{ react_nvm_nvm_root }}" - nvm_node_dir: "{{ react_nvm_node_dir }}" - nvm_npm_path: "{{ react_nvm_npm_path }}" - nvm_version: "{{ react_nvm_version }}" - -- name: Install React global packages - npm: - executable: "{{ react_nvm_npm_path }}" - global: true - name: "{{ item }}" - delegate_to: 127.0.0.1 - become_user: "{{ react_system_user }}" - with_items: "{{ react_system_wide_dependencies }}" +- name: Add system user + user: + name: "{{ react_system_user }}" + shell: /bin/bash + group: "{{ react_system_group }}" + append: true + create_home: true - name: Ensure required directories are present file: @@ -28,8 +13,6 @@ owner: "{{ react_system_user }}" group: "{{ react_system_group }}" path: "{{ item }}" - delegate_to: 127.0.0.1 - become_user: "{{ react_system_user }}" when: - item is defined - item is not none @@ -38,42 +21,120 @@ - "{{ react_checkout_path }}" - "{{ react_system_user_home }}/.ssh" +- name: Install react pre-requisites for local deployment + # a pre-requisite here is that the controlling machine has node and yarn installed + block: + - name: Install system-wide dependencies + apt: + name: "{{ react_local_system_wide_dependencies }}" + state: present + update_cache: true + cache_valid_time: 600 -- name: Copy git key - copy: - content: "{{ react_git_key }}" - dest: "{{ react_system_user_home }}/.ssh/{{ react_git_key_filename }}" - owner: "{{ react_system_user }}" - mode: 0600 - no_log: false - register: copied_git_key_file - delegate_to: 127.0.0.1 - become_user: "{{ react_system_user }}" - when: - - react_git_key is defined - - react_git_key is not none + - name: Git clone local + git: + accept_hostkey: "yes" + repo: "{{ react_git_url }}" + dest: "{{ react_local_checkout_path }}" + version: "{{ react_git_version }}" + depth: 1 + force: yes + become: true + delegate_to: localhost + become_user: "{{ react_local_user }}" + when: " not react_remote_js_build|bool" -- name: Git clone react repo - git: - accept_hostkey: true - repo: "{{ react_git_url }}" - dest: "{{ react_checkout_path }}" - version: "{{ react_git_version }}" - depth: 1 - key_file: "{{ copied_git_key_file.dest | default('') }}" - delegate_to: 127.0.0.1 - become_user: "{{ react_system_user }}" - when: - - react_git_key is defined - - react_git_key is not none +- name: Remote Git clone + block: + - name: Detect if Node is installed + command: node --version + register: node_version + changed_when: false + ignore_errors: true -- name: Remove Git Key - file: - state: absent - path: "{{ react_system_user_home }}/.ssh/{{ react_git_key_filename }}" - delegate_to: 127.0.0.1 - become_user: "{{ react_system_user }}" - when: - - react_git_key is defined - - react_git_key is not none - - react_remove_git_key + - name: Download node + shell: > + set -o pipefail && + curl -sL https://deb.nodesource.com/setup_{{ react_node_version }} + | sudo -E bash - + become: true + become_user: root + args: + warn: false + executable: /bin/bash + when: node_version.rc != 0 + + - name: Add yarn apt key to keyring + apt_key: + url: https://dl.yarnpkg.com/debian/pubkey.gpg + state: present + + - name: Add yarn to sources + lineinfile: + create: true + line: "deb https://dl.yarnpkg.com/debian/ stable main" + path: /etc/apt/sources.list.d/yarn.list + regexp: "deb https://dl.yarnpkg.com/debian/ stable main" + state: present + become: true + become_user: root + + - name: Update apt cache + apt: + update_cache: "true" + + - name: Install system-wide dependencies + apt: + name: "{{ react_remote_system_wide_dependencies }}" + state: present + update_cache: true + cache_valid_time: 600 + + - name: Git clone without key + git: + accept_hostkey: "yes" + repo: "{{ react_git_url }}" + dest: "{{ react_checkout_path }}" + version: "{{ react_git_version }}" + depth: 1 + become: true + become_user: "{{ react_system_user }}" + when: + - react_git_key is not defined or react_git_key is none + + - name: Copy git key + copy: + content: "{{ react_git_key }}" + dest: "{{ react_system_user_home }}/.ssh/{{ react_git_key_filename }}" + owner: "{{ react_system_user }}" + mode: 0600 + no_log: false + when: + - react_git_key is defined + - react_git_key is not none + + - name: Git clone with key + git: + accept_hostkey: "yes" + repo: "{{ react_git_url }}" + dest: "{{ react_checkout_path }}" + version: "{{ react_git_version }}" + depth: 1 + key_file: "{{ react_system_user_home }}/.ssh/{{ react_git_key_filename }}" + become: true + become_user: "{{ react_system_user }}" + when: + - react_git_key is defined + - react_git_key is not none + + - name: Remove Git Key + file: + state: absent + path: "{{ react_system_user_home }}/.ssh/{{ react_git_key_filename }}" + become: true + become_user: "{{ react_system_user }}" + when: + - react_git_key is defined + - react_git_key is not none + - react_remove_git_key + when: "react_remote_js_build|bool" diff --git a/tasks/main.yml b/tasks/main.yml index b7af77d..3011c05 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,5 +1,5 @@ --- -- name: Install react app +- name: Install React app using local build include_tasks: install.yml tags: - install diff --git a/tests/test.yml b/tests/test.yml index 3adf0fb..c49ac2d 100644 --- a/tests/test.yml +++ b/tests/test.yml @@ -7,12 +7,12 @@ test -e /usr/bin/python || \ (apt -y update && apt install -y python-minimal) register: output - changed_when: output.stdout|trim() != "" + changed_when: output.stdout|trim()|bool - name: Install sudo if not there raw: | test -e /usr/bin/sudo || apt install -y sudo register: output - changed_when: output.stdout|trim() != "" + changed_when: output.stdout|trim()|bool gather_facts: False become: True @@ -21,12 +21,14 @@ vars: react_system_user: "react_example_app" react_node_version: 10.x - react_git_url: "https://github.com/onaio/kaznet-frontend" - react_git_version: "v1.0.4" + react_git_url: "https://github.com/onaio/kaznet-frontend.git" + react_git_version: "v0.0.1" react_app_settings: REACT_APP_WEBSITE_NAME: 'Example App' + GENERATE_SOURCEMAP: "false" + SKIP_PREFLIGHT_CHECK: "true" SOMETHING_ELSE: "you can put anything here" gather_facts: True become: True roles: - - role: ../.. \ No newline at end of file + - role: ../..