Skip to content

ci(deploy): hands-off auto-deploy via CI-writes-to-GitOps - #19

Merged
Coldaine merged 3 commits into
mainfrom
feat/auto-deploy-ci
Jun 18, 2026
Merged

ci(deploy): hands-off auto-deploy via CI-writes-to-GitOps#19
Coldaine merged 3 commits into
mainfrom
feat/auto-deploy-ci

Conversation

@Coldaine

@Coldaine Coldaine commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

User description

What & why

Makes every merge to main auto-deploy to the cluster with no human step, using the pattern
coldaine-k8cluster already standardized on (docs/app-delivery.md) — which is also Argo CD's
documented 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 & push sha-<short> → CI writes ghcr.io/coldaine/robot-overview@sha256:<digest>
straight into apps/robot-overview/deployment.yaml on coldaine-k8cluster main (bot commit, no PR)
→ Argo (automated + selfHeal) syncs within ~3 min → pod rolls. Zero in-cluster components; the
cluster stays pull-only with no inbound path.

Changes (.github/workflows/image.yml)

  • build job exposes the pushed @sha256 digest (image-digest output, id: build).
  • update-k8cluster rewritten: short-lived GitHub App token (GITOPS_APP_ID/GITOPS_APP_KEY)
    scoped to coldaine-k8cluster; pins the immutable digest via yq; direct commit to main
    (bot author, [skip ci]); concurrency + rebase-retry so racing merges don't collide.
  • No-ops gracefully until the App secrets exist (no hard CI failure pre-setup). Drops the old PAT.

One-time setup required (only you can do this — credentials)

  1. Create a GitHub App (org/personal), permission Contents: Read and write, installed on
    only Coldaine/coldaine-k8cluster.
  2. Add repo secrets to RobotOverview: GITOPS_APP_ID (App ID) and GITOPS_APP_KEY (the PEM
    private key). Remove the now-unused K8CLUSTER_REPO_TOKEN.
  3. Allow the bot to push to coldaine-k8cluster main (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

  • After a successful main branch build, CI now writes the new RobotOverview image digest directly into coldaine-k8cluster and commits it to main, instead of opening a pull request.
  • The deployed image is now pinned to an immutable digest, so the cluster rolls out the exact built image.
  • If the GitOps GitHub App is not set up yet, the workflow now skips the deploy step with a notice instead of failing the build.
  • Concurrent merges are handled with retry-and-rebase so one deploy does not block or overwrite another.

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:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

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:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

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 the coldaine-k8cluster repository, without requiring pull requests or manual intervention.

Architecture & Flow

main branch merge
        ↓
   Build image
        ↓
  Push to GHCR (with `@sha256` digest)
        ↓
  Mint scoped GitHub App token
        ↓
  Commit immutable digest to coldaine-k8cluster/main
        ↓
  Argo CD auto-sync detects change (≈3 min)
        ↓
  Pod rollout with new image

Key Changes to .github/workflows/image.yml

Build Job (image)

Aspect Change
New Output image-digest: ${{ steps.build.outputs.digest }} — exposes the pushed image's immutable @sha256 digest
Build Step ID Added id: build to the Docker build action to reference digest output
Existing Behavior image-ref output retained for backward compatibility

Deployment Job (update-k8cluster)

Triggered on: push events to main branch only

Serialization: Concurrency group gitops-write-coldaine-k8cluster with cancel-in-progress: false prevents write collisions from rapid merges.

Authentication Flow:

  • Secrets-driven activation: Job gracefully no-ops if GITOPS_APP_ID / GITOPS_APP_KEY are not configured
  • Uses actions/create-github-app-token@v1 to mint a short-lived, scoped token (scoped to Coldaine/coldaine-k8cluster only)
  • Replaces previous PAT + PR-based approach with direct main commits

Deployment Logic:

  1. Checks out coldaine-k8cluster repository's main branch
  2. Locates apps/robot-overview/deployment.yaml
  3. Uses yq to update the robot-overview container image reference to the immutable @sha256 digest
  4. Commits directly to main with message format: chore(robot-overview): deploy <SHORT_SHA> [skip ci]
  5. Implements rebase-retry mechanism (3 attempts) to handle concurrent main advances between checkout and push

Safety Features:

  • Graceful no-op when target file doesn't exist
  • Skips commit if no changes detected
  • [skip ci] flag prevents CI re-trigger from bot commit
  • Read-only permissions on source repository; writes occur on target repository via App token

Security & Architecture Decisions

Aspect Design Choice
No inbound network Cluster remains pull-only; Argo CD pulls GitOps updates via existing sync mechanism
No image-updater Avoids external component dependencies and limitations with plain-YAML applications
Immutable digests Uses @sha256 instead of mutable tags for full reproducibility
Bot commits Direct commits with [skip ci] flag eliminate unnecessary CI re-runs
Scoped tokens GitHub App token restricted to single repository, improving security over repository-wide PATs

Required One-Time Setup

  1. Create a GitHub App with Contents: read-write permissions on coldaine-k8cluster
  2. Add repository secrets:
    • GITOPS_APP_ID: GitHub App ID
    • GITOPS_APP_KEY: GitHub App private key
  3. Configure coldaine-k8cluster branch protection to allow the bot to push directly to main

Code Review Summary

Metric Value
Lines Changed +64 / -30
Jobs Modified image (output added), update-k8cluster (completely replaced)
New Public Output jobs.image.outputs.image-digest
Review Effort High (architectural change to deployment mechanism)

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>
Copilot AI review requested due to automatic review settings June 18, 2026 21:04
@codeant-ai

codeant-ai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Coldaine, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d6b1882f-fe0d-4d58-9fad-d219b75e800d

📥 Commits

Reviewing files that changed from the base of the PR and between bb034d5 and ca21edb.

📒 Files selected for processing (1)
  • .github/workflows/image.yml
📝 Walkthrough

Walkthrough

The image workflow gains a new image-digest job output captured from the Docker build step. The update-k8cluster job is replaced: instead of opening a bump PR via a PAT token with a tag reference, it now mints a GitHub App token, directly commits to coldaine-k8cluster main, patches apps/robot-overview/deployment.yaml to an immutable @sha256 digest via yq, and includes concurrency serialization plus push retry logic.

Changes

Digest-pinned k8cluster deployment

Layer / File(s) Summary
Expose image digest from build step
.github/workflows/image.yml
Assigns id: build to the Docker build step and declares jobs.image.outputs.image-digest pointing to that step's digest output, making the SHA256 digest consumable by downstream jobs.
Replace PR-based update with direct digest-pinned commit
.github/workflows/image.yml
Removes the PAT-token PR creation flow; adds GitHub App token minting, direct checkout of coldaine-k8cluster main, yq patch pinning the container image to @sha256 digest in apps/robot-overview/deployment.yaml, commit/push with a serialization concurrency group, and a retry loop on push rejection.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hoppity-hop through the pipeline I go,
No more PRs with tags in a row!
A digest of SHA, immutable and true,
Direct to main — no approval to queue.
The rabbit commits with a retry or two! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: implementing hands-off auto-deployment via CI-writes-to-GitOps pattern, which aligns with the primary objective of automating cluster deployment on main merges.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auto-deploy-ci

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codeant-ai codeant-ai Bot added the size:M This PR changes 30-99 lines, ignoring generated files label Jun 18, 2026
@kilo-code-bot

kilo-code-bot Bot commented Jun 18, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
WARNING 2
Issue Details (click to expand)

WARNING

File Line Issue
doc/audit.md 1 Stale duplicate of docs/audit.md - documentation sprawl
docs/plans/ multiple Plans for already-executed features remain in repo as stale docs
Resolved Issues (fixed in new commits)
File Issue Resolution
.github/workflows/image.yml APP_READY only checked GITOPS_APP_ID Now checks both GITOPS_APP_ID != '' && GITOPS_APP_KEY != '' (line 98)
.github/workflows/image.yml No yq installation step Ensure yq (mikefarah) is available step added (lines 127-135)
.github/workflows/image.yml Rebase failure exits without retry git rebase --abort on conflict + retry loop added (lines 180-181)
.github/workflows/image.yml Actions not pinned to SHAs All workflow actions pinned to verified commit SHAs with version comments (6dc7d25)
Other Observations (not in diff)
File Issue
doc/audit.md Duplicate/stale documentation: doc/audit.md is an exact copy of docs/audit.md. Having two copies at different paths is confusing. The doc/ directory should be removed or the canonical version kept in one location. AGENTS.md does not route to either audit doc.
docs/plans/02-deploy-alpha.md Executed plan not removed: Status says "queued" but deployment infrastructure (Dockerfile, CI publish to GHCR) was completed in PR #16, and this PR #19 is further automating the deploy pipeline. The plan's content should either be captured in architecture.md or deleted.
docs/plans/03-expand-product.md Executed plan not removed: Status says "queued" but feature work (items inventory #17, product expansion #18) has already been merged.
docs/plans/05-global-themes-technical-plan.md Executed plan not removed: Global themes were implemented in PR #13. The technical execution plan should be archived.
docs/plans/global_themes.md Executed plan not removed: Conceptual themes doc - same timeline as 05-global-themes, should be live in architecture.md or removed.
docs/NORTH_STAR.md Open Questions section still lists unresolved decisions (hosting, DB host, auth, LLM population) that the PR description and current CI pipeline have implicitly resolved.
docs/audit.md Audit states "0 tests, Grade F" but the repo now has Vitest tests (79 tests from PR #15). The audit doc is stale.
AGENTS.md Does not route to doc/ directory or mention that stale docs exist there. Consider adding a note about canonical doc locations.
Files Reviewed (1 file)
  • .github/workflows/image.yml - 0 new issues (4 previous inline issues resolved)

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

Severity Count
WARNING 2
Issue Details (click to expand)

WARNING

File Line Issue
doc/audit.md 1 Stale duplicate of docs/audit.md - documentation sprawl
docs/plans/ multiple Plans for already-executed features remain in repo as stale docs
Resolved Issues (fixed in new commit)
File Issue Resolution
.github/workflows/image.yml APP_READY only checked GITOPS_APP_ID Now checks both GITOPS_APP_ID != '' && GITOPS_APP_KEY != '' (line 98)
.github/workflows/image.yml No yq installation step Ensure yq (mikefarah) is available step added (lines 127-135)
.github/workflows/image.yml Rebase failure exits without retry git rebase --abort on conflict + retry loop added (lines 180-183)
Other Observations (not in diff)
File Issue
doc/audit.md Duplicate/stale documentation: doc/audit.md is an exact copy of docs/audit.md. Having two copies at different paths is confusing. The doc/ directory should be removed or the canonical version kept in one location. AGENTS.md does not route to either audit doc.
docs/plans/02-deploy-alpha.md Executed plan not removed: Status says "queued" but deployment infrastructure (Dockerfile, CI publish to GHCR) was completed in PR #16, and this PR #19 is further automating the deploy pipeline. The plan's content should either be captured in architecture.md or deleted.
docs/plans/03-expand-product.md Executed plan not removed: Status says "queued" but feature work (items inventory #17, product expansion #18) has already been merged.
docs/plans/05-global-themes-technical-plan.md Executed plan not removed: Global themes were implemented in PR #13. The technical execution plan should be archived.
docs/plans/global_themes.md Executed plan not removed: Conceptual themes doc - same timeline as 05-global-themes, should be live in architecture.md or removed.
docs/NORTH_STAR.md Open Questions section still lists unresolved decisions (hosting, DB host, auth, LLM population) that the PR description and current CI pipeline have implicitly resolved.
docs/audit.md Audit states "0 tests, Grade F" but the repo now has Vitest tests (79 tests from PR #15). The audit doc is stale.
AGENTS.md Does not route to doc/ directory or mention that stale docs exist there. Consider adding a note about canonical doc locations.
Files Reviewed (1 file)
  • .github/workflows/image.yml - 0 new issues (3 previous inline issues resolved)

Fix these issues in Kilo Cloud

Previous review (commit bb034d5)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
WARNING 2
Issue Details (click to expand)

WARNING

File Line Issue
doc/audit.md 1 Stale duplicate of docs/audit.md - documentation sprawl
docs/plans/ multiple Plans for already-executed features remain in repo as stale docs
Other Observations (not in diff)
File Issue
doc/audit.md Duplicate/stale documentation: doc/audit.md is an exact copy of docs/audit.md. Having two copies at different paths is confusing. The doc/ directory should be removed or the canonical version kept in one location. AGENTS.md does not route to either audit doc.
docs/plans/02-deploy-alpha.md Executed plan not removed: Status says "queued" but deployment infrastructure (Dockerfile, CI publish to GHCR) was completed in PR #16, and this PR #19 is further automating the deploy pipeline. The plan's content should either be captured in architecture.md or deleted.
docs/plans/03-expand-product.md Executed plan not removed: Status says "queued" but feature work (items inventory #17, product expansion #18) has already been merged.
docs/plans/05-global-themes-technical-plan.md Executed plan not removed: Global themes were implemented in PR #13 (feat(ui): global themes, stateful inventory loop). The technical execution plan should be archived.
docs/plans/global_themes.md Executed plan not removed: Conceptual themes doc - same timeline as 05-global-themes, should be live in architecture.md or removed.
docs/NORTH_STAR.md Open Questions section still lists unresolved decisions (hosting, DB host, auth, LLM population) that the PR description and current CI pipeline have implicitly resolved. The PR description says deploys go via GHCR to a k3s cluster behind Cloudflare Tunnel—this answers the hosting question. NORTH_STAR.md should be updated to reflect current reality.
docs/audit.md Audit states "0 tests, Grade F" but the repo now has Vitest tests (PR #15: "Vitest suite — store, slot compatibility, format, and data integrity (79 tests)"). The audit doc is stale.
AGENTS.md Does not route to doc/ directory or mention that stale docs exist there. Consider adding a note about canonical doc locations.
Files Reviewed (1 file)
  • .github/workflows/image.yml - 0 issues

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.

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4-flash-20260423 · 541,667 tokens

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread .github/workflows/image.yml Outdated
Comment on lines +96 to +98
# 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 }}
Comment on lines +125 to +126
- name: Pin the new image digest and commit to main
if: ${{ env.APP_READY == 'true' }}
Comment on lines +162 to +165
echo "Push rejected (attempt ${attempt}); rebasing on latest main."
git fetch origin main
git rebase origin/main
done
coderabbitai[bot]
coderabbitai Bot previously requested changes Jun 18, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 18930f6 and bb034d5.

📒 Files selected for processing (1)
  • .github/workflows/image.yml

Comment on lines +105 to +123
- 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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:


🌐 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.

Suggested change
- 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

Comment thread .github/workflows/image.yml
Comment thread .github/workflows/image.yml
- 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>
@Coldaine

Copy link
Copy Markdown
Collaborator Author

Thanks — addressed the comments in ca21edb:

Applied

  • Copilot (APP_READY): now gates on GITOPS_APP_ID != '' && GITOPS_APP_KEY != '' so a half-configured App no-ops instead of failing token minting.
  • Copilot (yq): added an explicit mikefarah yq install guard (downloads a pinned v4.45.1 only if absent).
  • Copilot (rebase under set -e): rebase conflicts now git rebase --abort and retry from a fresh fetch instead of dying mid-rebase.
  • CodeRabbit (persist-credentials): checkout now uses persist-credentials: false; the App token is carried on the remote URL only for the fetch/push, so it isn't left in git config.
  • CodeRabbit (DRY image ref): new_ref is built from the REGISTRY/IMAGE_NAME workflow env vars.

Skipped (with reason)

  • CodeRabbit (pin actions to SHAs): the suggested SHAs blind-bump majors (create-github-app-token v1→v3.2.0), and every other action in this workflow + the repo's other workflows use version tags. SHA-pinning is worth doing, but as a deliberate repo-wide pass against tested versions — not an unreviewed major-version bump on a single job. Tracking separately.

@Coldaine

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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>
@Coldaine

Copy link
Copy Markdown
Collaborator Author

Pinned all workflow actions to their current commit SHAs in 6dc7d25 (with version comments) — addresses the supply-chain comment for the whole file, no behavior change. All three CodeRabbit items are now resolved.

@Coldaine
Coldaine dismissed coderabbitai[bot]’s stale review June 18, 2026 21:26

All three findings resolved in ca21edb + 6dc7d25 (persist-credentials:false + tokenized push, REGISTRY/IMAGE_NAME env vars, and all actions pinned to commit SHAs). Verified in-file; this CHANGES_REQUESTED was raised against the pre-fix commit and not auto-cleared.

@Coldaine
Coldaine merged commit 20bd756 into main Jun 18, 2026
5 of 6 checks passed
@Coldaine
Coldaine deleted the feat/auto-deploy-ci branch June 18, 2026 21:26
@sonarqubecloud

Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants