ci(deploy): hands-off auto-deploy via CI-writes-to-GitOps - #19
Conversation
Replaces the PAT+PR+mutable-tag bump with the pattern coldaine-k8cluster standardized on (docs/app-delivery.md) and that Argo CD documents as its CI automation flow: - build job now exposes the pushed image @sha256 digest (image-digest output) - update-k8cluster mints a short-lived GitHub App token (GITOPS_APP_ID/KEY) scoped to coldaine-k8cluster, pins the immutable digest into apps/robot-overview/deployment.yaml via yq, and commits DIRECTLY to main (bot author, [skip ci]) — no PR. Argo's automated+selfHeal app rolls it. - serialized via concurrency + rebase-retry so racing main merges don't collide - no-ops gracefully until the App secrets are configured (no hard CI failure) This is the repo-native, image-updater-free auto-deploy: zero in-cluster components, pull-only/no-inbound preserved, works with our plain-YAML app. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reached
More reviews will be available in 49 minutes and 53 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe image workflow gains a new ChangesDigest-pinned k8cluster deployment
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 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)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code Review SummaryStatus: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Resolved Issues (fixed in new commits)
Other Observations (not in diff)
Files Reviewed (1 file)
Fix these issues in Kilo Cloud Previous Review Summaries (2 snapshots, latest commit ca21edb)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit ca21edb)Status: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Resolved Issues (fixed in new commit)
Other Observations (not in diff)
Files Reviewed (1 file)
Fix these issues in Kilo Cloud Previous review (commit bb034d5)Status: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Other Observations (not in diff)
Files Reviewed (1 file)
PR Code Review (diff): The workflow changes are well-implemented. Security posture is correct (App token scoped to one repo, no PAT). Concurrency control prevents GitOps repo collisions. Rebase-retry loop handles racing merges. Error handling covers missing secrets, missing files, and missing digest. No code-level issues found in the diff itself. Reviewed by deepseek-v4-flash-20260423 · 541,667 tokens |
There was a problem hiding this comment.
Pull request overview
Automates production deployment on every merge to main by having CI write the newly built image digest directly into the GitOps repo (Coldaine/coldaine-k8cluster) so Argo CD can sync and roll out the change without any manual step.
Changes:
- Exposes the built image digest (
image-digest) from the image build job for downstream deployment. - Replaces the PR-based GitOps update flow with a GitHub App–scoped token that commits directly to
coldaine-k8cluster@main, with concurrency control and push retry logic.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Empty until the GitHub App is configured — lets the job no-op instead of hard-failing. | ||
| APP_READY: ${{ secrets.GITOPS_APP_ID != '' }} | ||
| IMAGE_DIGEST: ${{ needs.image.outputs.image-digest }} |
| - name: Pin the new image digest and commit to main | ||
| if: ${{ env.APP_READY == 'true' }} |
| echo "Push rejected (attempt ${attempt}); rebasing on latest main." | ||
| git fetch origin main | ||
| git rebase origin/main | ||
| done |
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/image.yml:
- Around line 115-123: The checkout step for the Coldaine/coldaine-k8cluster
repository persists credentials in the git config for subsequent steps. Add
persist-credentials: false to the actions/checkout@v5 step to disable automatic
credential persistence, then if a subsequent step performs a git push operation,
explicitly pass the token from steps.app-token.outputs.token to the git push
command using an embedded token in the repository URL rather than relying on the
persisted credentials.
- Around line 142-144: The `new_ref` variable assignment on line 143 hardcodes
the image reference as `ghcr.io/coldaine/robot-overview` instead of using the
workflow-level environment variables `REGISTRY` and `IMAGE_NAME` that are
already defined. Replace the hardcoded image reference with a dynamic
construction using these environment variables (e.g.,
`${REGISTRY}/${IMAGE_NAME}`) so that changes to the registry or image name only
need to be updated in one place rather than being duplicated in the workflow.
- Around line 105-123: Pin the GitHub Actions to their full commit SHAs instead
of mutable version tags to prevent supply-chain attacks. Replace the `uses`
directive in the `actions/create-github-app-token` step from the current version
tag format to a pinned SHA format (e.g.,
actions/create-github-app-token@[COMMIT_SHA]). Similarly, update the
`actions/checkout` step to use a pinned SHA instead of the version tag. This
ensures that even if these actions are compromised, your workflow will continue
using the known secure version you've tested and approved.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 35fed85b-6a24-419d-b66f-2dabda1a1f59
📒 Files selected for processing (1)
.github/workflows/image.yml
| - name: Mint a scoped GitHub App token for the GitOps repo | ||
| id: app-token | ||
| if: ${{ env.APP_READY == 'true' }} | ||
| uses: actions/create-github-app-token@v1 | ||
| with: | ||
| app-id: ${{ secrets.GITOPS_APP_ID }} | ||
| private-key: ${{ secrets.GITOPS_APP_KEY }} | ||
| owner: Coldaine | ||
| repositories: coldaine-k8cluster | ||
|
|
||
| # Uses a cross-repo PAT; credentials must persist for the later git push. | ||
| - name: Check out coldaine-k8cluster | ||
| if: ${{ env.GH_TOKEN != '' }} | ||
| if: ${{ env.APP_READY == 'true' }} | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| repository: Coldaine/coldaine-k8cluster | ||
| token: ${{ env.GH_TOKEN }} | ||
| token: ${{ steps.app-token.outputs.token }} | ||
| path: coldaine-k8cluster | ||
| ref: main | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
What are the latest release commit SHAs for actions/create-github-app-token and actions/checkout GitHub Actions?
💡 Result:
As of June 18, 2026, the latest release commit SHAs for the specified GitHub Actions are as follows: actions/create-github-app-token The latest release is v3.2.0 [1][2], published on May 12, 2026 [3][2]. The commit SHA associated with this release is bcd2ba49218906704ab6c1aa796996da409d3eb1 [3]. actions/checkout The latest release is v6.0.3 [4], published on June 2, 2026 [4]. The commit SHA associated with this release is df4cb1c [4].
Citations:
- 1: https://github.com/actions/create-github-app-token?tab=readme-ov-file
- 2: https://github.com/actions/create-github-app-token/releases/tag/v3.2.0
- 3: actions/create-github-app-token@bcd2ba4
- 4: https://github.com/actions/checkout/releases/tag/v6.0.3
🌐 Web query:
What is the complete commit SHA for actions/checkout v6.0.3?
💡 Result:
The complete commit SHA for the actions/checkout v6.0.3 release is df4cb1c069e1874edd31b4311f1884172cec0e10 [1][2].
Citations:
Pin actions to SHA hashes for supply-chain security.
Both actions/create-github-app-token@v1 and actions/checkout@v5 are referenced by mutable tags. If these actions are compromised, your workflow would automatically pull malicious code. This is especially critical here since the workflow handles a privileged App token with write access to another repository.
Pin to full commit SHAs. Use the latest stable releases:
🔒 Proposed fix
- name: Mint a scoped GitHub App token for the GitOps repo
id: app-token
if: ${{ env.APP_READY == 'true' }}
- uses: actions/create-github-app-token@v1
+ uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.GITOPS_APP_ID }}
private-key: ${{ secrets.GITOPS_APP_KEY }}
owner: Coldaine
repositories: coldaine-k8cluster
- name: Check out coldaine-k8cluster
if: ${{ env.APP_READY == 'true' }}
- uses: actions/checkout@v5
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
repository: Coldaine/coldaine-k8cluster
token: ${{ steps.app-token.outputs.token }}
path: coldaine-k8cluster
ref: main
fetch-depth: 0📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Mint a scoped GitHub App token for the GitOps repo | |
| id: app-token | |
| if: ${{ env.APP_READY == 'true' }} | |
| uses: actions/create-github-app-token@v1 | |
| with: | |
| app-id: ${{ secrets.GITOPS_APP_ID }} | |
| private-key: ${{ secrets.GITOPS_APP_KEY }} | |
| owner: Coldaine | |
| repositories: coldaine-k8cluster | |
| # Uses a cross-repo PAT; credentials must persist for the later git push. | |
| - name: Check out coldaine-k8cluster | |
| if: ${{ env.GH_TOKEN != '' }} | |
| if: ${{ env.APP_READY == 'true' }} | |
| uses: actions/checkout@v5 | |
| with: | |
| repository: Coldaine/coldaine-k8cluster | |
| token: ${{ env.GH_TOKEN }} | |
| token: ${{ steps.app-token.outputs.token }} | |
| path: coldaine-k8cluster | |
| ref: main | |
| fetch-depth: 0 | |
| - name: Mint a scoped GitHub App token for the GitOps repo | |
| id: app-token | |
| if: ${{ env.APP_READY == 'true' }} | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ secrets.GITOPS_APP_ID }} | |
| private-key: ${{ secrets.GITOPS_APP_KEY }} | |
| owner: Coldaine | |
| repositories: coldaine-k8cluster | |
| - name: Check out coldaine-k8cluster | |
| if: ${{ env.APP_READY == 'true' }} | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| repository: Coldaine/coldaine-k8cluster | |
| token: ${{ steps.app-token.outputs.token }} | |
| path: coldaine-k8cluster | |
| ref: main | |
| fetch-depth: 0 |
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 115-123: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 108-108: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 117-117: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 108-108: dangerous use of GitHub App tokens (github-app): app token inherits blanket installation permissions
(github-app)
🤖 Prompt for 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.
In @.github/workflows/image.yml around lines 105 - 123, Pin the GitHub Actions
to their full commit SHAs instead of mutable version tags to prevent
supply-chain attacks. Replace the `uses` directive in the
`actions/create-github-app-token` step from the current version tag format to a
pinned SHA format (e.g., actions/create-github-app-token@[COMMIT_SHA]).
Similarly, update the `actions/checkout` step to use a pinned SHA instead of the
version tag. This ensures that even if these actions are compromised, your
workflow will continue using the known secure version you've tested and
approved.
Source: Linters/SAST tools
- APP_READY now requires BOTH GITOPS_APP_ID and GITOPS_APP_KEY (Copilot) — an id without a key would fail token minting instead of cleanly no-oping - add an explicit mikefarah yq install guard (Copilot) — not reliably preinstalled - handle rebase conflicts under set -e: abort + retry instead of dying mid-rebase (Copilot) - checkout persist-credentials: false; carry the App token on the remote URL for fetch/push so the privileged token isn't left in git config (CodeRabbit) - build new_ref from REGISTRY/IMAGE_NAME env vars instead of hardcoding (CodeRabbit) Deliberately NOT pinning actions to commit SHAs (CodeRabbit): the suggested SHAs blind-bump majors (create-github-app-token v1->v3) and the rest of this workflow + repo use version tags; SHA-pinning belongs in a deliberate repo-wide pass, not an unreviewed major bump on one job. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks — addressed the comments in Applied
Skipped (with reason)
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
Supply-chain hardening for the workflow that handles a privileged cross-repo write token. Each action is pinned to the SHA its current major tag resolves to today (no behavior change, no blind major bump) with the version in a comment: - actions/checkout v5, actions/create-github-app-token v1 - docker/setup-buildx-action v3, docker/login-action v3, docker/metadata-action v5, docker/build-push-action v6 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Pinned all workflow actions to their current commit SHAs in |
|
❌ The last analysis has failed. |
User description
What & why
Makes every merge to
mainauto-deploy to the cluster with no human step, using the patterncoldaine-k8clusteralready standardized on (docs/app-delivery.md) — which is also Argo CD'sdocumented CI automation flow.
We deliberately do not use argocd-image-updater (the cluster repo rejected it: it silently
skips plain-YAML apps, has private-GHCR auth failures, not prod-ready).
Flow
merge main→ build & pushsha-<short>→ CI writesghcr.io/coldaine/robot-overview@sha256:<digest>straight into
apps/robot-overview/deployment.yamloncoldaine-k8clustermain(bot commit, no PR)→ Argo (
automated + selfHeal) syncs within ~3 min → pod rolls. Zero in-cluster components; thecluster stays pull-only with no inbound path.
Changes (
.github/workflows/image.yml)@sha256digest (image-digestoutput,id: build).update-k8clusterrewritten: short-lived GitHub App token (GITOPS_APP_ID/GITOPS_APP_KEY)scoped to
coldaine-k8cluster; pins the immutable digest viayq; direct commit to main(bot author,
[skip ci]);concurrency+ rebase-retry so racing merges don't collide.One-time setup required (only you can do this — credentials)
only
Coldaine/coldaine-k8cluster.GITOPS_APP_ID(App ID) andGITOPS_APP_KEY(the PEMprivate key). Remove the now-unused
K8CLUSTER_REPO_TOKEN.coldaine-k8clustermain(branch-protection bypass for the App) —the repo's docs already note "branch protection on main must allow the delivery bot."
Until step 1–2 are done the job simply skips. Once set, deploys are fully automatic.
🤖 Generated with Claude Code
CodeAnt-AI Description
Auto-deploy RobotOverview to the GitOps repo after each main branch build
What Changed
mainbranch build, CI now writes the new RobotOverview image digest directly intocoldaine-k8clusterand commits it tomain, instead of opening a pull request.Impact
✅ Faster production image rollouts✅ Fewer deploy PRs to review✅ Exact image deployments✅ Fewer failed deploys during rapid merges💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Overview
This PR implements automated hands-off deployment for RobotOverview by introducing a CI-writes-to-GitOps workflow pattern. On every merge to
main, the workflow builds a container image and immediately deploys it to the cluster via direct commits to thecoldaine-k8clusterrepository, without requiring pull requests or manual intervention.Architecture & Flow
Key Changes to
.github/workflows/image.ymlBuild Job (
image)image-digest: ${{ steps.build.outputs.digest }}— exposes the pushed image's immutable@sha256digestid: buildto the Docker build action to reference digest outputimage-refoutput retained for backward compatibilityDeployment Job (
update-k8cluster)Triggered on:
pushevents tomainbranch onlySerialization: Concurrency group
gitops-write-coldaine-k8clusterwithcancel-in-progress: falseprevents write collisions from rapid merges.Authentication Flow:
GITOPS_APP_ID/GITOPS_APP_KEYare not configuredactions/create-github-app-token@v1to mint a short-lived, scoped token (scoped toColdaine/coldaine-k8clusteronly)Deployment Logic:
coldaine-k8clusterrepository'smainbranchapps/robot-overview/deployment.yamlyqto update therobot-overviewcontainer image reference to the immutable@sha256digestmainwith message format:chore(robot-overview): deploy <SHORT_SHA> [skip ci]Safety Features:
[skip ci]flag prevents CI re-trigger from bot commitSecurity & Architecture Decisions
@sha256instead of mutable tags for full reproducibility[skip ci]flag eliminate unnecessary CI re-runsRequired One-Time Setup
Contents: read-writepermissions oncoldaine-k8clusterGITOPS_APP_ID: GitHub App IDGITOPS_APP_KEY: GitHub App private keycoldaine-k8clusterbranch protection to allow the bot to push directly tomainCode Review Summary
image(output added),update-k8cluster(completely replaced)jobs.image.outputs.image-digest