Skip to content

Job runner and agent: pipelines run end to end - #5

Merged
KristiforMilchev merged 1 commit into
mainfrom
job-runner
Nov 3, 2026
Merged

KristiforMilchev merged 1 commit into
mainfrom
job-runner

Conversation

@KristiforMilchev

Copy link
Copy Markdown
Contributor

Milestone M1's main goal: a pipeline now runs end to end. The controller schedules jobs, a worker checks out the exact commit, the agent runs the real commands, and the output is stored.

Agent (internal/agent, cmd/agent)

  • Checks out the exact commit and verifies it.
  • Runs steps with bash -e -o pipefail, sh, pwsh or cmd, with a per-step timeout. A timeout gives exit code 124.
  • Masks secrets in output, even when a secret is split across output chunks; tested against every possible split.
  • Kills the whole process tree on cancel or timeout, so background processes can't outlive their step. I checked the tests by breaking this on purpose.
  • Request paths can't leave the work directory, and collecting files doesn't follow symlinks.

Worker kit (pkg/worker)

  • Git mirror per repository: VMs check out from the worker's local copy. Local paths are refused unless explicitly allowed, and tokens are passed through the environment so they don't show up in the process list.
  • Job runner: a fresh VM per job. Infrastructure failures (mirror, VM, agent) are reported as errors and retried elsewhere. Job failures (exit code, denied secret, timeout, missing commit) are reported as failed and not retried.
  • Outbox: updates and logs survive a reconnect. A job stays in the heartbeat until its result is delivered, so its lease can't expire while the result is waiting.
  • worker.Run: the one entry point the worker-* repos call from main.

Controller

  • Job logs are stored per job and deduplicated. They're accepted only from the worker that holds the job. New command: controller run logs <run>.

devworker: try everything on one machine without VMs, with no isolation. The README shows how.

Fixes found along the way

  • Reconnect backoff now starts at 100ms instead of 500ms, so a worker is back well within its lease. A new test caught a job being retried after a short drop.
  • Values containing : in pipeline files, common in run: commands, now get a hint explaining how to quote them.

Tests

  • End-to-end with real commands, a real Git repository and a real agent per job: success with continue-on-error, a failure skipping dependent jobs, a fresh VM per job, a denied secret, cancel, job timeout, a missing commit, and a job surviving a reconnect.
  • Full suite passes 6 times in a row under the race detector.
  • Also run by hand with the real binaries: PostgreSQL → controller serve → devworker join/run → a 3-job matrix pipeline against this repository's own commit. It succeeded, and controller run logs showed the output.

Still missing: stored test reports and artifacts (those steps are skipped with a note), the secrets broker (requests are denied for now), real VM drivers, and Git providers.

🤖 Generated with Claude Code

- internal/agent: checkout of the exact commit, running steps (bash with
  pipefail, sh, pwsh, cmd), secrets masked in output even when split across
  chunks, the whole process tree killed on cancel and timeout, collecting
  files without following symlinks; paths can't leave the work directory
- pkg/worker: Git mirrors (local paths only when allowed; tokens passed
  via the environment), the job runner (fresh VM per job, infrastructure
  errors retried, job failures not), an outbox that carries updates and
  logs across reconnects, and worker.Run for the OS-specific workers
- workertest: optional real agent per fake VM
- Controller: logs stored per job, deduplicated, accepted only from the
  worker holding the job; controller run logs
- cmd/devworker: try it all on one machine without VMs (no isolation)
- Reconnect backoff starts at 100ms so a worker is back within its lease
- Pipeline errors: a hint for values containing ': '
- End-to-end tests with real commands, a real repository and real agents

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KristiforMilchev
KristiforMilchev merged commit 42d2e12 into main Nov 3, 2026
1 check passed
@KristiforMilchev
KristiforMilchev deleted the job-runner branch November 3, 2026 13:59
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