Today I Learned

A Zero One initiative

1 post about #ansible

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:

  1. Considers the task as changed if the exit status is 0
  2. Considers the task as failed if exist status is > 1, as 1 means no match, meaning no migrations and therefore not a failure condition.
  3. 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.