Skip to content

Running playbooks

Nothing deploys from CI. GitHub Actions is a pull-request gate only — lint, secret hygiene, skill portability. Everything that touches an environment runs through ansible-playbook, either wrapped by a skill or as an AAP job template.

That is deliberate: keeping deploys out of CI means no runner ever needs the vault password, and there is no second copy of it in GitHub Environment secrets (#7).


Running a phase

ansible-galaxy collection install -r collections/requirements.yml

ansible-playbook playbooks/setup.yml \
  -i inventory --limit sandbox -e target_env=sandbox \
  --vault-id sales.demos@~/secrets/.vault_pass_sales_demos

--vault-id is required — credentials come from the vault-encrypted playbooks/group_vars/all/secrets.yml. Without it the run fails with "Attempting to decrypt but no vault secrets found".

--limit selects the environment and is mandatory. Playbooks target hosts: aap, so without a limit they match every environment at once — they assert on that and fail closed rather than configuring two environments in one run. Adding -e target_env=<env> makes the play verify the inventory resolved to the environment you meant.


Applying the AAP configuration

Always run validate.yml first; it is the same play in check mode.

ansible-playbook playbooks/validate.yml --check -i inventory --limit sandbox \
  -e target_env=sandbox --vault-id sales.demos@~/secrets/.vault_pass_sales_demos

ansible-playbook playbooks/config.yml -i inventory --limit sandbox \
  -e target_env=sandbox --vault-id sales.demos@~/secrets/.vault_pass_sales_demos

validate.yml needs --check and refuses to run without it

A play-level check_mode: true sets the task's check mode but leaves the ansible_check_mode variable False, and infra.aap_configuration's entire check-mode handling keys off that variable (#173).

config.yml reports changed on every run. AAP returns SUBSCRIPTIONS_CLIENT_SECRET as $encrypted$ and never in the clear, so the role cannot compare desired against actual and rewrites it each time. That is the platform refusing to hand back a secret, not drift.


Verify it in the EE

That command runs on your laptop, against ~/.ansible/collections and your system python. An AAP job template runs the same playbook inside sales-demos-ee, against whatever that image baked in. Two dependency sets, and only one of them is what production uses.

Nothing else can tell them apart — CI executes nothing, so a local run is the only pre-merge verification and by default it verifies the wrong one. Before a playbook change merges, run it in the image as well:

utilities/run-in-ee.sh playbooks/probe_env.yml \
  -i inventory --limit sandbox -e target_env=sandbox \
  --vault-id sales.demos@~/secrets/.vault_pass_sales_demos

Everything after the playbook is byte-identical to the ansible-playbook command above. The wrapper adds ansible-navigator, the right image, and two read-only mounts; it changes none of your arguments. ~/ paths resolve inside the container because the mounts are placed where the container's home is.

Add --with-hub-token for config.yml, validate.yml, setup.yml, sync_hub.yml and curate_hub.yml, which read the Red Hat offline token from ~/.ansible.cfg. The wrapper refuses rather than warns if you forget — without the mount the ini lookup raises (Invalid filename: 'None') rather than returning an empty string.

This is a verification path, not a replacement: ansible-playbook stays the everyday command. /sales-demos-verify-ee walks the whole thing.

It has already earned it. #122 (a hijacked python interpreter) and #173 (validate.yml failing on the EE's older ansible-core) were both invisible to CI, to a laptop run, and to build-ee.sh. See Execution environment.


Keep the run log

Phase 0 takes 10–20 minutes. If it fails and the terminal is gone, so is the evidence. Set a log path before running:

export ANSIBLE_LOG_PATH=~/ansible-logs/sales-demos-$(date +%F).log

Logs go to ~/ansible-logs/, outside the repo — it is public, and keeping them out entirely beats relying on an ignore rule.

Do not pipe through tee

In a pipeline the exit status comes from tee, not from ansible-playbook, so a failed run reports success. That is not hypothetical: it caused a real misread during Phase 0, where the harness showed exit 0 for a playbook that had actually failed.