Skip to main content
RunBook Academy

← All checklists in Ansible

Before deploymentchange-management

Checklist: Promoting a change to production

20 items ·14 critical ·5 warn ·1 info

Run this when a change is proposed for production, before the change record is approved - hours or days ahead of the run, not minutes. It is the wrapper around the change; the pre-execution checklist is the gate at the keyboard. Both exist because they are answered by different people at different times.

Why so many items have no command

Nine of the twenty items here have no command, and that is the point. This checklist is mostly about things a machine cannot observe: whether an approver looked at the change, whether the on-call engineer knows, whether the abort criteria were agreed before anybody had a reason to want to continue.

Where a command exists it is doing one of two things: confirming a precondition against the real hosts, or producing a number for the record. Neither replaces the attestation - “backups confirmed” needs a person willing to put their name next to it, and the find command only tells you a file exists.

Access this needs

Six commands connect to the target hosts: ping, service_facts, setup, find, and the systemctl list-timers invocation. All of them read; none changes anything. service_facts and setup are fact-gathering modules and find only walks a directory. The command module invocation is the one to look at twice - systemctl list-timers is read-only, but the command module will run whatever you give it, so do not adapt that item casually.

The rest are local: the controller clock, the Git revision, the collection list, the configuration dump.

Where the evidence goes

Everything here belongs in the change record, with a timestamp per item. The freshness item is not decoration: a reviewer reading the record afterwards needs to know whether “targets healthy” was checked five minutes before the run or the previous afternoon, because those are different claims and they look identical without a time next to them.

Sign-off

  • Change owner: _____________ Date: ___________
  • Approver: _________________ Date: ___________
  • On-call briefed by: _______ Time: ___________

Critical14 items

  1. date -u '+%Y-%m-%d %H:%M:%S UTC'
  2. echo "promoting: $(git rev-parse HEAD)"
    echo "staged:    <hash recorded from the staging run>"
  3. ansible --version | head -1; ansible-galaxy collection list
  4. ansible-inventory -i inventories/production --list | jq -r 'to_entries[] | select(.key != "_meta" and .value.hosts) | "\(.key)\t\(.value.hosts | length)"'
  5. ansible-config dump | grep -E '^DEFAULT_VAULT_IDENTITY_LIST|^DEFAULT_VAULT_ID_MATCH'
  6. ansible -i inventories/production web -m ansible.builtin.ping --one-line | grep -v 'SUCCESS'
  7. ansible -i inventories/production web -m ansible.builtin.service_facts --one-line | grep -v 'SUCCESS'
  8. ansible -i inventories/production web -m ansible.builtin.find -a 'paths=/var/backups patterns=app-*.tar.gz age=-1d' --one-line | grep -v '"matched": [1-9]'
  9. ansible -i inventories/production web -m ansible.builtin.setup -a 'filter=ansible_memfree_mb,ansible_mounts' --one-line | grep -v 'SUCCESS'

Warning5 items

  1. ansible -i inventories/production web -m ansible.builtin.command -a 'systemctl list-timers --all --no-pager' --one-line
  2. ansible-config dump | grep '^DEFAULT_LOG_PATH'; id -un

Info1 item