feat: store what a job printed and act on pull requests #7

Merged
day01 merged %!d() commits from %!s() into %!s() 2026-08-07 07:40:01 +00:00
Owner

Two gaps left the control plane unable to stand in for the forge.

Logs

Log lines were parsed and dropped. A run was unobservable: the aggregate knew a job had finished and nobody could see what it did. They are stored now, keyed by (run, job, offset), so a batch a node resends after a broken connection is written once instead of doubling the output — the idempotent reporting the protocol asks for, enforced by the primary key rather than by hoping.

Output travels beside the aggregate rather than through it. A job that prints nothing is not less valid, and a line arriving late does not move the run anywhere, so logs are not events against the run.

Pull requests

Runs now trigger on pull requests too: filtered by the branch the request is aimed at, compiled at the head commit, and closing one starts nothing.

The part worth reviewing. A path filter with nothing to admit does not fire (fires_on in the compiler), and a pull request webhook does not carry the list of files it touches. A workflow filtering on paths: would therefore have silently never run on a pull request, with nothing anywhere saying why. Rather than assume the list is empty, the control plane asks the forge for it through a ChangedFiles port of its own. The test asserts exactly this: the workflow filters on src/**, and the run only exists because the file list was fetched.

Verification

45 tests. The forge stub now answers by what was asked for rather than in a fixed order, which is what caught the interaction between the two features.

fmt, clippy -D warnings, check-architecture.sh, check-rust-loc.sh all pass.

Still missing

Manual runs and schedules — the first needs an API of its own, the second a scheduler; neither is a webhook. The runner still does not speak this protocol, which is the last thing between this and a deployment.

Two gaps left the control plane unable to stand in for the forge. ## Logs Log lines were parsed and dropped. A run was unobservable: the aggregate knew a job had finished and nobody could see what it did. They are stored now, keyed by `(run, job, offset)`, so a batch a node resends after a broken connection is written once instead of doubling the output — the idempotent reporting the protocol asks for, enforced by the primary key rather than by hoping. Output travels beside the aggregate rather than through it. A job that prints nothing is not less valid, and a line arriving late does not move the run anywhere, so logs are not events against the run. ## Pull requests Runs now trigger on pull requests too: filtered by the branch the request is aimed at, compiled at the head commit, and closing one starts nothing. **The part worth reviewing.** A path filter with nothing to admit does not fire (`fires_on` in the compiler), and a pull request webhook does not carry the list of files it touches. A workflow filtering on `paths:` would therefore have silently never run on a pull request, with nothing anywhere saying why. Rather than assume the list is empty, the control plane asks the forge for it through a `ChangedFiles` port of its own. The test asserts exactly this: the workflow filters on `src/**`, and the run only exists because the file list was fetched. ## Verification 45 tests. The forge stub now answers by what was asked for rather than in a fixed order, which is what caught the interaction between the two features. `fmt`, `clippy -D warnings`, `check-architecture.sh`, `check-rust-loc.sh` all pass. ## Still missing Manual runs and schedules — the first needs an API of its own, the second a scheduler; neither is a webhook. The runner still does not speak this protocol, which is the last thing between this and a deployment.
day01 added 1 commit 2026-08-07 07:36:15 +00:00
		Two gaps left the control plane unable to stand in for the forge.

Log lines were parsed and dropped, so a run was unobservable: the aggregate
knew a job had finished and nobody could see what it did. They are stored now,
keyed by the offset the node reported, which makes a resent batch the same fact
twice rather than new output. A node retrying after a broken connection no
longer doubles the log.

Only pushes triggered runs. Pull requests do now, filtered by the branch they
are aimed at and compiled at the head commit, with closing a pull request
starting nothing.

That second part carried a trap worth naming. A path filter with nothing to
admit does not fire, and a pull request webhook does not say which files it
touches — so a workflow filtering on `paths:` would have silently never run,
with nothing anywhere saying why. The files are asked for through a port of
their own instead of being assumed empty.

Output travels beside the aggregate rather than through it: a job that prints
nothing is not less valid, and a line arriving late does not move the run
anywhere.
	
day01 merged commit 854b3cc2dc into %!s() 2026-08-07 07:40:01 +00:00
day01 deleted branch feat/store-the-output-and-act-on-pull-requests 2026-08-07 07:40:01 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: syncode/control#7