ci(nightly): add nightly build channel tracking latest agent CLIs - #1519
Conversation
Add a scheduled nightly image build that publishes drop-in images per agent variant carrying each vendor's latest CLI. Unlike the release and pre-beta lanes — which pin every CLI version (and SHA256) as a build ARG and therefore republish the same CLI on every rebuild — this lane resolves each vendor's latest version each morning and passes it as a build-arg override to Dockerfile.package. Nightly is a drop-in channel with no compatibility guarantee. It favors freshness over cohort atomicity: variants build independently (fail-fast: false), so one vendor breaking their latest does not hold back the rest. Tags: nightly-<variant> (moving) plus nightly-YYYYMMDD-<run-id>-<variant> (immutable rollback). native and agentcore are excluded — they carry no agent CLI to freshen. To let SHA-pinned variants (kiro, grok, devin, antigravity) move to an unknown-ahead-of-time version, Dockerfile.package now skips the sha256sum check when the SHA build-arg is empty. This is inert for the release/pre-beta path, which still passes its pinned SHAs and stays verified; devin and hermes resolve their SHA from the vendor and keep the check enabled. antigravity's AGY_VERSION becomes an ARG (re-exported as ENV) so it is build-arg overridable.
c48e5d9 to
0e2ddd0
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Important
CHANGES REQUESTED
Consolidated review: #1519 (comment)
Address independent review findings: - Resolve each vendor's latest version once per variant in a dedicated resolve job (matrix over variants only) instead of independently in each variant×arch build leg. amd64 and arm64 now consume the same resolved version via a per-variant artifact, so a vendor publishing mid-run can no longer produce a mixed multi-arch manifest. devin now resolves both per-arch sha256 digests up front. - Surface the resolved CLI version in the tag job step summary. - Hash the hermes installer via the authenticated GitHub Contents API (raw+json) for the resolved commit, matching the release fetch and dodging shared-runner 429s on raw.githubusercontent.com. - Harden the dispatch variant allowlist check with grep -qF.
This comment has been minimized.
This comment has been minimized.
- F1: drop pi from the nightly matrix. Its package/unified target sets OPENAB_AGENT_COMMAND=openab-agent but never ships that binary (a pre-existing bug in all lanes), so nightly-pi would publish a runtime-broken image. Excluded until the pi target is fixed. - F2: let each variant publish independently after a peer failure. tag now runs with always() && !cancelled() and tags only when its own two digests are present; a failed build leg fails just that variant's tag. - F3: restrict canonical publication to the default branch. build and tag gate on github.ref == refs/heads/main, so a workflow_dispatch from a feature branch validates (matrix/compile/resolve) without publishing. - F5: append GITHUB_RUN_ATTEMPT to the immutable rollback tag so a re-run (which re-resolves mutable versions) cannot move a tag documented immutable. - F7: parse the manual variant input once into a normalized, validated, de-duplicated list; reject empty elements and duplicates before the matrix JSON is produced. - F8: surface the effective antigravity version as an image label (dev.openab.agy.version) so inspect reflects the installed version, while the parity-checked ENV AGY_VERSION stays pinned. F4 (resolve once per variant) and F6 (devin digest format validation) were already addressed in the prior commit.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Important
CHANGES REQUESTED
Consolidated review: #1519 (comment)
- allow build matrix children to run after a peer resolver failure while still requiring the shared matrix and compile prerequisites - resolve Kiro latest objects to strong per-arch ETags, enforce them with If-Match during download, and require both installed CLI versions to match before creating the multi-arch manifest - use the authenticated GitHub API helper for Antigravity releases - reject leading, interior, trailing, and whitespace-only variant fields - replace digest word-splitting with a quoted array
Response to review on
|
| Finding | Resolution |
|---|---|
| F1 — one resolver failure suppresses every build | build now overrides the default needs success gate with always() && !cancelled(), while still requiring successful shared matrix/compile jobs. Each matrix child downloads its exact nightly-resolve-<variant> artifact; only the failed resolver's two build children fail, while sibling variants continue. tag already runs status-aware and requires only its own two digests. |
| F2 — Kiro remains mutable per architecture | The resolver now captures and validates each latest object's strong ETag once. Dockerfile.package sends quoted If-Match on the native download, so content drift fails HTTP 412. After push-by-digest, each native architecture runs kiro-cli --version and uploads a report; the Kiro tag job requires both reports to exist and match before manifest creation. Live verification: matching ETag → 206, wrong ETag → 412. |
| F3 — Antigravity bypasses authenticated helper | Release lookup now uses github_api; the exact resolver was executed successfully and resolved 1.1.24. |
| F4 — trailing empty selector accepted | Raw comma shapes are rejected before Bash field splitting, then trimmed elements are validated/deduplicated. The exact script rejects ,kiro, kiro,,claude, kiro,, kiro, , and duplicates; valid normalized subsets and all pass. |
| Canonical Review Contract stale | PR description and all five contract sections now reflect the resolve job, main-only publication, pi exclusion, attempt-unique tag, Antigravity override/label, Kiro ETag+version gate, current accepted risks, and current acceptance criteria. |
Additional validation: actionlint + shellcheck clean; BuildKit Kiro-target check clean (skipping only an unrelated pre-existing secret-name heuristic); exact Kiro and Antigravity resolvers pass; Kiro equal/mismatch comparison tests pass/fail as intended; package-pin parity and git diff --check pass.
|
/review |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Important
CHANGES REQUESTED
Consolidated review: #1519 (comment)
|
Note LGTM ✅ - The exact-head fix closes both prior blockers with fail-closed checksum policy and one authoritative Antigravity version source; independent review and remote CI are green. What This PR DoesThis PR adds a scheduled and manually dispatchable How It WorksA strict selector creates the variant matrix. Shared binaries are compiled for amd64 and arm64, per-variant resolver artifacts feed the build matrix, and each tag job requires its own two valid image digests. Kiro binds mutable downloads to resolved strong ETags and requires matching installed versions across architectures. Grok and Antigravity may use the accepted TLS-only nightly path only through an explicit default-false opt-in. Findings
Resolved Finding Details🟢 F1: Shared checksum policy now fails closedThe shared package Dockerfile no longer interprets an empty SHA as implicit authorization. Kiro accepts an empty SHA only when its once-resolved ETag is present. Grok and Antigravity declare 🟢 F2: Antigravity metadata has one source of truth
Baseline Check
Addressing Inline and External Reviewer FeedbackPrior inline findings
Addressed in
Addressed in All earlier workflow findings remain resolved: Contributor and prior review feedback
Accepted and hardened: the accepted Grok/Antigravity TLS-only risk remains, but the relaxation is now explicit and fail-closed for every other caller. Release and pre-beta defaults remain pinned and verified.
Verified: pin-parity validation is green, legacy images retain their pinned defaults, and the nightly Antigravity image now persists the resolved effective version through the same argument used for installation. Validation
Review Coverage
Non-blocking Follow-ups
What's Good (🟢)
Three Reasons We Might Not Need This PR
|
There was a problem hiding this comment.
Note
LGTM ✅ - The exact-head fix closes both prior blockers; independent verification and the full remote check matrix are green.
Consolidated review: #1519 (comment)
Follow-up to #1519 addressing review findings from Sol and Fable: - F1: accept multipart S3 ETags (<md5>-<partcount>) in the Kiro latest-object validation. The ~586MB object sits at the multipart boundary; a future re-upload flipping its ETag to the suffixed form would otherwise hard-fail every nightly-kiro build with no SHA fallback. If-Match accepts multipart ETags, so both shapes are valid. - #2: use `grep -m1` instead of `grep | head -1` in the cursor resolver to avoid the SIGPIPE (exit 141) that head-closing-the-pipe triggers under pipefail, which surfaced as a spurious red job. - F5: correct the misleading no-cache comment — no-cache rebuilds every Dockerfile.package layer for the variant, not just the CLI layer; the openab binary is not recompiled (prebuilt via the bins= context).
Follow-up to #1519 addressing review findings from Sol and Fable: - F1: accept multipart S3 ETags (<md5>-<partcount>) in the Kiro latest-object validation. The ~586MB object sits at the multipart boundary; a future re-upload flipping its ETag to the suffixed form would otherwise hard-fail every nightly-kiro build with no SHA fallback. If-Match accepts multipart ETags, so both shapes are valid. - #2: use `grep -m1` instead of `grep | head -1` in the cursor resolver to avoid the SIGPIPE (exit 141) that head-closing-the-pipe triggers under pipefail, which surfaced as a spurious red job. - F5: correct the misleading no-cache comment — no-cache rebuilds every Dockerfile.package layer for the variant, not just the CLI layer; the openab binary is not recompiled (prebuilt via the bins= context). Co-authored-by: chaodu-agent <chaodu-agent@users.noreply.github.com>
Summary
Adds a scheduled nightly image channel for
openabdev/openab, analogous to the nightlychannel in
openab-pty. Each supported variant packages the current OpenAB binary with thevendor's latest CLI.
The pinned release and pre-beta lanes cannot already provide this: their CLI versions and,
for binary downloads, SHA256 values are defaults inside
Dockerfile.package, so rebuildingthose lanes intentionally republishes the same CLI. Nightly resolves fresh vendor metadata
and supplies build-argument overrides without changing those defaults.
Channel behavior
06:23 UTC; manual dispatch may select a strict comma-separated subset.variant → build each variant/architecture by digest → create per-variant multi-arch manifests.
main. A feature-branch dispatch may validate theselector, compilation, and resolvers but cannot push images.
nightly-<variant>— moving tag.nightly-YYYYMMDD-<run-id>.<attempt>-<variant>— immutable rollback point; the attemptsuffix prevents a workflow re-run from moving an existing rollback tag.
successful siblings; that variant keeps yesterday's moving tag.
nativeandagentcoreare excluded because they contain no vendor CLI.piis temporarilyexcluded because its existing package target does not ship its configured adapter (fix(docker): pi target sets OPENAB_AGENT_COMMAND=openab-agent but never ships that binary #1520).
Integrity model
the authenticated GitHub Contents API.
validates it, and the Dockerfile sends
If-Matchduring each download (a changed object failsHTTP 412). Each native image then runs
kiro-cli --version; the tag job requires amd64 andarm64 reports to match before creating a manifest.
downloads intentionally use empty SHA overrides and rely on TLS. This relaxation is confined
to
nightly-*builds.Validation
duplicates; accepts normalized valid subsets and
all.If-Match→ HTTP 206; incorrect ETag → HTTP 412.actionlint+shellcheck: clean.Dockerfile.packageKiro target: BuildKit--checkclean after skipping only the unrelated,pre-existing
OPENAB_AGENT_AUTH_COMMANDsecret-name heuristic.git diff --check: pass.Review Contract
Goal
Provide a daily and manually dispatchable nightly channel that is a drop-in image replacement
for each supported agent variant, packages the vendor's latest CLI, allows healthy variants to
publish independently, and leaves pinned release/pre-beta behavior unchanged. Nightly explicitly
has no compatibility guarantee.
Non-goals
pre-beta-*tags, pinned versions, or pinned SHA defaults.native,agentcore, or the currently brokenpipackage target (fix(docker): pi target sets OPENAB_AGENT_COMMAND=openab-agent but never ships that binary #1520).version check because its vendor offers only a mutable latest URL.
Accepted Residual Risks
affected variant fails its build or advances its moving tag; recovery is pinning the previous
attempt-unique rollback tag.
current resolution path. Nightly relies on TLS and empty SHA overrides for these two variants.
This does not weaken release/pre-beta because their non-empty pinned SHAs remain the defaults.
while another remains on yesterday's tag. The failed variant's red resolver/build/tag is the
alert; successful variants are not withheld.
compatible. This is part of the channel's explicit no-guarantee contract.
Acceptance Criteria
maincan publish moving and attempt-unique multi-arch tags for everyselected supported variant; a non-main dispatch cannot publish.
proceeds only when its exact resolve artifact exists, and each tag requires its own two valid
architecture digests.
If-Match; bothinstalled
kiro-cli --versionreports must match before its manifest is created.,kiro,kiro,,claude, andkiro,.pre-beta defaults still fail on checksum mismatch, and pin-parity validation remains green.
syntax, package-pin parity, and whitespace validation pass.
Follow-ups
pipackage target and re-add it to nightly (fix(docker): pi target sets OPENAB_AGENT_COMMAND=openab-agent but never ships that binary #1520).guarantees than its current build gate.
metadata becomes available.