| name | deploy-release |
| description | Guide and perform a FULL E-Heza production release for ONE site — build from `main`, deploy to Pantheon Dev, promote Dev → Test → Live, then cut the GitHub release + changelog. Trigger when the user wants to release, ship to production, go live, promote to Test/Live, or generate release notes for a site (rwanda / burundi / somalia). For deploying an arbitrary branch to a multidev/review env instead, use the `deploy-multidev` skill. Drives the safe steps itself and pauses for the interactive or production-affecting commands. |
Full Release (E-Heza → Pantheon, main → Live)
This skill performs a full production release for one single site: build from main, deploy to Pantheon Dev, promote Dev → Test → Live, then cut the GitHub release + changelog. It mirrors the runbook at https://github.com/Gizra/ihangane/wiki/Deployment and the commands in server/RoboFile.php.
Just need to push a branch to a multidev/review env for testing? Use the deploy-multidev skill — this one is production-only and main-only.
Shared reference (site table, RoboFile internals, one-time Pantheon clone setup, troubleshooting): .claude/skills/_deploy-common/deploy-reference.md — read it before running.
Execution model — who runs what
You (Claude) drive every step except the deploy/promote commands — those move code to Dev/Test/Live and need a human to review and confirm.
One site per run. To release several sites, finish this flow, then re-invoke for the next site.
Site → config mapping
Look up the chosen site's EHEZA_SITE, PANTHEON_NAME, and Pantheon clone dir (server/.pantheon-<PANTHEON_NAME>) in the site table in .claude/skills/_deploy-common/deploy-reference.md.
⚠️ Two distinct Burundi sites (vhw, uvl) share EHEZA_SITE=burundi but have different PANTHEON_NAME. Always pin the exact Pantheon site with the user — never assume "burundi".
Step 0 — Gather inputs (ask the user)
This skill always runs the full path (main → Dev → Test → Live). Use AskUserQuestion to collect:
- Target site — Rwanda / Burundi-vhw / Burundi-uvl / Somalia. Resolve to
EHEZA_SITE + PANTHEON_NAME via the shared site table.
- Cut the GitHub release at the end? (yes/no) — the tag + changelog + GitHub release, done once code is on Live.
Confirm the plan back in one line (site, PANTHEON_NAME, full release to Live, release-notes y/n) before proceeding.
Step 1 — Preflight checks (🟢 you run; all must pass before deploying)
Run these and report a ✅/❌ checklist. Stop and surface any ❌ — do not deploy past a failure.
- Config matches the target site. Read
.ddev/config.local.yaml and confirm EHEZA_SITE and PANTHEON_NAME equal the chosen site's values.
- If they don't match: tell the user to fix
.ddev/config.local.yaml (the mandatory restart in Step 2 loads the new values). This is the #1 footgun — wrong PANTHEON_NAME pushes code to the wrong Pantheon site; wrong EHEZA_SITE builds the wrong site's data/config.
main clean & level with origin/main. Step 2 runs git checkout main, so you need not be sitting on main now — but it must be deploy-ready: in sync with the remote and free of tracked changes. The deploy aborts only on tracked changes; untracked files (e.g. .ddev/, server/.pantheon-*) are ignored, so check with -uno (not -sb, which would false-alarm on those):
git fetch origin main --tags
git rev-list --left-right --count main...origin/main
git status -s -uno
- All intended PRs merged into
main. Ask the user to confirm the release content is fully merged (you can show git log --oneline origin/main -5 for context).
- Pantheon clone exists & clean. Confirm
server/.pantheon-<PANTHEON_NAME>/ exists and is clean:
git -C server/.pantheon-<PANTHEON_NAME> status -s -uno
If the directory is missing, point the user to the one-time clone command in the shared reference — they must create it before deploying.
- Terminus authenticated.
ddev auth ssh covers the git push to Pantheon, but the post-deploy/promotion terminus remote:drush (cc all / updb / uli) and fra have separate auth — without it the deploy pushes code and then fails with "You are not logged in", leaving the env on new code with a stale cache/registry:
ddev exec terminus auth:whoami
- If not logged in: run
ddev terminus-auth (logs terminus in from TERMINUS_MACHINE_TOKEN, or ddev terminus-auth <token>). If the token isn't set yet, add TERMINUS_MACHINE_TOKEN to .ddev/config.local.yaml (see shared reference) and ddev restart.
Step 2 — Local prep
- 🟢 You run:
git checkout main && git pull.
- Restart DDEV — always, deciding reinstall first. Ask the user (AskUserQuestion) whether to reinstall the project on this restart — default No:
- No (default): ensure the
post-start hook in .ddev/config.local.yaml is in its default state (only - exec-host: ddev client-install active; everything below commented). No reinstall.
- Yes: uncomment the entire commented
post-start block (see Reinstall-on-restart toggle in the shared reference) so the restart runs site-install + migrations + feature flags for the selected $EHEZA_SITE. Re-comment afterward if future restarts shouldn't reinstall.
Then run ddev restart (local-only and safe to run; the reinstall answer is the confirmation for the destructive local-DB wipe a reinstall performs).
- 🟢 You run:
ddev auth ssh — injects SSH keys so the deploy can push to Pantheon. (Hand to the user only if it prompts for a key passphrase.)
- 🟢 You run:
ddev gulp publish — minified production build of the Elm client. Long (allow several minutes); let it finish before deploying.
Step 3 — Deploy to Dev
🔴 User runs (the one human-review step) — offer it tee'd to a log so you read the outcome yourself:
ddev robo deploy:pantheon 2>&1 | tee /tmp/deploy-dev.log
Tell the user explicitly: at the "Commit changes and deploy?" prompt, review the printed git status of the Pantheon repo and confirm only if the change-set is exactly what they expect. When it returns, Read /tmp/deploy-dev.log to verify the push + auto-run cc all/updb/fra/uli — don't ask for a paste.
What this command does automatically (so you don't double-run it): rsyncs the build into the Pantheon clone, commits + pushes to Pantheon master, then runs on Dev cc all (twice), updb -y, fra -y, cc all, and uli.
Pantheon's master branch = the Dev environment, not production. This step only updates Dev; promotion to Test/Live is Step 5.
Step 4 — Post-deploy / verify (every env you touch)
The robo deploy already ran cc all/updb/fra/cc all/uli itself — confirm in the log. So just sanity-check the env (open the uli login link from the deploy output, smoke-test the app). If the deploy added manual steps (new variables, migrations), run those too.
⚠️ If you promote via the Pantheon dashboard GUI (Test/Live tabs) instead of deploy:pantheon-sync, the robo command never runs, so updb/fra/cc all do NOT run on that env — do them by hand: ddev exec terminus remote:drush <PANTHEON_NAME>.<env> -- updb -y, then -- fra -y, then -- cc all.
Step 5 — Promote Dev → Test → Live
Do these in order, pausing for the user and re-verifying between each. Each deploy:pantheon-sync runs terminus env:deploy then cc all×2 + updb -y + fra -y + cc all + uli on that env.
- 🔴 User runs (tee'd):
ddev robo deploy:pantheon-sync test 2>&1 | tee /tmp/deploy-test.log → Read the log (confirm updb/fra/cc ran) → verify on the Test URL.
- Pause for explicit user go-ahead (this next one hits production).
- 🔴 User runs (tee'd):
ddev robo deploy:pantheon-sync live 2>&1 | tee /tmp/deploy-live.log → Read the log (confirm updb/fra/cc ran) → verify on the Live URL.
(Equivalent GUI path: Pantheon dashboard → Test tab → confirm deploy → Live tab → confirm deploy.)
Step 6 — Cut the GitHub release (after code is on Live, if requested)
Run from the eheza-app repo (origin = TIP-Global-Health/eheza-app).
- 🟢 Find the latest tag (this becomes the previous tag for the changelog):
git fetch --tags origin
git describe --tags --abbrev=0 origin/main
- Decide the next tag with the user: patch bump (
v1.17.1 → v1.17.2) for minor changes, minor bump (→ v1.18.0) for a new feature. Confirm before tagging.
- 🟢 Create & push the new tag:
git tag <new-tag> && git push origin <new-tag>
- 🟢 Generate the changelog — pass the PREVIOUS tag, since
generate:release-notes lists changes since the tag you give it:
ddev robo generate:release-notes <previous-tag>
- 🟢 Draft the release with
gh (or hand the user the GitHub "new release" URL). Use the new tag, target main, title Release <new-number>. The body's first line states the deploy date and sites, e.g. Deployed in production on <Month DD, YYYY> (<sites>), followed by the generator output starting at ## Changelog:
gh release create <new-tag> --target main --title "Release <new-number>" --notes "$(cat <<'EOF'
Deployed in production on <Month DD, YYYY> (<sites>)
<## Changelog ... output>
EOF
)"
Confirm the date and site list with the user before publishing.
Wrap-up
Report what was released: site, PANTHEON_NAME, each env reached (Dev/Test/Live), fra run per env, and the release tag/URL if cut. Note anything skipped or any preflight ❌ that blocked progress.
For deeper details (RoboFile internals, the one-time Pantheon clone setup, troubleshooting preflight failures), see .claude/skills/_deploy-common/deploy-reference.md.