Polling is now the primary, read-only trigger (always-on thread); the /hook
webhook is an optional admin-registered push optimization deduped by comment id.
Authorize commenters via GET /orgs/{owner}/members/{user} (204, read-level) +
optional allowlist, replacing the admin-requiring /collaborators permission
endpoint. Bot never self-registers webhooks. Enroll = POLL_REPOS + tests/<recipe>/.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
3.4 KiB
Markdown
71 lines
3.4 KiB
Markdown
# Enrolling a recipe under cc-ci (D5)
|
|
|
|
Adding a recipe is a small, repeatable, **no-harness-surgery** operation:
|
|
|
|
## 1. Make the recipe available on the mirror
|
|
|
|
Recipes under test live on the private mirror `git.autonomic.zone/recipe-maintainers/<recipe>`,
|
|
synced from upstream `git.coopcloud.tech`. If not yet mirrored, mirror it (abra fetch + push to the
|
|
org) — see the recipe mirror+PR flow (plan §4.1). A recipe may ship its own `tests/` dir in its repo;
|
|
those are discovered and run against the live app (D4 — see below).
|
|
|
|
## 2. Add the per-recipe test tree in this repo
|
|
|
|
```
|
|
tests/<recipe>/
|
|
├── recipe_meta.py # optional per-recipe harness config (see below)
|
|
├── test_install.py # install-stage assertions (health + Playwright)
|
|
├── test_upgrade.py # upgrade-stage assertions (data survives)
|
|
└── test_backup.py # backup→mutate→restore assertions
|
|
```
|
|
|
|
Copy from an existing recipe (e.g. `tests/custom-html/` for a simple app, `tests/keycloak/` for a
|
|
DB-backed one). The shared fixtures live in `tests/conftest.py` + `runner/harness/` — **do not edit
|
|
them to add a recipe**; instead set per-recipe config in `recipe_meta.py`:
|
|
|
|
```python
|
|
HEALTH_PATH = "/realms/master" # path that returns a healthy status (default "/")
|
|
HEALTH_OK = (200,) # acceptable status codes (default 200/301/302)
|
|
DEPLOY_TIMEOUT = 600 # seconds for services to converge (default 600)
|
|
HTTP_TIMEOUT = 600 # seconds for the app to answer (default 300)
|
|
```
|
|
|
|
The test files use the fixtures: `deployed_app` (install), `deployed` (function-scoped), and the
|
|
`harness.lifecycle` helpers (`http_get`, `http_body`, `exec_in_app`, `upgrade_app`, `backup_app`,
|
|
`restore_app`, `previous_version`). The harness forces `LETS_ENCRYPT_ENV=""` (no ACME) and a unique
|
|
short domain per run, and guarantees teardown.
|
|
|
|
## 3. Recipe-local tests (D4)
|
|
|
|
If the recipe's own repo contains `tests/test_*.py`, the runner snapshots them right after fetch and
|
|
runs them against the **live deployment** as a `recipe-local` stage. Contract: those tests receive
|
|
env `CCCI_BASE_URL` (e.g. `https://<app>.ci.commoninternet.net/`) and `CCCI_APP_DOMAIN`.
|
|
|
|
## 4. Add the repo to the bridge poll list
|
|
|
|
The trigger is **polling** (primary): add the repo's full name to the comment-bridge `POLL_REPOS`
|
|
csv (`modules/bridge.nix`) and `nixos-rebuild switch`. The bridge then polls that repo's open PRs
|
|
every 30s and fires a run on a new `!testme` comment from an authorized org member. This needs only
|
|
**read + comment** access — no webhook, no repo-admin.
|
|
|
|
`!testme` on a PR runs install/upgrade/backup + any recipe-local tests, and reports back to the PR.
|
|
|
|
### Optional: lower-latency webhook (admin-registered)
|
|
|
|
Polling already satisfies D1 (<60s). For lower latency an **admin** may *optionally* register a
|
|
Gitea `issue_comment` webhook (the bot does **not** self-register one — that needs repo-admin):
|
|
|
|
- URL `https://ci.commoninternet.net/hook`, content-type `application/json`, event `Issue Comment`,
|
|
secret = the shared webhook HMAC (`secrets/secrets.yaml` → `webhook_hmac`).
|
|
- The Gitea instance must allow the host (admin: add `ci.commoninternet.net` to the
|
|
`[webhook] ALLOWED_HOST_LIST`).
|
|
|
|
The webhook and poller are deduped by comment id, so a comment seen by both fires only once.
|
|
|
|
## Run locally
|
|
|
|
```sh
|
|
RECIPE=<recipe> PR=<n> REF=<sha-or-branch> SRC=recipe-maintainers/<recipe> \
|
|
STAGES=install,upgrade,backup cc-ci-run runner/run_recipe_ci.py
|
|
```
|