~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

A workflow waits for the checks it runs after holding no job

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:run/after

What changes

A workflow can name others in after, as after: [check, test, web]. The runner files it queued with the rest, then waits for those checks at its commit, by itself, before it asks for a job at all. Once they have all passed or were skipped, it takes its turn as any run does. If one fails or errs it is filed failure without running, and if one is cancelled, cancelled, its log naming which. A name with no check there is not waited for, and the log says so. It reads the checks again as each of its runs ends, and every minute besides. A stop drops a run still waiting, as any run not yet started.

Why

On main at 1b7d479 the deploy and publish-lexicons each waited for the commit's checks in a step, so each held one of prod's two jobs (--jobs 2) for 25 minutes and more. test was queued at 16:23 and started at 17:08, just after publish-lexicons gave up its wait; web started one second after the deploy gave up. Both then failed, "test has not passed", and nothing deployed. A wait in a step always holds a job; only the runner can wait without one.

This pull is the runner alone. The runner deploying it reads workflow files with its own, older parser, which refuses keys it does not know, so deploy.yml and publish-lexicons.yml move to after in a pull of their own once this is deployed: their wait steps go, and the deploy builds once the checks pass rather than while they run.

How it was checked

a_workflow_runs_after_others_holding_no_job (crates/knotless-run/tests/run.rs), with one job: a deploy and a notify filed before test wait without it, so test runs; both run once it passes, the deploy's log saying how long it waited and that nope has no check; both are filed failure when test fails; and at a newer commit, the deploy, kept by its turn on the ref, ends cancelled as its test was, and the notify is cancelled for the newer, as ever. workflow::tests::after covers the key's parsing. The rest is left to CI.

Shortcomings

It waits only for its own runner's checks: one run by another runner counts as absent. A deploy that moves to after no longer builds its image while the checks run, so it goes up a few minutes later, but neither does its build take a job from them.

🤖 Generated with Claude Code

Approved

This adds an after key to workflows. A run with after waits, holding no job, for the named checks at its commit, and only then asks for a turn. It is filed failure or cancelled without running if one of them did not pass. The wake-up is sound: mark_unchanged comes before the reads, so an end that lands mid-read is not missed. Docs, the change file and tests are in place. I found nothing that must change. I did not run the tests or read the check results, and I read only the diff, not the code around it.

Two small things:

  • The /// f's output, or Noneifcancelled first. line that documented until_cancelled now sits above enum Waited, so it reads as Waited's doc. until_cancelled lost its doc. Move the line back.
  • Nothing rejects a cycle, such as a after b and b after a. Both would stay queued with no job until a stop, and a pull waiting on them would never merge. A parse-time check on direct cycles within one file is impossible, since workflows are parsed one file at a time. A note in the docs, or a cap on how long a run waits, would be enough.
crates/knotless-run/src/lib.rsline 4111
/// `f`'s output, or `None` if `cancelled` first.
/// How a run's wait before its steps ended: holding its job; not to run,
/// as [`After::Not`] says; or cancelled.
review.knotless.dev

This line is the doc of until_cancelled, which now sits below Waited. The doc comment now attaches to Waited and until_cancelled has none. Move it back.

Merged as 935d10f