ci: rework build/release pipelines + add Thailand GitOps deploy#35
Conversation
Rework the image pipelines so semver releases promote the exact CI-built (and staging-tested) image instead of rebuilding, and so path scoping works without breaking tag handling. Workflows: - build.yml (default image): main push (path-scoped to image inputs) + dispatch. No tag trigger, so `paths:` filtering is reliable. Pushes sha-<short> always, latest on main, <branch-slug> on dispatch-from-branch. - build-thailand.yml (overlay): workflow_run (overlay the fresh sha base, mirror its moving tag) + thai-path push (overlay latest, with a dorny/paths-filter guard that defers to workflow_run when base paths also changed, killing the double-build + stale-base overlay) + dispatch. Dropped the unreliable workflow_run.branches filter; gate on conclusion == success. - release.yml (new): vX.Y.Z tag -> promote sha-<short> to X.Y.Z via `oras tag` (byte-identical to the tested image, immune to floating-pin drift), with a full build only as fallback. Thai mirrors the regular image's mode so its overlay always sits on the exact regular image being released. GitOps compatibility: every producing job captures the image digest and emits a short-lived (retention-days: 7) deploy-info artifact (image/tag/digest/ git_sha/ref/environment) for the forthcoming staging/production/siam-ai deploy workflows. Builds set provenance:false / sbom:false for one stable single-platform digest. concurrency added on all three (cancel-in-progress on branch builds; never cancel a release). Hardening: - Add .dockerignore (shared by both Dockerfiles; excludes only non-image paths, keeps skills-thailand/ and the Dockerfiles). - Pin every external action to an immutable commit SHA with a version comment. New actions bumped to latest major after a compatibility review: upload-artifact v7.0.1, paths-filter v4.0.1, setup-oras v2.0.0. Pre-existing actions held at latest-within-major for a follow-up phase. Docs: rewrite CLAUDE.md CI/versioning/deployment sections to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cross-major bumps for the six actions that predated the pipeline rework, after reviewing each major's release notes for breaking changes against our usage. All re-pinned to immutable commit SHAs with version comments. - actions/checkout v4 -> v7.0.0 - actions/setup-node v4 -> v6.4.0 - actions/setup-python v5 -> v6.2.0 - docker/build-push-action v6 -> v7.2.0 - docker/setup-buildx-action v3 -> v4.1.0 - docker/login-action v3 -> v4.2.0 Scrutiny notes: - All bump to a Node-24 runtime requiring Actions Runner >= v2.327.1; satisfied by GitHub-hosted ubuntu-latest runners. - checkout v7 (#2454) refuses to check out fork-PR code on workflow_run / pull_request_target. Verified harmless: the guard only fires when workflow_run.event starts with "pull_request" AND the head repo is a fork; our "Build and Push" triggers only on push/workflow_dispatch, so the check no-ops. It actually hardens our workflow_run+ref checkout. - login v4 / setup-buildx v4 / build-push v7 only remove deprecated inputs/outputs and DOCKER_BUILD_* envs we don't use; our with: keys are core and unchanged. - setup-node v5+ auto-enables package-manager caching when package.json has a packageManager field. The repo has no package.json/lockfile and the test job installs no JS deps, so this is inert; added an explicit package-manager-cache: false guard anyway. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add deploy-thailand.yml, which pins the agent-sandbox-thailand image in
EternisAI/gitops-siam-ai (apps/clusters/oa1/axion/app/release/values.yaml,
keys axion.sandbox.image.tag/.digest) so Flux reconciles it onto oa1-siam.
Triggers:
- workflow_run after "Release (promote tag)" succeeds -> deploy the released
semver, read from that run's deploy-info-siam-ai artifact.
- workflow_dispatch -> deploy inputs.image_tag, else the branch's moving tag
(latest on main, <slug> otherwise).
The digest is always re-resolved from GHCR via oras (registry is the source of
truth) and the run fails if the tag isn't published. The values.yaml edit is a
surgical awk line-replace anchored on the sandbox image's repository: line (not
yq, which would reflow the human-maintained file's comments/alignment); it is
idempotent and pushed via a rebase-retry loop. Runs in the "Axion Siam.AI"
GitHub Environment (GITOPS_PAT secret). No reconcile-watch (out of scope).
Update CLAUDE.md: Deployment section now documents deploy-thailand.yml as
implemented (siam-ai done; staging/production still forthcoming).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
WalkthroughThis PR overhauls the container image CI/CD pipeline. It adds a shared Sequence DiagramsequenceDiagram
participant Dev as Developer
participant BuildBase as build.yml
participant BuildThai as build-thailand.yml
participant Release as release.yml
participant DeployThai as deploy-thailand.yml
participant GHCR as GHCR Registry
participant GitOps as gitops-siam-ai
Dev->>BuildBase: push to main (Dockerfile)
BuildBase->>GHCR: push base:sha-short + base:latest
BuildBase->>BuildThai: trigger workflow_run
BuildThai->>GHCR: build and push thai:sha-short + thai:latest
Dev->>Release: push vX.Y.Z tag
Release->>GHCR: oras check base:sha-short
GHCR-->>Release: digest
Release->>GHCR: oras tag → base:X.Y.Z
Release->>GHCR: oras check thai:sha-short
GHCR-->>Release: digest
Release->>GHCR: oras tag → thai:X.Y.Z
Release->>DeployThai: trigger workflow_run with artifacts
DeployThai->>GHCR: oras resolve thai:X.Y.Z digest
GHCR-->>DeployThai: image_digest
DeployThai->>GitOps: checkout and awk update values.yaml
GitOps-->>DeployThai: commit/push with retry loop
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Around line 100-103: The workflow is publishing the `:latest` tag from a
release fallback build, which can unintentionally move the latest tag away from
branch CI semantics. Remove the line containing `${{ steps.meta.outputs.image
}}:latest` from the tags list in the workflow, keeping only the short SHA-based
tag and the versioned tag to ensure the latest tag is only managed by the
primary branch CI pipeline.
- Around line 24-27: The tag trigger pattern in the `on.push.tags` section is
using regex syntax instead of glob syntax. Change the pattern
`v[0-9]+.[0-9]+.[0-9]+` to `v*.*.*` which is the correct glob pattern syntax
that will properly match semantic version tags like `v1.2.3`. The glob pattern
uses asterisks as wildcards rather than regex character classes and quantifiers.
In @.github/workflows/test.yml:
- Around line 15-17: The checkout steps in the test jobs are not disabling
credential persistence, which leaves the GitHub token in git config and widens
the security blast radius. Add the persist-credentials parameter set to false in
both checkout actions (the ones using
actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 at lines 15-17 and the
corresponding step around lines 44-46) to prevent credential persistence since
these test jobs do not require repository write access.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b80e1fb6-9a4e-45c8-b571-eda14ec567b0
📒 Files selected for processing (8)
.dockerignore.github/workflows/build-thailand.yml.github/workflows/build.yml.github/workflows/deploy-thailand.yml.github/workflows/release.yml.github/workflows/test.ymlCLAUDE.mdDockerfile.thailand
…st checkouts - release.yml: the fallback build no longer pushes :latest. The moving `latest` tag is build.yml's (main CI) to manage; a release must not move it (the tagged commit may not be main's tip). Now mirrors the promote path, which only adds the :<ver> tag. Keeps sha-<short> + <ver>. - test.yml: set persist-credentials: false on both checkouts — these jobs never push via git, so GITHUB_TOKEN need not persist in .git/config. Skipped the reviewer's third suggestion (change tag filter to v*.*.*): the current `v[0-9]+.[0-9]+.[0-9]+` is valid GitHub filter-pattern glob ([] ranges and + quantifier are supported, . is literal) and is strictly more precise. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dispatching build.yml or build-thailand.yml with a tag ref (e.g. v0.3.0) selected would derive the output tag from the ref — building a v-prefixed slug (agent-sandbox[-thailand]:v0.3.0) that overlays the wrong base (latest, not the released version), uses the non-canonical `v` prefix, and bypasses release.yml's byte-identical promote of sha-<short> -> <ver>. Add a GITHUB_REF_TYPE=tag guard that fails fast with a pointer to the correct path: push a vX.Y.Z git tag -> release.yml promotes both images. Restore the semver mention to build-thailand.yml's workflow_dispatch comment + input description. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reworks the CI/CD pipelines so versioned releases are produced deterministically and the Thai image auto-deploys to
siam-ai. Three commits, building on each other.What changes
1. Split build / release (
a60afa6)build.yml(continuous):mainpushes + manual dispatch, path-scoped to files that go into the image. No tag trigger. Tagssha-<short>always,lateston main,<branch-slug>on dispatch-from-branch.release.yml(NEW): triggers onvX.Y.Ztags; promotes the already-builtsha-<short>image to theX.Y.Ztag viaoras tag(byte-identical, drift-free), rebuilding only as a fallback. Mirrors the same mode to the Thai overlay.build-thailand.yml: no tag trigger; path-scoped +workflow_runoff the base build, with adorny/paths-filterskip-gate to avoid double-builds..dockerignore(NEW), shared by both Dockerfiles.paths:-filtered tag trigger is silently skipped (tag pushes introduce zero changed files), so tag handling lives in its own workflow.deploy-infoartifact (image/tag/digest/env) as a deploy fast-path; the registry stays the source of truth.2. Pin + upgrade actions (
a60afa6+58da1d7)workflow_runusage;package-manager-cache: falseadded to the test job (no lockfile in repo).3. Thailand GitOps deploy (
73c831f)deploy-thailand.yml(NEW): pinsagent-sandbox-thailandinEternisAI/gitops-siam-ai(apps/clusters/oa1/axion/app/release/values.yaml, keysaxion.sandbox.image.tag/.digest) → Flux reconciles onto oa1-siam.workflow_runafter "Release (promote tag)" succeeds → deploys the released semver (tag read from that run'sdeploy-info-siam-aiartifact).workflow_dispatch→inputs.image_tag, else the branch's moving tag (latest/<slug>).oras(source of truth); fails if the tag isn't published.values.yamledited with a surgicalawkline-replace anchored on the sandbox image'srepository:line — notyq(the file is human-maintained with comments/alignment yq would reflow). Idempotent; pushed via a rebase-retry loop as the Eternis DevOps Bot.Axion Siam.AIGitHub Environment (holdsGITOPS_PAT). No reconcile-watch (out of scope).Verified
values.yaml: touches exactly the two sandbox lines, alignment/quoting preserved, idempotent re-apply = no-op, result valid YAML.actionlint(incl. shellcheck onrun:blocks) clean; all workflow YAML parses.Axion Siam.AIenvironment +GITOPS_PATsecret exist in this repo; no branch policy / reviewers to blockworkflow_runor branch dispatch.Notes for reviewers / rollout
GITOPS_PATscope (fine-grained, Contents: write ongitops-siam-ai) can only be confirmed by a run; safe smoke test once merged: dispatchdeploy-thailandonmainwith emptyimage_tag→ resolveslatest, no-op if already current.main.🤖 Generated with Claude Code
Summary by CodeRabbit
values.yaml..dockerignore.