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:

```yaml
- 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.

gabrielfortuna
November 29, 2021