How to check with Ansible if rails must migrate
Running a migration can be a lengthy process which may require app restarts. It’s best to avoid blindly running one just in case and only running them when required.
Using Ansible, we can achieve this with these two tasks:
- name: Check for outstanding migrations
ansible.builtin.shell:
cmd: bundle exec rails db:migrate:status | grep --silent --perl-regex "^\s+down\s+\d+"
chdir: /to/my/app/dir
register: migration_status
changed_when: migration_status.rc == 0
failed_when: migration_status.rc < 1
run_once: true
- name: Run any outstanding migrations
ansible.builtin.shell:
cmd: bundle exec rails db:migrate
chdir: /to/my/app/dir
when: migration_status.rc == 0
notify:
- Some handler that restarts things
The first task runs rails db:migrate:status
and searches for any down
, i.e. outstanding migrations. It registers the return, and does three key things:
- Considers the task as changed if the exit status is 0
- Considers the task as failed if exist status is > 1, as 1 means no match, meaning no migrations and therefore not a failure condition.
- Only runs the task once, so if you have a large inventory, you don’t waste time.
The 2nd task only runs if the first’s rc
is 0, and then notifies a handler to restart the app if needed.