From a0f30ac40170f8178d2a3c7517e45bcfa598167e Mon Sep 17 00:00:00 2001 From: Adam Hebden Date: Sat, 17 Apr 2021 17:02:00 +0100 Subject: [PATCH] Symlinking on deploys & Rollback functionality (#8) * Changes glimesh-web role to symlink deploys with states * Moves Glimesh shutdown to last possible place * Removes redundant comment in glimesh-web * Adds quick Ansible script to rollback Glimesh to prev version * Forgot to quote Ansible variable * Adds delegation & deletion to synchronize symlink deploys * Adds checking /opt/glimesh.tv dir exists * Changes deploys to use git hash * Fixed link target by disabling follow * Fixing missed prod build path to synchronize * Fixed bad when indent on delete old dirs * Maybe fixes directory deleting - fully tested in docker --- ansible/roles/glimesh-web/tasks/main.yml | 151 ++++++++++++++++++----- ansible/web-rollback.yml | 34 +++++ 2 files changed, 157 insertions(+), 28 deletions(-) create mode 100644 ansible/web-rollback.yml diff --git a/ansible/roles/glimesh-web/tasks/main.yml b/ansible/roles/glimesh-web/tasks/main.yml index ea25699..7f5b0a4 100644 --- a/ansible/roles/glimesh-web/tasks/main.yml +++ b/ansible/roles/glimesh-web/tasks/main.yml @@ -5,15 +5,15 @@ name: "{{ inventory_hostname }}" - name: Ensure .ssh directory exists. - file: + file: dest: "/root/.ssh" - mode: 0700 - owner: root + mode: 0700 + owner: root state: directory - name: Install ssh key - copy: - src: "glimesh-deploy" + copy: + src: "glimesh-deploy" dest: "/root/.ssh/id_rsa" mode: 0600 owner: root @@ -27,12 +27,12 @@ # - name: install required packages # apt: -# pkg: -# - esl-erlang -# - elixir -# - npm +# pkg: +# - esl-erlang +# - elixir +# - npm # - git -# - openssl +# - openssl # - imagemagick # state: present # update_cache: yes @@ -43,8 +43,10 @@ - name: install rebar command: mix local.rebar --force -- name: ensure /tmp/glimesh.tv exists - file: path=/tmp/glimesh.tv state=directory +- name: ensure tmp build dir exists + file: + path: /tmp/glimesh.tv + state: directory - name: download glimesh.tv git: @@ -62,19 +64,41 @@ chdir: /tmp/glimesh.tv register: glimesh_git_hash -- name: change version +- name: change version lineinfile: path: /tmp/glimesh.tv/mix.exs regexp: '^\s+version: .*$' line: "version: \"0.1.0+{{ glimesh_git_hash.stdout }}\"," +- set_fact: + deploy_dest: "/opt/glimesh.tv-{{ glimesh_git_hash.stdout }}" + +## Check we should deploy + +- name: Get currently deployed hash + stat: + path: /opt/glimesh.tv + follow: no + get_checksum: no + register: current_deploy + +- name: Same version deployed? + pause: + prompt: | + WARNING: Latest version is already deployed. + Pess Enter to continue + delegate_to: localhost + when: current_deploy.stat.exists and current_deploy.stat.lnk_target == deploy_dest + register: same_deploy + +## Build the deploy + - name: install mix dependencies - command: mix do deps.get, deps.compile + command: mix do deps.get, deps.compile args: chdir: /tmp/glimesh.tv environment: MIX_ENV: prod - # when: glimesh.changed - name: install npm asset deps command: npm --prefix ./assets ci --progress=false --no-audit --loglevel=error @@ -95,15 +119,41 @@ # when: glimesh.changed - name: build glimesh.tv - command: mix do compile --force, release --force --overwrite + command: mix do compile --force, release --force --overwrite args: chdir: /tmp/glimesh.tv environment: MIX_ENV: prod # when: glimesh.changed +- name: Ensure new directory exists + file: + path: "{{ deploy_dest }}" + state: directory + owner: nobody + recurse: yes + +- name: Copy newly built files to new host + synchronize: + src: /tmp/glimesh.tv/_build/prod + dest: "{{ deploy_dest }}" + links: yes + delete: yes + delegate_to: "{{ inventory_hostname }}" + +- name: Check permissions + file: + path: "{{ deploy_dest }}" + owner: nobody + recurse: yes + +## Change the service + - name: setup unit file for glimesh.tv - template: src=glimesh.service.j2 dest=/etc/systemd/system/glimesh.service mode=644 + template: + src: glimesh.service.j2 + dest: /etc/systemd/system/glimesh.service + mode: 644 tags: config - name: reload systemd immediately @@ -111,22 +161,20 @@ daemon_reload: yes - name: gracefully shut down old glimesh app - systemd: + systemd: name: glimesh state: stopped -# Copying the file will automatically restart the daemon. -- name: copy built glimesh.tv - command: cp -Rf /tmp/glimesh.tv/_build/prod /opt/glimesh.tv - -- name: permissions +- name: Change the symlink file: - path: /opt/glimesh.tv + src: "{{ deploy_dest }}" + dest: /opt/glimesh.tv + state: link owner: nobody - recurse: yes + force: yes - name: start new glimesh app - systemd: + systemd: name: glimesh state: started @@ -136,5 +184,52 @@ delay: 5 - name: pause to make sure the other node can take over - pause: - seconds: 15 \ No newline at end of file + pause: + seconds: 15 + +- name: Add a symlink to the old deploy for ease of rollback + file: + src: "{{ current_deploy.stat.lnk_target }}" + dest: /opt/glimesh.tv-old + state: link + owner: nobody + force: yes + +- name: Cleanup old directories + block: + - name: Get currently deployed dest + stat: + path: /opt/glimesh.tv + follow: no + get_checksum: no + register: gtv_current + + - name: Get old deployed dest + stat: + path: /opt/glimesh.tv-old + follow: no + get_checksum: no + register: gtv_old + + # Cleanup + - name: Find all deploy folders + find: + paths: /opt + file_type: directory + use_regex: yes + patterns: "^glimesh.tv-([a-zA-Z0-9]+)$" + recurse: no + register: all_deploys + + - name: Delete old directories + file: + path: "{{ item }}" + state: absent + when: + - item != '/opt/glimesh.tv-old' + - gtv_current.stat.exists == False or item != gtv_current.stat.lnk_target + - gtv_old.stat.exists == False or item != gtv_old.stat.lnk_target + with_items: "{{ all_deploys.files | map(attribute='path') | list }}" + + tags: + - cleanup diff --git a/ansible/web-rollback.yml b/ansible/web-rollback.yml new file mode 100644 index 0000000..3d4d9bd --- /dev/null +++ b/ansible/web-rollback.yml @@ -0,0 +1,34 @@ +- name: web + hosts: web + serial: 1 + + tasks: + - name: Get old deployed hash + stat: + path: /opt/glimesh.tv-old + follow: no + get_checksum: no + register: old_deploy + + - name: Change the symlink + file: + src: "{{ old_deploy.stat.lnk_target }}" + dest: /opt/glimesh.tv + state: link + owner: nobody + force: yes + + - name: restart glimesh + systemd: + name: glimesh + daemon_reload: yes + state: restarted + + - name: wait for service to be online + wait_for: + port: 8080 + delay: 5 + + - name: pause to make sure the other node can take over + pause: + seconds: 15