feat(demo): one quickstart, three provider modes - #595
Open
behinddwalls wants to merge 1 commit into
Open
Conversation
behinddwalls
force-pushed
the
demo-docs
branch
from
August 14, 2026 21:01
7705b24 to
511826d
Compare
behinddwalls
force-pushed
the
demo-docs
branch
2 times, most recently
from
August 14, 2026 22:52
b8138b7 to
15aeedb
Compare
## Summary ### Why? The repository had two divergent local paths, and the quickstart documented the wrong one. `make local-submitqueue-start` brought up an all-fake stack — fake change provider, fake CI, **noop merger** — and `doc/howto/QUICKSTART.md` (#591) described that. It reached `landed` in seconds with no credentials, but nothing was ever pushed, so it proved the pipeline's choreography and nothing about merging. `make local-provider-start` ran the real thing, but was GitHub-only: it hardcoded the token-requiring overlay, so the credential-free provider configuration that already existed could not be reached by hand at all. `PROVIDER=local` failed at `docker compose up` on a missing `GITHUB_TOKEN`, and would have merged nothing past that, since the overlay it needs bind-mounts a repository the other one has never heard of. Those two are not variants of one thing. Faking every edge and merging into a real repository answer different questions, and calling both "local" is what made them hard to keep apart. Three further confusions came out of reading the result back: - **Two stack families did the same thing.** Once `fake` was a first-class provider, `local-submitqueue-start` and `local-provider-start` were the same run under *different compose project names* — which had already produced a wrong instruction, since `make local-submitqueue-ps` inspects project `submitqueue` and reports "not running" for a stack started as `submitqueue-provider`. - **One document mixed two audiences.** `PROVIDER-E2E.md` opened with a tier table pairing bazel test targets with hand-run demo commands, as though `make e2e-test` and "open a pull request and watch it land" were rungs of one ladder. Automated suites belong to testing, which `TESTING.md` already documents. - **`demo-pr` was named for something two of the three modes do not have.** A fake change is a URI and a git change is a branch; neither is a pull request. ### What? `PROVIDER` now names three modes, and is the only thing that changes between them: | `PROVIDER` | A change is | Landing it | Needs | |---|---|---|---| | `fake` (default) | a URI, and nothing else | reports success without touching a repository | nothing | | `git` | a branch in a bare repository on disk | a real fetch, cherry-pick and push | nothing | | `github` | a real pull request | a real push to a real repository | a repository and a token | **Provider directories.** `demo/provider/local/` becomes `demo/provider/git/` — both old names were "local" — and gains a `demo-queue` entry so the default `QUEUE` works there. It needs its own `checkoutPath`: Runway refuses two queues that share a checkout with differing merger configuration, and `demo-queue` squash-rebases where `e2e-git-queue` rebases. A new `demo/provider/fake/` spells out the all-fake mode rather than leaving it implied by absent configuration. `e2e-git-queue` is untouched, and `make e2e-git-test` is the gate that proves it. **One stack target.** `local-submitqueue-start` takes `PROVIDER` and layers that mode's overlay; `local-provider-start`, `-stop` and `-clean` are gone. One compose project again, so `ps`, `logs`, `stop` and `clean` all describe whatever is running. Which overlay a mode needs is a Makefile map, since it is not something the two config files can express — `github` requires a credential, `git` requires the sandbox mounted, `fake` neither — and a new `docker-compose.fake.yml` covers the third. **One demo document.** `PROVIDER-E2E.md` is merged into `QUICKSTART.md`, which walks all three rungs in order and carries what only that document had: the token permission table, the GitHub configuration, why a landed pull request shows as *Merged*, wiring real GitHub Actions, and the GitHub-specific failure modes. Its provider-neutral operational material — `land-list` / `land-watch`, `SQ_TOKEN`, service logs, `QUEUE_LOG_LEVEL` — moves with it, into the document people read first. No test target is mentioned in any of it. **`make demo-requests`** (was `demo-pr`, in `service/submitqueue/demo/requests`) works without GitHub. `createOne` was the only function that touched the provider; it now describes a change and hands it to a `changeSource`. Three implement it: `fakeSource` (no I/O at all — mints a reproducible `git://` URI), `gitSource` (pushes real branches with the pinned `@git//:git`, serializing its commands because one working tree cannot take concurrent checkouts), and `githubSource` (the REST client, extracted unchanged). `GITHUB_TOKEN` is read only when it is needed. **Folder overlap, made real.** A change writes all of its files into one folder under `demo/`, and states the paths it touched on its change URI (`sq-files=`, beside the existing `sq-fake=`) for the fake change provider to report back. All three profiles then use `pathoverlap` by directory, so a run shows both halves of the queue's behaviour: changes sharing a folder are batched in order and speculate on each other, changes in different folders go out beside each other. How many folders there are is `FOLDERS`, defaulting to a number between five and ten picked per run and printed with the run's opening line. It is the dial on what a run demonstrates: `FOLDERS=1` serializes everything, a number well above `COUNT` keeps everything apart. The previous layout could do neither — it hashed each file's own name into two nested levels of 256, which put a twelve-file run's odds of any collision at roughly one in a thousand and scattered a single change across as many directories as it had files. What changed is the bucket count and what gets hashed, not the naming. **Matching stack lifecycle targets.** `local-submitqueue-stop` did not exist — the only way to stop the stack was `local-stop`, which stops every domain's. It exists now, and `local-submitqueue-clean` removes the git sandbox and the overlay's volumes rather than only the base file's, which is what the documentation already claimed it did. **`tool/gitsandbox`** provisions the bare repository `PROVIDER=git` merges into, idempotently, so a restart keeps whatever landed. **`platform/gitexec`** locates git and strips the ambient environment, so a developer's hooks or signing key cannot fail a demo. Three fixes fell out of getting this to work at all: - Runway's checkout directory moves to a named volume unless a path is given. It is where git clones, cherry-picks and commits, and on macOS a freshly written loose object read back over a bind mount can report `loose object … is corrupt` — which failed the first land against every new stack. The E2E still passes a path and still gets a bind mount. - The Runway image now creates `/var/runway/checkouts`, so a named volume mounted there starts with a mode the service can write. Without it the service failed at boot with `mkdir: permission denied` whenever it ran as a non-root user. - Change URIs are storage keys capped at 255 bytes, so the file marker names one path per directory rather than every file — for a directory-keyed analyzer that is the same set of keys — and drops paths that would not fit rather than truncating one into a different directory. ## Test Plan Every command in the rewritten quickstart was run by hand against a live stack, and the output quoted in it is what it printed. - ✅ `make local-submitqueue-start` (defaults to `fake`) then `make demo-requests COUNT=6` — all six landed - ✅ inspected `batch_dependent` across three runs. `FOLDERS=1` produced a full chain — every batch depending on every later one. `FOLDERS=50` produced four batches with no dependents at all. The default picked eight folders, put two of six changes in the same one, and recorded a dependency between exactly those two and nothing else - ✅ `make local-submitqueue-stop` leaves the sandbox and its data; `make local-submitqueue-clean` removes the sandbox, the volumes and the images, verified by looking for leftovers afterwards - ✅ `PROVIDER=git make local-submitqueue-start` from a clean slate, then `PROVIDER=git make demo-requests` — real branches and multi-file commits, verified with `git -C /tmp/sq-sandbox/sandbox.git log --oneline main` - ✅ `PROVIDER=git make demo-requests STACKED=true` — three changes, exactly one more entry in the target's reflog, so the stack landed atomically - ✅ first land against a brand-new stack, repeatedly, which is the case the named volume fixes - ✅ the 255-byte limit is a real one this hit first: an eight-file change was rejected with `change URI exceeds 255 bytes` before the marker was budgeted. Covered now by a unit test that builds a URI from `changeFilePath` output and asserts both the length and that it still parses - ✅ `make test` (105 targets), `make lint`, `make check-gazelle`, `make check-tidy` - ✅ `make e2e-test` and `make e2e-git-test`, after the rename and again after the compose change `PROVIDER=github` is unchanged in behaviour but needs a token, so it has not been re-run; the GitHub source is the previous code path moved behind the interface. ## Note for reviewers `make local-provider-start` is gone — use `make local-submitqueue-start`, which with no arguments now means `fake` where the old provider target meant GitHub. `make local-stop` still stops every domain's stack; `make local-submitqueue-stop` is the new one that stops only this.
behinddwalls
force-pushed
the
demo-docs
branch
from
August 14, 2026 23:09
15aeedb to
04445d2
Compare
behinddwalls
marked this pull request as ready for review
August 14, 2026 23:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why?
The repository had two divergent local paths, and the quickstart documented the wrong one.
make local-submitqueue-startbrought up an all-fake stack — fake change provider, fake CI, noop merger — anddoc/howto/QUICKSTART.md(#591) described that. It reachedlandedin seconds with no credentials, but nothing was ever pushed, so it proved the pipeline's choreography and nothing about merging.make local-provider-startran the real thing, but was GitHub-only: it hardcoded the token-requiring overlay, so the credential-free provider configuration that already existed could not be reached by hand at all.PROVIDER=localfailed atdocker compose upon a missingGITHUB_TOKEN, and would have merged nothing past that, since the overlay it needs bind-mounts a repository the other one has never heard of.Those two are not variants of one thing. Faking every edge and merging into a real repository answer different questions, and calling both "local" is what made them hard to keep apart.
Three further confusions came out of reading the result back:
fakewas a first-class provider,local-submitqueue-startandlocal-provider-startwere the same run under different compose project names — which had already produced a wrong instruction, sincemake local-submitqueue-psinspects projectsubmitqueueand reports "not running" for a stack started assubmitqueue-provider.PROVIDER-E2E.mdopened with a tier table pairing bazel test targets with hand-run demo commands, as thoughmake e2e-testand "open a pull request and watch it land" were rungs of one ladder. Automated suites belong to testing, whichTESTING.mdalready documents.demo-prwas named for something two of the three modes do not have. A fake change is a URI and a git change is a branch; neither is a pull request.What?
PROVIDERnow names three modes, and is the only thing that changes between them:PROVIDERfake(default)gitgithubProvider directories.
demo/provider/local/becomesdemo/provider/git/— both old names were "local" — and gains ademo-queueentry so the defaultQUEUEworks there. It needs its owncheckoutPath: Runway refuses two queues that share a checkout with differing merger configuration, anddemo-queuesquash-rebases wheree2e-git-queuerebases. A newdemo/provider/fake/spells out the all-fake mode rather than leaving it implied by absent configuration.e2e-git-queueis untouched, andmake e2e-git-testis the gate that proves it.One stack target.
local-submitqueue-starttakesPROVIDERand layers that mode's overlay;local-provider-start,-stopand-cleanare gone. One compose project again, sops,logs,stopandcleanall describe whatever is running. Which overlay a mode needs is a Makefile map, since it is not something the two config files can express —githubrequires a credential,gitrequires the sandbox mounted,fakeneither — and a newdocker-compose.fake.ymlcovers the third.One demo document.
PROVIDER-E2E.mdis merged intoQUICKSTART.md, which walks all three rungs in order and carries what only that document had: the token permission table, the GitHub configuration, why a landed pull request shows as Merged, wiring real GitHub Actions, and the GitHub-specific failure modes. Its provider-neutral operational material —land-list/land-watch,SQ_TOKEN, service logs,QUEUE_LOG_LEVEL— moves with it, into the document people read first. No test target is mentioned in any of it.make demo-requests(wasdemo-pr, inservice/submitqueue/demo/requests) works without GitHub.createOnewas the only function that touched the provider; it now describes a change and hands it to achangeSource. Three implement it:fakeSource(no I/O at all — mints a reproduciblegit://URI),gitSource(pushes real branches with the pinned@git//:git, serializing its commands because one working tree cannot take concurrent checkouts), andgithubSource(the REST client, extracted unchanged).GITHUB_TOKENis read only when it is needed.Folder overlap, made real. A change writes all of its files into one folder under
demo/, and states the paths it touched on its change URI (sq-files=, beside the existingsq-fake=) for the fake change provider to report back. All three profiles then usepathoverlapby directory, so a run shows both halves of the queue's behaviour: changes sharing a folder are batched in order and speculate on each other, changes in different folders go out beside each other.How many folders there are is
FOLDERS, defaulting to a number between five and ten picked per run and printed with the run's opening line. It is the dial on what a run demonstrates:FOLDERS=1serializes everything, a number well aboveCOUNTkeeps everything apart. The previous layout could do neither — it hashed each file's own name into two nested levels of 256, which put a twelve-file run's odds of any collision at roughly one in a thousand and scattered a single change across as many directories as it had files. What changed is the bucket count and what gets hashed, not the naming.Matching stack lifecycle targets.
local-submitqueue-stopdid not exist — the only way to stop the stack waslocal-stop, which stops every domain's. It exists now, andlocal-submitqueue-cleanremoves the git sandbox and the overlay's volumes rather than only the base file's, which is what the documentation already claimed it did.tool/gitsandboxprovisions the bare repositoryPROVIDER=gitmerges into, idempotently, so a restart keeps whatever landed.platform/gitexeclocates git and strips the ambient environment, so a developer's hooks or signing key cannot fail a demo.Three fixes fell out of getting this to work at all:
loose object … is corrupt— which failed the first land against every new stack. The E2E still passes a path and still gets a bind mount./var/runway/checkouts, so a named volume mounted there starts with a mode the service can write. Without it the service failed at boot withmkdir: permission deniedwhenever it ran as a non-root user.Test Plan
Every command in the rewritten quickstart was run by hand against a live stack, and the output quoted in it is what it printed.
make local-submitqueue-start(defaults tofake) thenmake demo-requests COUNT=6— all six landedbatch_dependentacross three runs.FOLDERS=1produced a full chain — every batch depending on every later one.FOLDERS=50produced four batches with no dependents at all. The default picked eight folders, put two of six changes in the same one, and recorded a dependency between exactly those two and nothing elsemake local-submitqueue-stopleaves the sandbox and its data;make local-submitqueue-cleanremoves the sandbox, the volumes and the images, verified by looking for leftovers afterwardsPROVIDER=git make local-submitqueue-startfrom a clean slate, thenPROVIDER=git make demo-requests— real branches and multi-file commits, verified withgit -C /tmp/sq-sandbox/sandbox.git log --oneline mainPROVIDER=git make demo-requests STACKED=true— three changes, exactly one more entry in the target's reflog, so the stack landed atomicallychange URI exceeds 255 bytesbefore the marker was budgeted. Covered now by a unit test that builds a URI fromchangeFilePathoutput and asserts both the length and that it still parsesmake test(105 targets),make lint,make check-gazelle,make check-tidymake e2e-testandmake e2e-git-test, after the rename and again after the compose changePROVIDER=githubis unchanged in behaviour but needs a token, so it has not been re-run; the GitHub source is the previous code path moved behind the interface.Note for reviewers
make local-provider-startis gone — usemake local-submitqueue-start, which with no arguments now meansfakewhere the old provider target meant GitHub.make local-stopstill stops every domain's stack;make local-submitqueue-stopis the new one that stops only this.Issues