Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 15 additions & 24 deletions doc/howto/QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ Start the stack, put traffic through it, and watch changes land — beginning wi

The stack always runs the same way. What changes is where the changes come from and what landing them does, chosen with `PROVIDER`:

| `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` | A change is | Building it | Landing it | Needs |
|---|---|---|---|---|
| **`fake`** (default) | a URI, and nothing else | instant fake pass | reports success without touching a repository | nothing |
| **`git`** | a branch in a bare repository on disk | instant fake pass | a real fetch, cherry-pick and push | nothing |
| **`github`** | a real pull request | a real GitHub Actions run per batch | a real push to a real repository | a repository, a token, and CI minutes |

They are a ladder, not alternatives: the same commands work on each rung, so you can start with the one that needs nothing and only pay for what you want to see next. Each is a directory of configuration under [`service/submitqueue/demo/provider/`](../../service/submitqueue/demo/provider) — the difference between rungs is two YAML files, not a code path.

The queue's own logic is real on every rung; what changes is how much of the world around it is. Two things are worth knowing before reading a `landed` as more than it is. On `fake` and `git` **the build is faked**, so `landed` means the pipeline ran, not that anything was tested. And on `fake` and `git` the change provider is faked too: it cannot read a repository to see what a change touched, so `make demo-requests` states the paths on the change URI itself (`sq-files=`) for the conflict analyzer to key on. A change submitted by hand on those rungs touches nothing as far as the analyzer can tell, and conflicts with nothing.

## Start the stack

```bash
Expand Down Expand Up @@ -252,9 +254,9 @@ For a **fine-grained** token, grant these repository permissions. Each is here b
| Contents | Read and write | the git merger — clone, fetch, push to the target branch, and force-move each landed change's head branch |
| Pull requests | Read | the change provider reads pull request metadata, and `land -pr` reads the head commit |
| Pull requests | Read **and write** | only for `make demo-requests`, which opens pull requests |
| Actions | Read and write | only if you switch the build runner to GitHub Actions — dispatch a run, poll it, cancel it |
| Actions | Read and write | the build runner — dispatch a run per batch, poll it, cancel it |

A **classic** PAT needs `repo`, plus `workflow` if you use the GitHub Actions build runner.
A **classic** PAT needs `repo` and `workflow`.

Two things people get caught by. Fine-grained tokens must have the repository explicitly selected under "Repository access" — org-owned repositories also need the org to have approved fine-grained tokens at all. And **Contents: Read and write is the one that cannot be reduced**: landing *is* pushing, so a read-only token fails at the last step, after everything else has appeared to work.

Expand Down Expand Up @@ -299,7 +301,7 @@ Worth understanding *why* they show merged, because nothing called an API to clo

`make demo-requests STACKED=true` submits a chain instead, each pull request targeting the previous one's branch. All of them land as one push to `main`, and all of them show as merged.

**Your CI does not run these builds.** Even here the build runner is fake, so a land takes seconds and costs no Actions minutes — GitHub supplies the change metadata and takes the push, and nothing else. That is worth knowing before reading `landed` as "CI passed on the combination", because it did not run. See [Using real CI](#using-real-ci) below.
**These builds are real.** This rung dispatches your workflow once per speculative batch and polls it to completion, so `landed` here means a build of that batch passed — not that a fake said so. It is the only rung where nothing is faked, and the only one that costs you Actions minutes. [Using real CI](#using-real-ci) below covers what the workflow has to accept and why testing the *combination* is the whole point.

### Land an existing pull request

Expand All @@ -323,14 +325,12 @@ The order of `PRS` is the stack order.

### Using real CI

The demo keeps the build runner fake so a land finishes in seconds. Switching to real GitHub Actions takes three things.
This rung runs your workflow for real — `profiles.yaml` already selects the `githubactions` runner. Two things have to be true of the repository you point it at.

**1. The workflow must be dispatchable.** The runner triggers builds with `POST /actions/workflows/{id}/dispatches`, which only works if the workflow declares `workflow_dispatch`. A typical scratch-repo `ci.yml` triggered on `pull_request` alone cannot be dispatched at all — GitHub rejects it. Add the trigger and the inputs the runner sends:
**The workflow must be dispatchable, and must accept the `sq_*` inputs.** The runner triggers builds with `POST /actions/workflows/{id}/dispatches`, which only works if the workflow declares `workflow_dispatch`. A typical scratch-repo `ci.yml` triggered on `pull_request` alone cannot be dispatched at all — GitHub rejects the call:

```yaml
on:
pull_request:
merge_group:
workflow_dispatch:
inputs:
sq_head_uris:
Expand All @@ -347,20 +347,11 @@ on:
required: false
```

**2. Point the runner at it.** Replace the `buildRunner` line for the queue in `profiles.yaml`:

```yaml
buildRunner:
type: githubactions
owner: behinddwalls
repo: sq-demo
workflow: ci.yml # file name or numeric workflow id
ref: main # the branch the workflow definition is read from
```
**And the workflow must apply both input sets**, which is the part that decides whether any of this means anything. A workflow that checks out the pull request and builds it tests *that change alone* — not what a submit queue is for. The point of speculation is the **combination**: `sq_base_uris` are the in-flight changes assumed to land first, `sq_head_uris` is the batch under test on top of them. A workflow that ignores them is green about the wrong thing, and the queue is only exercising its trigger-and-poll loop.

**3. Grant Actions: Read and write** on the token (see the permissions table above).
Two consequences worth planning for. A land now takes as long as the workflow does, so runs are minutes rather than seconds. And every speculation path dispatched is a run: the queue's [build budget](#put-traffic-through-it) is the cap on how many can be in flight at once, and on a metered account it is a spending control as much as a CI one.

One caveat worth understanding before you rely on the result. A workflow that only checks out the pull request tests *that change alone* — which is not what a submit queue is for. The point of speculation is to test the **combination**: `sq_base_uris` are the in-flight changes assumed to land first, and `sq_head_uris` is the batch under test on top of them. Until the workflow actually applies both, a green run says nothing about whether the batch lands cleanly, and the queue is only exercising its trigger-and-poll loop.
`pull_request` is deliberately absent above. With the queue dispatching a run per batch, leaving it on doubles the runs and tests something the queue already covers.

## Make a change fail

Expand Down
30 changes: 18 additions & 12 deletions service/submitqueue/demo/provider/github/profiles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,23 @@ queues:
# detection.
analyzer: {type: pathoverlap, by: directory}

# The build runner is inherited from the defaults above, so every build
# succeeds instantly. A land then completes in seconds, and the demo shows
# the queue and the merge rather than spending its time waiting on CI.
# Real CI. Each speculative batch is a workflow_dispatch, polled to
# completion, so `landed` here means a build of that batch passed rather
# than that a fake said so — this is the one rung where nothing is faked.
#
# To run real CI instead, add the block below. It needs a workflow in the
# target repository that is triggerable by workflow_dispatch and accepts the
# sq_base_uris / sq_head_uris inputs, and a token with the `workflow` scope.
# The cost is honest too: a land takes as long as the workflow does, and
# every speculation path dispatched is Actions minutes spent. Set the build
# budget accordingly — see `speculator: {buildBudget: N}`.
#
# buildRunner:
# type: githubactions
# owner: behinddwalls
# repo: sq-demo
# workflow: submitqueue-validate.yml
# ref: main
# ---- point these at your own scratch repo ----
buildRunner:
type: githubactions
owner: behinddwalls
repo: sq-demo
# File name or numeric id. The workflow must declare workflow_dispatch and
# accept the four sq_* inputs; a workflow triggered only by pull_request
# cannot be dispatched at all and GitHub rejects the call.
workflow: ci.yml
# The branch the workflow definition is read from, not the code under test.
ref: main
# ----------------------------------------------
Loading