Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and `merge --ff-only` refuses while tracked paths are dirty. Discard is not available here (workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed. - `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new prose — the commit exists so the trunk merge can proceed. - `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat owns (AGENTS.md § Live-sync tiers). `ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the inert all-zero AWS example id — and they appear inside the two skill pages that teach that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal dies with this landing. No `--no-verify` was used: the gate ran and its verdict is recorded here. Refs #61
37 lines
2.5 KiB
Markdown
37 lines
2.5 KiB
Markdown
---
|
|
name: new-fleet-service-checklist
|
|
description: "Add a new deployable service to serverAppConfigs: the four registration touch-points (two allowlists, planner, router) whose drift breaks the first-ever deploy."
|
|
---
|
|
|
|
# Adding a new service to the serverAppConfigs deployer
|
|
|
|
A new `--service <name>` target must be registered in **four** files or the first deploy fails at a gate. Two fleet services (cadvisor, gpu-exporter) shipped with the client gate missed within a day of each other; the failure mode is `Service 'X' is not deployed on <target>` from `deploy.sh`, exit 2 — before SSH.
|
|
|
|
## The four touch-points (per target host)
|
|
|
|
1. `scripts/deploy.sh` → `valid_service()` case: add `<target>:<svc>`. **Client gate** — the one people forget.
|
|
2. `scripts/deploy-remote.sh` → `service_is_allowed()` case: add `<target>:<svc>`, **and** the dispatcher `case` branch `<svc>) deploy_<svc> ;;`.
|
|
3. `scripts/deploy-plan.py`: the name in the target's service set (`DANKCLAW_SERVICES` / `DANKSERVER_SERVICES`) + `SERVICE_ORDER`, plus a path map so edits to the service's own files select it (for `scripts/<svc>.*` host processes, map the exact filenames like the signal-relay/gpu-exporter maps do).
|
|
4. `scripts/test-changed.sh`: route the service's files to its seam, else focused test runs skip it (full `tests/run.sh` still covers).
|
|
|
|
Sanctioned exception: `dankclaw:searxng-network` is client-only (network unit, no remote handler) — the drift test exempts it.
|
|
|
|
## Enforcement + local verification
|
|
|
|
`tests/deployment_flow.bats` test "the client and remote allowlists agree per target" diffs the two extracted lists. Verify before pushing:
|
|
|
|
```bash
|
|
grep -oE 'dank(claw|server):[a-z0-9-]+' <(sed -n '/^valid_service()/,/^}/p' scripts/deploy.sh) \
|
|
| grep -v dankclaw:searxng-network | sort -u > /tmp/cli
|
|
grep -oE 'dank(claw|server):[a-z0-9-]+' <(sed -n '/^service_is_allowed()/,/^}/p' scripts/deploy-remote.sh) \
|
|
| sort -u > /tmp/rem
|
|
diff /tmp/cli /tmp/rem # must be empty
|
|
```
|
|
|
|
Also: a `# comment` after a trailing `\` inside a bash `case` pattern list **breaks line continuation** (syntax error) — annotate on its own line above.
|
|
|
|
## Gotchas
|
|
|
|
- Merge ≠ deploy: `deploy.sh <host> --service <svc>` must still be run per host; a merged service is dead code until then (GPU stats "not showing" was exactly this).
|
|
- `deploy.sh` refuses to run anywhere but a clean `main` checkout: the canonical dev checkout is `/home/blank/Projects/serverAppConfig` (not the session `~/.omp/wt/...` worktree, not the build worktree).
|