review: file [adversary] A4 (same-recipe concurrent checkout collision); M6 verify in progress
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
17
BACKLOG.md
17
BACKLOG.md
@ -116,3 +116,20 @@ Two single-writer sections (§6.1): Builder edits only `## Build backlog`; Adver
|
||||
remove the `.env` after a confirmed undeploy, or undeploy-by-stack-name as a fallback that
|
||||
doesn't need the `.env`. *Re-test:* run install, kill the process mid-deploy, verify the next
|
||||
run (or janitor) leaves zero residual service/volume/secret. Adversary closes after re-test.
|
||||
|
||||
- [ ] **[adversary] A4 — Concurrent same-recipe runs collide on the shared recipe checkout.**
|
||||
Found by review (M6 verify); to confirm empirically. Per-run isolation is correct for the app
|
||||
**domain/volume/secret** (hashed `<recipe[:4]>-<6hex(recipe|pr|ref)>`), but the recipe *source
|
||||
checkout* is a single shared path `~/.abra/recipes/<recipe>`: `run_recipe_ci.fetch_recipe`
|
||||
does `rm -rf ~/.abra/recipes/<recipe>` then `git clone`+`checkout <ref>`, and abra itself
|
||||
re-checks-out the recipe to a version tag mid-deploy. There is **no per-run abra home
|
||||
(`ABRA_DIR`/`HOME`), no lock, and no Drone concurrency cap** (runner capacity=2). So two
|
||||
concurrent runs of the **same recipe at different refs** (e.g. `!testme` on two PRs of one
|
||||
recipe) race on that dir — one can deploy/test the other's code, or fail mid-fetch. (Benign
|
||||
when both want identical content, which is why an earlier accidental same-recipe overlap
|
||||
didn't visibly break — masking the bug.) This weakens the §6 "two concurrent runs don't
|
||||
collide" guarantee and matters for D10 (6 recipes via real PRs). *Repro:* start two runs of
|
||||
one recipe with different REFs simultaneously; check each deploys its own ref's code (add a
|
||||
per-ref marker) and neither errors mid-fetch. *Fix:* per-run abra home/recipe dir (e.g.
|
||||
`ABRA_DIR=$(mktemp -d)` or `~/.abra-runs/<app>`), or a per-recipe lock, or cap Drone to
|
||||
serialize same-recipe builds. Adversary confirms + closes after re-test.
|
||||
|
||||
20
REVIEW.md
20
REVIEW.md
@ -169,3 +169,23 @@ and not softened):
|
||||
reused per stage).
|
||||
|
||||
Verdict: **M5 PASS.**
|
||||
|
||||
## M6 — Recipe-local tests + second recipe: VERIFICATION IN PROGRESS (no verdict yet) @2026-05-27T01:48Z
|
||||
|
||||
M6 CLAIMED. Host has been continuously busy (Builder M6.5 ramp), so deploy-based checks are
|
||||
deferred to an idle window; static + evidence review so far:
|
||||
- **custom-html 3-stage:** already verified cold by me (see M5 PASS) — green + clean teardown.
|
||||
- **D4 recipe-local discovery — code genuine:** `run_recipe_ci.snapshot_recipe_tests` copies the
|
||||
recipe-shipped `tests/` before abra re-checkouts to a version tag, then `run_recipe_local` deploys
|
||||
the app and runs those tests against the LIVE app via `CCCI_BASE_URL`/`CCCI_APP_DOMAIN`, merged as
|
||||
a separate stage with guaranteed teardown. Demo branch `recipe-maintainers/custom-html@
|
||||
ci/d4-recipe-local` confirmed to ship `tests/test_recipe_local.py` (Gitea API). Will run it cold to
|
||||
confirm the stage executes+passes.
|
||||
- **keycloak (#2) install — test genuine:** `/realms/master` 200 health + real Playwright admin
|
||||
console login (waits for the username field). `recipe_meta.py` (HEALTH_PATH/timeouts) confirms D5
|
||||
"no harness surgery". Empirical keycloak reproduction deferred (heavy deploy; idle window).
|
||||
- **Filed [adversary] A4** (concurrency): same-recipe concurrent runs share `~/.abra/recipes/<recipe>`
|
||||
with no isolation/lock/concurrency-cap — a collision vector for the §6 concurrency check; to
|
||||
confirm empirically.
|
||||
|
||||
Pending for idle host: cold D4 run, keycloak reproduce, A2/A3 kill-probe re-test, A4 concurrency test.
|
||||
|
||||
Reference in New Issue
Block a user