Skip to content

actions: orchestrator Tier 1 (serve, event mapper, trigger/promote/finish/check) - #57

Open
calvin-archastro wants to merge 1 commit into
mainfrom
actions/orchestrator
Open

calvin-archastro wants to merge 1 commit into
mainfrom
actions/orchestrator

Conversation

@calvin-archastro

Copy link
Copy Markdown
Contributor

Orchestrator T1.1-T1.3 (Decision D2: Go, calling pail as a subprocess): pail-actions serve --store URL [--replica NAME]. Stateless; any number of replicas.

What it does

  1. Wake (T1.1): runs pail events --branch '*' --prefix actions/ --cursor bucket:actions/cursors/<replica> --safety-poll 10; every line sets a wake flag, plus a 10 s timer (a lapsed lease emits nothing). One tick answers all pending wakes.
  2. Map (T1.1/T1.2): ref lines to push, pull_request (opened/synchronize/reopened/closed from _meta:prs/<n>.json diffs and PR-branch moves) and workflow_dispatch (behind Tier2View, stubbed). GitHub-shaped payloads stored on the run. PR events and pr/* pushes plan the base branch's workflows (D7; the event does not carry the writer, so every pr/* is treated as untrusted). Schedule: not built.
  3. Decide (T1.3): Decide(snapshot, input) is pure, over a snapshot of _actions; passes: trigger, promote, finish (T1.4 adds passes).
    • trigger: runs/<id>, claims/<key>, jobs, numbers/<wf>/<n>, concurrency/<g> CAS, cancels the previous holder when cancel-in-progress.
    • promote: needs met -> queued (or waiting on an environment without a non-actor approval); a need failed -> skipped.
    • finish: all jobs concluded -> run completed/conclusion; run in_progress when a job is.
    • check: completed jobs of the current attempt projected to _checks:<sha>/ci.<job>.json, reconciled every tick.
  4. Commit: one pail put _actions per tick. Written+existed -> --expect, created -> --expect absent, read-only -> identical rewrite with --expect (pail put only accepts --expect on paths it writes). Exit 4 -> re-read, decide again.

Left for T1.4

orchestrator.Tier2View (today: Dispatches, Ack; TODO lists QueuedEntries/Leases/Results) and Pass func(*Decider) in decide.go. No tier2 package here. Leader lease: not done (optimisation).

Contract changes (docs/actions.md, same PR)

  • Run: optional payload; cancel_in_progress is a boolean. Job: job_id; file name is the escaped instance id; static-false if jobs created completed/skipped.
  • Claim key for pull_request reopened/closed gets a /<type> suffix (else a close at the pushed head collides with that push's claim).
  • Concurrency group: ${{ github.* }} filled in, escaped; no serialising for groups without cancel-in-progress.
  • _checks.state mapping; the check commit cannot guard the run (another ref).
  • Event mapping table; crash window between cursor advance and commit loses mapped triggers (cost: re-push); a new cursor triggers every branch head once.

Model vs doc

  • §7.2 "check ... also guards the run" is not implementable: _checks is another ref. The model has one shared state.
  • §7.2 "read, not written -> --expect" is not expressible in pail put; done as identical rewrite.
  • Model has no numbers/, idx/, if-skipped-at-creation, timed_out, run status; all additive. idx/ not written.

Tests

  • decide_test.go (pure): push -> run/jobs/claim/number/group; duplicate event and repeated tick -> no second run; needs chain and gate; failed need skips; finish; cancel-in-progress (mirrors supersedeRun), two replicas racing (mirrors concurrentPushesRun), trigger guards; _checks projection.
  • integration_test.go: real pail on a file:// store (skips without PAIL_BIN/target/release/pail): push tick, repeat/restart, forced conflict between read and commit -> retry, no double trigger, supersede, PR from base workflows.
  • CI actions job now builds pail so these run.

🤖 Generated with Claude Code

…nish/check)

pail-actions serve: pail events as a wake flag, push/pull_request/dispatch
mapping with the base branch's workflows for PRs, a pure decide() over an
_actions snapshot, and one guarded pail put per tick (--expect, --if-absent,
read-only records guarded by an identical rewrite). _checks projection with
reconcile. Tier 2 intents are left behind the Tier2View/Pass seams.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant