9.4 KiB
Finalization Runbook
Everything that can be done without your credentials is done. This file is the copy-paste path through what remains. Work top to bottom.
Note: written while another agent (Codex) was editing files in this repo. The line numbers in §5 are a snapshot — re-run the grep before trusting them.
0. What is already verified (no need to redo)
Verified locally on 2026-07-26 with Docker 29.5.3 (linux/amd64):
| Item | Result |
|---|---|
docker build Q1 (q1-deploy-monitor/app) |
builds clean → ghaymah-api:latest, 249 MB |
docker build Q5 (q5-mithal-dashboard) |
builds clean → mithal-monitor:latest, 200 MB |
| Q1 container | /health → 200 {"status":"ok","uptime_s":11.254,...}; /metrics counter increments; Docker healthcheck reports healthy |
| Q5 container | start.sh launches collector + static server; collector wrote a real record inside the container (up:true, code:200, ssl_days_left:50); dashboard rendered at /index.html with badge, uptime tile, TLS card, chart and table; healthcheck healthy |
| Q1 monitor | up/down transitions, ALERT after exactly 3 consecutive failures, --once exit codes |
| Q5 collector | live measurements against mithal.space; unreachable-host run records all-nulls without crashing |
Both images are already built on this machine. You can go straight to docker push.
1. Set your Docker Hub username once
Everything below reuses this. Run in PowerShell:
$DH = "yourdockerhubusername" # <-- edit this line only
2. Push both images (10 min)
docker login
docker tag ghaymah-api:latest "docker.io/$DH/ghaymah-api:latest"
docker tag mithal-monitor:latest "docker.io/$DH/mithal-monitor:latest"
docker push "docker.io/$DH/ghaymah-api:latest"
docker push "docker.io/$DH/mithal-monitor:latest"
Then, on hub.docker.com, confirm both repositories are Public — Ghaymah pulls them anonymously. A private repo is the single most common cause of a deployment that never leaves "pulling".
3. Deploy both apps on Ghaymah (30 min)
Same form twice:
| Field | Q1 | Q5 |
|---|---|---|
| Container Image URL | docker.io/<DH>/ghaymah-api:latest |
docker.io/<DH>/mithal-monitor:latest |
| Application Name | ghaymah-api |
mithal-monitor |
| Port Number | 8080 |
8080 |
| Public Access | enabled | enabled |
| Env vars (optional) | APP_NAME=ghaymah-api, APP_VERSION=1.0.0 |
INTERVAL_S=60 |
Record both public URLs — you need them in §5.
Verify immediately:
curl.exe -f "<Q1_URL>/health"
Then open <Q5_URL>/index.html in a browser (it will show 1–2 checks at first).
Start the Q1 monitor the moment Q1 is live
This is the long pole — the Q1 dashboard is only convincing with hours of history. Leave this window open for the rest of the assessment:
$env:APP_URL="<Q1_URL>"; python q1-deploy-monitor\monitor\monitor.py
Q5 needs nothing — its collector runs inside the deployed container.
4. Resolve the Q3 blocker (the CLI question) — 20 min
What I established from public sources (so you don't repeat the search):
- Install:
curl -sSL https://cli.ghaymah.systems/install.sh | bash - The installer downloads
gy-{platform}-{arch}fromhttps://cli.ghaymah.systems(override withSERVER_URL) and installs to$HOME/ghaymah/bin/gy. - The only env var the installer honours is
SERVER_URL. No token env var exists in the installer. - Documented commands:
gy auth login(browser-based),gy auth status,gy resource project get,gy resource project create --set .name=my-new-project,gy resource application init --project-id <ID>,gy resource application launch,gy resource application logs. .ghaymah.jsonfields:id,name,projectId,ports[].expose/.number,publicAccess.enabled/.domain,resourceTier,dockerFileName,env,domains.- Nothing public documents non-interactive auth, a registry hostname, or updating
an application to an external image tag.
/docs/clireturns 404; the changelog and product pages list "container registry" and "CI/CD" as features with no syntax.
Run these three commands after gy auth login — they are the fastest way to
settle it, and their output is what I need to finish the workflow:
gy auth login --help
gy --help
gy resource application --help
Look specifically for: a --token / --api-key flag, any GHAYMAH_* env var, a
gy resource application update/set-image subcommand, or a gy registry group.
Also check the authenticated dashboard for an API tokens / service accounts
page and for the registry hostname.
Paste whatever those print back to me and I will finish deploy.yml,
scripts/ghaymah_deploy.sh and CICD.md in one pass.
If it turns out no non-interactive path exists, that is a legitimate finding — the honest write-up (deploy job documented, adapter exits 78 rather than faking success, manual promotion step described) scores better than invented syntax. Do not invent a command to make the pipeline look green.
5. Replace the placeholders
Snapshot of what is unfilled (re-run the grep after Codex finishes):
Select-String -Path (Get-ChildItem -Recurse -Include *.md,*.yml,*.sh -Path . | Where-Object FullName -notmatch '\\\.git\\') -Pattern 'MY_DOCKERHUB_USER|the public URL Ghaymah assigns|<!-- VERIFY|<PROJECT_ID>'
| Placeholder | Where | Replace with |
|---|---|---|
<MY_DOCKERHUB_USER> |
q1-deploy-monitor/README.md (5×), q5-mithal-dashboard/README.md (5×) |
your Docker Hub user |
<the public URL Ghaymah assigns> |
q1-deploy-monitor/README.md (6×), q5-mithal-dashboard/README.md (1×) |
the two live URLs |
<PROJECT_ID> |
q3-cicd/CICD.md:91, root README.md:22 |
your Ghaymah project id |
<!-- VERIFY --> × 5 |
q2-postmortem/POSTMORTEM.md:133, q3-cicd/CICD.md:111,125, q4-scalability/SCALABILITY.md:108,112 |
see §6 |
Bulk replacement (run after Codex is done, from the repo root):
$DH="yourdockerhubusername"; $Q1="https://your-q1-url"; $Q5="https://your-q5-url"
Get-ChildItem -Recurse -Include *.md -File | Where-Object FullName -notmatch '\\\.git\\' | ForEach-Object {
(Get-Content $_.FullName -Raw) `
-replace '<MY_DOCKERHUB_USER>', $DH `
-replace '<the public URL Ghaymah assigns>', $Q1 |
Set-Content $_.FullName -Encoding utf8
}
That sets the Q1 URL everywhere; then fix the single Q5 occurrence in
q5-mithal-dashboard/README.md by hand (it is the /index.html line).
6. The five remaining VERIFY areas
Each needs one look at the authenticated dashboard. What to check, and what to do with the answer:
| # | File | Question to answer in the dashboard |
|---|---|---|
| 1 | q2-postmortem/POSTMORTEM.md:133 |
Does Ghaymah show per-container memory/CPU metrics, restart counts, and configurable alert rules + notification channels? Screenshot the monitoring page. |
| 2 | q3-cicd/CICD.md:111 |
Non-interactive auth for CI — settled by §4. |
| 3 | q3-cicd/CICD.md:125 |
External-image update syntax — settled by §4. |
| 4 | q4-scalability/SCALABILITY.md:108 |
Block Storage: snapshots supported? retention/encryption/restore? |
| 5 | q4-scalability/SCALABILITY.md:112 |
Block Storage: size limits, resize, IOPS/throughput, attachment/access modes, zone binding. |
Rule for all five: if the platform confirms it, state it plainly and drop the
marker. If the platform does not expose it, rewrite the sentence to describe
the general requirement and say the platform-specific limits were not documented
at the time of writing — then drop the marker. No VERIFY string may survive in
the submitted repo.
7. Screenshots to capture
Save under docs/screenshots/ with these names so the READMEs can link them:
q1-service-running.png— the Ghaymah dashboard showing the running Q1 appq1-health-response.png— browser or terminal showing/health→ 200 JSONq1-monitor-dashboard.png— the Q1 dashboard with a populated latency chartq3-approval-gate.png— the GitHub Actions run paused on the production reviewer promptq5-live-dashboard.png— the deployed Q5 dashboard with ≥ 1 h of historyghaymah-monitoring.png— optional, supports the Q2 detection section
8. GitHub, secrets, pipeline
- Create the repo, add the remote, push.
- Settings → Secrets and variables → Actions: add the secrets named in
.github/workflows/deploy.yml(Docker Hub user/token, plus whatever §4 settles for Ghaymah). - Settings → Environments →
production→ Required reviewers: yourself. - Run the workflow → let it pause → screenshot the gate → approve.
Decide before pushing whether PLAN.md, PROMPTS.md and CHECKLIST.md belong in
the submission. They document your internal agent workflow; graders don't need
them. Either delete them or list them in .gitignore.
9. Final gate before submitting
Select-String -Path (Get-ChildItem -Recurse -Include *.md,*.yml,*.sh -File | Where-Object FullName -notmatch '\\\.git\\') -Pattern 'VERIFY|MY_DOCKERHUB_USER|the public URL Ghaymah assigns'
Must return nothing. Then:
- Both apps reachable at their public URLs
- Q1 dashboard chart has hours of points; Q5 uptime tile computed over real 24 h data
- All screenshots committed and linked from the root README
- Every numbered sub-requirement of Q1–Q5 ticked (CHECKLIST.md §7.1)
- Final commit pushed