Skip to content

Conversation

bramwelt
Copy link
Contributor

Implements container image building for pull requests and manual
workflow dispatch. Builds both project-api and root-project-setup
binaries using ko for multi-platform support (amd64/arm64) with SPDX
SBOM generation.

Generated with Claude Code

Co-Authored-By: Claude [email protected]
Signed-off-by: Trevor Bramwell [email protected]

@Copilot Copilot AI review requested due to automatic review settings August 19, 2025 20:24
@bramwelt bramwelt requested a review from a team as a code owner August 19, 2025 20:24
Copy link

coderabbitai bot commented Aug 19, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a new GitHub Actions workflow "Publish Container Branch" triggered on pull_request to main (no manual dispatch), which prepares a sanitized branch tag, and builds two multi-arch images (project-api, root-project-setup) with ko (v0.18.0), tagging by SHA and the computed tag and producing SPDX SBOMs. Also pins action references in existing ko-build workflows.

Changes

Cohort / File(s) Summary of Changes
New workflow: Publish Container Branch
.github/workflows/ko-build-branch.yaml
New workflow file added. Trigger: pull_request to main only. Workflow-level permission contents: read. Job Publish Container runs on ubuntu-latest with job permissions contents: read, packages: write and conditionally runs only when PR head repo is not a fork. Steps: pinned actions/checkout and actions/setup-go, pinned ko-build/setup-ko (version v0.18.0); step Prepare container tag sanitizes github.head_ref and emits tag to GITHUB_OUTPUT; two ko build steps build cmd/project-api and scripts/root-project-setup for linux/amd64 and linux/arm64, tagging with SHA and computed tag, and producing SPDX SBOMs.
Workflow updates: pinned actions & ko version
.github/workflows/ko-build-main.yaml, .github/workflows/ko-build-tag.yaml
Updated external action references to specific commit SHAs for actions/checkout and actions/setup-go, and updated ko-build/setup-ko pin and bumped Ko from v0.17.1 to v0.18.0. No functional control-flow changes.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor Dev as Developer
    participant GH as GitHub
    participant Runner as Actions Runner
    participant Ko as ko CLI
    participant Reg as Container Registry

    Dev->>GH: Open PR to main
    GH-->>Runner: Trigger "Publish Container Branch" job (pull_request)
    Runner->>Runner: actions/checkout@<pinned-sha>
    Runner->>Runner: actions/setup-go@<pinned-sha> (go.mod)
    Runner->>Runner: ko-build/setup-ko@<pinned-sha> (v0.18.0)
    Runner->>Runner: Prepare container tag (sanitize github.head_ref -> tag)
    Runner->>Ko: ko build cmd/project-api (-B, platforms, -t SHA, -t tag, --sbom spdx)
    Ko->>Reg: Push images + SPDX SBOM
    Runner->>Ko: ko build scripts/root-project-setup (-B, platforms, -t SHA, -t tag, --sbom spdx)
    Ko->>Reg: Push images + SPDX SBOM
    Runner-->>GH: Job completes (success/failure)
    note right of Runner: Job runs only if PR head repo is not a fork
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bramwelt/publish-container-branch

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@bramwelt bramwelt changed the title itHub workflow to build containers for branches [LFXV2-306] GitHub workflow to build containers for branches Aug 19, 2025
Implements container image building for pull requests and manual
workflow dispatch. Builds both project-api and root-project-setup
binaries using ko for multi-platform support (amd64/arm64) with SPDX
SBOM generation.

Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Trevor Bramwell <[email protected]>
@bramwelt bramwelt force-pushed the bramwelt/publish-container-branch branch from 2a071cf to a33d77f Compare August 19, 2025 20:25
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds a GitHub workflow to build container images for pull requests and manual workflow dispatch. The workflow uses ko to build multi-platform containers with SPDX SBOM generation for both project-api and root-project-setup binaries.

Key changes:

  • Adds automated container building for pull requests targeting main branch
  • Implements multi-platform support (amd64/arm64) using ko build tool
  • Includes SPDX SBOM generation for security compliance

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
.github/workflows/ko-build-branch.yaml (2)

32-32: Prefer relative import paths for portability (repeat of earlier review)

Using full module import paths hardcodes the repository and reduces portability. Relative paths work the same within this repo.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \

40-40: Prefer relative import paths for portability (repeat of earlier review)

Same rationale as above for root-project-setup.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \
🧹 Nitpick comments (2)
.github/workflows/ko-build-branch.yaml (2)

24-27: Optional: enable Go module cache to speed builds

actions/setup-go supports caching via dependency files.

       - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5
         with:
           go-version-file: go.mod
+          cache-dependency-path: go.sum

6-11: Follow-up: separate cleanup workflow still pending

The linked issue mentions removing branch-specific images after merge. That’s not part of this workflow (which is fine). Flagging to ensure a companion workflow is added.

I can draft a ghcr cleanup workflow that:

  • Triggers on push to main and deletes tags matching the merged branch name.
  • Optionally runs on a scheduled cron to prune stale branch tags.
    Would you like me to open a PR with that?
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7836ac0 and a33d77f.

📒 Files selected for processing (1)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
🔇 Additional comments (2)
.github/workflows/ko-build-branch.yaml (2)

23-29: Good security posture: pinned action SHAs and minimal permissions

Pinned SHAs for actions and scoped permissions look solid. Nice work.


33-37: SBOM generation and multi-arch builds look good

Using --sbom spdx and targeting linux/amd64,linux/arm64 aligns with supply-chain and platform goals.

Also applies to: 41-45

`github.ref` here refers to the pull request merge branch
`refs/pull/#/merge`, but this should instead be `github.head_ref` which
refers to the branch that triggered the workflow.

Signed-off-by: Trevor Bramwell <[email protected]>
@bramwelt bramwelt force-pushed the bramwelt/publish-container-branch branch from e6ba5cf to 4f8aec8 Compare August 19, 2025 21:18
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (5)
.github/workflows/ko-build-branch.yaml (5)

32-32: Prefer local import paths for portability.

Hardcoding the module path reduces portability (e.g., if this is run on a fork with a different module path). Local paths work with ko and are simpler.

Apply this diff:

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \

40-40: Same portability nit: use local path.

Apply this diff:

-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \

16-22: Forked PRs will fail to publish (read-only token). Gate publishing.

PRs from forks cannot push to GHCR. Add a job-level condition to skip publishing for forks.

Apply this diff:

 jobs:
   publish:
     name: Publish Container
+    if: ${{ github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork }}
     runs-on: ubuntu-latest
     permissions:
       contents: read
       packages: write

22-29: Images won’t publish without KO_DOCKER_REPO and registry auth.

ko needs KO_DOCKER_REPO and push credentials. As-is, it defaults to ko.local and won’t push to GHCR.

Add a GHCR login step and configure KO_DOCKER_REPO (lower-cased):

       - uses: ko-build/setup-ko@d982fec422852203cfb2053a8ec6ad302280d04d  # v0.8
         with:
           version: v0.17.1
+      - name: Login to GHCR and set KO_DOCKER_REPO
+        shell: bash
+        run: |
+          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
+          echo "KO_DOCKER_REPO=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"

30-37: github.ref_name can still be an invalid container tag on PRs. Sanitize tags.

For pull_request, ref_name can be like “123/merge” (contains “/”). Use head_ref for PRs and lower-case/sanitize. Update both build steps.

Apply this diff:

       - name: Build project-api for PR
-        run: |
-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+        run: |
+          # Derive a safe tag:
+          if [ "${{ github.event_name }}" = "pull_request" ]; then
+            TAG_NAME="${{ github.head_ref }}"
+          else
+            TAG_NAME="${{ github.ref_name }}"
+          fi
+          # Sanitize: lower-case, replace '/' with '-', strip spaces
+          TAG_NAME="$(echo "$TAG_NAME" | tr '[:upper:]' '[:lower:]' | tr '/' '-' | tr -s ' ')"
+          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
-            -t ${{ github.ref_name }} \
+            -t "${TAG_NAME}" \
             --sbom spdx

Repeat for the second build:

       - name: Build root-project-setup for PR
-        run: |
-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+        run: |
+          if [ "${{ github.event_name }}" = "pull_request" ]; then
+            TAG_NAME="${{ github.head_ref }}"
+          else
+            TAG_NAME="${{ github.ref_name }}"
+          fi
+          TAG_NAME="$(echo "$TAG_NAME" | tr '[:upper:]' '[:lower:]' | tr '/' '-' | tr -s ' ')"
+          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
-            -t ${{ github.ref_name }} \
+            -t "${TAG_NAME}" \
             --sbom spdx
🧹 Nitpick comments (4)
.github/workflows/ko-build-branch.yaml (4)

6-11: Trigger only when relevant paths change (align with “when services change”).

This currently triggers on every PR to main. To match the objective (“build per-branch when services change”), gate by paths for the two components and related build files.

Apply this diff:

 "on":
   pull_request:
     branches:
       - main
+    paths:
+      - 'cmd/project-api/**'
+      - 'scripts/root-project-setup/**'
+      - 'go.mod'
+      - 'go.sum'
+      - '.ko.yaml'
+      - '.github/workflows/ko-build-branch.yaml'
   workflow_dispatch:

30-45: Add job concurrency to avoid duplicate pushes for the same ref.

Helps prevent racing tags when multiple updates land quickly.

Apply this diff:

   publish:
     name: Publish Container
+    concurrency:
+      group: publish-${{ github.workflow }}-${{ github.ref }}
+      cancel-in-progress: true

30-45: Consider DRYing builds with a matrix or a loop.

You can reduce duplication and ensure consistent flags by using a matrix of import paths.

Example (partial):

strategy:
  matrix:
    component:
      - path: ./cmd/project-api
      - path: ./scripts/root-project-setup

steps:
  # ... setup steps ...
  - name: Build ${{ matrix.component.path }}
    run: |
      # compute TAG_NAME as shown earlier
      ko build ${{ matrix.component.path }} \
        -B --platform linux/amd64,linux/arm64 \
        -t ${{ github.sha }} -t "${TAG_NAME}" \
        --sbom spdx

1-11: Follow-up: add cleanup workflow for branch images after merge.

The linked issue also calls for removing branch-specific images post-merge. Plan a separate workflow (e.g., workflow_run on “closed” PRs or a scheduled cleanup) to delete GHCR tags for merged/deleted branches.

I can draft a .github/workflows/ko-cleanup-branch.yaml that enumerates GHCR tags for a branch and deletes them using the GH API or oras/ghcr APIs. Want me to open a follow-up PR?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a33d77f and e6ba5cf.

📒 Files selected for processing (1)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: MegaLinter
🔇 Additional comments (1)
.github/workflows/ko-build-branch.yaml (1)

23-29: Nice: pinned action SHAs and explicit ko version.

Good supply-chain hygiene and reproducibility.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (5)
.github/workflows/ko-build-branch.yaml (5)

32-32: Prefer relative package paths for portability

Hardcoding the module’s GitHub import path reduces portability and makes forks harder to test. ko supports building from local paths.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \

40-40: Prefer relative package paths for portability

Same as Line 32: use local path for the second image.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \

16-21: Gate publishing for forked PRs to prevent GHCR push failures

Forked PRs receive a read-only GITHUB_TOKEN and cannot push to GHCR; these runs will fail without gating.

Apply this diff at the job level:

   publish:
     name: Publish Container
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
     runs-on: ubuntu-latest

27-29: Add GHCR login and KO_DOCKER_REPO; ko won’t publish without both

ko needs a target repo and auth. Without KO_DOCKER_REPO and a registry login, it will not push to GHCR.

Append these steps right after setting up ko (Line 29):

       - uses: ko-build/setup-ko@d982fec422852203cfb2053a8ec6ad302280d04d  # v0.8
         with:
           version: v0.17.1
+      - name: Login to GHCR
+        uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567  # v3.3.0
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+      - name: Set KO_DOCKER_REPO
+        run: echo "KO_DOCKER_REPO=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"

30-37: Sanitize and centralize image tags; avoid using github.head_ref directly in commands

  • github.head_ref can include slashes and other invalid characters for Docker tags; workflow_dispatch does not populate head_ref at all, leading to empty tags.
  • actionlint flagged using github.head_ref directly in scripts; move it to an env var and sanitize.

Insert a sanitization step and update both builds to use it:

       - uses: ko-build/setup-ko@d982fec422852203cfb2053a8ec6ad302280d04d  # v0.8
         with:
           version: v0.17.1
+      - name: Set sanitized tag name
+        env:
+          EVENT_NAME: ${{ github.event_name }}
+          HEAD_REF: ${{ github.head_ref }}
+          REF_NAME: ${{ github.ref_name }}
+          GITHUB_SHA: ${{ github.sha }}
+        run: |
+          if [ "${EVENT_NAME}" = "pull_request" ]; then
+            NAME_RAW="${HEAD_REF}"
+          else
+            NAME_RAW="${REF_NAME}"
+          fi
+          NAME_RAW="${NAME_RAW:-${GITHUB_SHA}}"
+          # Docker tag charset: [A-Za-z0-9_.-], typically lowercase. Trim to 128 chars.
+          TAG_NAME="$(printf '%s' "$NAME_RAW" \
+            | tr '[:upper:]' '[:lower:]' \
+            | sed -E 's/[^a-z0-9._-]+/-/g' \
+            | sed -E 's/^-+|-+$//g' \
+            | cut -c1-128)"
+          echo "TAG_NAME=$TAG_NAME" >> "$GITHUB_ENV"
       - name: Build project-api for PR
         run: |
           ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
-            -t ${{ github.head_ref }} \
+            -t ${{ env.TAG_NAME }} \
             --sbom spdx
       - name: Build root-project-setup for PR
         run: |
           ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
-            -t ${{ github.head_ref }} \
+            -t ${{ env.TAG_NAME }} \
             --sbom spdx

Also applies to: 38-45

🧹 Nitpick comments (4)
.github/workflows/ko-build-branch.yaml (4)

16-21: Optional: add concurrency to avoid duplicate publishes on rapid updates

Helpful when multiple pushes/merges trigger builds—keeps only the latest run.

   publish:
     name: Publish Container
+    concurrency:
+      group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
+      cancel-in-progress: true

30-45: Step names say “for PR” but workflow also runs via workflow_dispatch

Minor naming mismatch; consider neutral names.

-      - name: Build project-api for PR
+      - name: Build project-api image
...
-      - name: Build root-project-setup for PR
+      - name: Build root-project-setup image

6-11: Consider path filters to build only when service code changes

Objective mentions “per-branch when service code changes.” Add paths to limit runs to relevant files.

Example (tune to your repo):

 "on":
   pull_request:
     branches:
       - main
+    paths:
+      - 'cmd/**'
+      - 'scripts/**'
+      - 'go.mod'
+      - 'go.sum'
+      - '.github/workflows/ko-build-branch.yaml'
   workflow_dispatch:

I can open a follow-up PR with a refined path list if you confirm the intended build targets.


1-46: Follow-up workflow for pruning branch-specific images

The linked issue calls for removing branch-specific containers post-merge. This PR adds builds, but the cleanup workflow is still missing.

I can draft a separate .github/workflows/ko-prune-branch.yaml that:

  • Triggers on pull_request closed with merged == true
  • Deletes GHCR tags matching the merged branch
  • Optionally deletes SBOM artifacts

Want me to prep that as a follow-up PR?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e6ba5cf and 4f8aec8.

📒 Files selected for processing (1)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ko-build-branch.yaml

31-31: "github.head_ref" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions for more details

(expression)


39-39: "github.head_ref" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions for more details

(expression)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and Test
  • GitHub Check: MegaLinter
🔇 Additional comments (1)
.github/workflows/ko-build-branch.yaml (1)

38-45: Confirmed: scripts/root-project-setup is a Go “main” package
The directory’s main.go declares package main and defines func main(), so the ko build step will succeed as written.

This is the docker imposed tag limit.

Signed-off-by: Trevor Bramwell <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (3)
.github/workflows/ko-build-branch.yaml (3)

37-37: Prefer local paths over hardcoded repo import paths for portability

Using full GitHub import paths reduces portability (e.g., forks) and couples the workflow to the module path. ko works fine with local paths.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \
-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \

Also applies to: 45-45


16-22: Gate publishing for forked PRs to prevent failures and unauthorized pushes

Forked PRs have read-only GITHUB_TOKEN for packages; publishing will fail. Gate the job so it only publishes for non-fork PRs or non-PR events. Optionally add a separate build-only path for forks.

 jobs:
   publish:
     name: Publish Container
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
     runs-on: ubuntu-latest
     permissions:
       contents: read
       packages: write

Optional: add another job under the inverse condition to do a local ko build (KO_DOCKER_REPO=ko.local) for fork validation without pushing.


22-29: Images won’t publish without KO_DOCKER_REPO and registry auth

This job is named “Publish Container” and grants packages: write, but there’s no GHCR auth and KO_DOCKER_REPO is unset. ko will default to ko.local and won’t push multi-arch images. Configure GHCR auth and KO_DOCKER_REPO.

       - uses: ko-build/setup-ko@d982fec422852203cfb2053a8ec6ad302280d04d  # v0.8
         with:
           version: v0.17.1
+      - name: Login to GHCR and configure ko repo
+        shell: bash
+        run: |
+          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
+          # GHCR requires lowercase owner/repo
+          echo "KO_DOCKER_REPO=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"
🧹 Nitpick comments (3)
.github/workflows/ko-build-branch.yaml (3)

6-11: Align triggers with “per-branch when service code changes” objective

Currently only pull_request to main and manual dispatch are supported. If you want per-branch builds on push and to limit runs to service changes, add push and path filters.

 "on":
   pull_request:
     branches:
       - main
+    paths:
+      - 'cmd/**'
+      - 'scripts/**'
+      - 'go.mod'
+      - 'go.sum'
+      - '.github/workflows/ko-build-branch.yaml'
+  push:
+    branches:
+      - '**'
+    paths:
+      - 'cmd/**'
+      - 'scripts/**'
+      - 'go.mod'
+      - 'go.sum'
+      - '.github/workflows/ko-build-branch.yaml'
   workflow_dispatch:

12-14: Optional: Add concurrency control to cancel superseded runs

Useful for busy PRs to avoid wasting CI minutes and registry churn.

 permissions:
   contents: read
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true

30-34: Nit: tag length and character policy

You currently allow underscores and uppercase and cap at 127. Docker tag max is 128; many teams standardize lowercase tags to avoid inconsistencies across tooling. Your updated sanitization (if applied) already lowers and caps at 128.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4f8aec8 and c1dec81.

📒 Files selected for processing (1)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ko-build-branch.yaml

32-32: "github.head_ref" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions for more details

(expression)

🔇 Additional comments (2)
.github/workflows/ko-build-branch.yaml (2)

35-51: SBOM generation looks good

Using ko’s --sbom spdx for both images is aligned with the SBOM requirement. No issues here.


35-51: Build targets verified: both are Go main packages
Both cmd/project-api and scripts/root-project-setup exist and contain package main, so the ko build steps will succeed as written.

This is not needed and is causing shellcheck to complain.

Signed-off-by: Trevor Bramwell <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (5)
.github/workflows/ko-build-branch.yaml (5)

35-42: Prefer relative build paths for portability

Hardcoding the module path ties the workflow to this repo path. Relative paths are more portable and work for forks/clones.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
             -t ${{ steps.container_tag.outputs.tag }} \
             --sbom spdx

43-50: Prefer relative build paths for portability (second build)

Apply the same change for root-project-setup.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
             -t ${{ steps.container_tag.outputs.tag }} \
             --sbom spdx

16-22: Gate publishing for forked PRs to avoid GHCR push failures

PRs from forks use a read-only GITHUB_TOKEN; pushes to GHCR will fail. Gate the job to run publishing only for non-fork PRs or non-PR events.

 jobs:
   publish:
     name: Publish Container
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
     runs-on: ubuntu-latest

30-34: Fix tag prep: handle workflow_dispatch and sanitize safely (avoid untrusted expressions)

github.head_ref is empty on workflow_dispatch and should not be inlined into shell. Normalize to lowercase, sanitize, and fallback to SHA.

-      - name: Prepare container tag
-        id: container_tag
-        run: |
-          container_tag=$(echo ${{ github.head_ref }} |  sed 's/[^_0-9a-zA-Z]/\-/g' | cut -c -127)
-          echo "tag=$container_tag" >> $GITHUB_OUTPUT
+      - name: Prepare container tag
+        id: container_tag
+        env:
+          EVENT_NAME: ${{ github.event_name }}
+          HEAD_REF: ${{ github.head_ref }}
+          REF_NAME: ${{ github.ref_name }}
+          SHA: ${{ github.sha }}
+        shell: bash
+        run: |
+          if [[ "$EVENT_NAME" == "pull_request" ]]; then
+            SRC="$HEAD_REF"
+          else
+            SRC="$REF_NAME"
+          fi
+          # lowercase, replace disallowed chars, trim to 128 chars, strip leading/trailing '-'
+          TAG="$(printf '%s' "$SRC" \
+            | tr '[:upper:]' '[:lower:]' \
+            | sed -E 's/[^0-9a-z._-]+/-/g' \
+            | sed -E 's/^-+|-+$//g' \
+            | cut -c1-128)"
+          # fallback to short SHA if empty
+          if [[ -z "$TAG" ]]; then TAG="${SHA:0:12}"; fi
+          echo "tag=$TAG" >> "$GITHUB_OUTPUT"

22-29: Images won’t publish without KO_DOCKER_REPO and registry auth

ko requires KO_DOCKER_REPO and registry credentials to push. As written, it will default to ko.local or fail to publish.

       - uses: ko-build/setup-ko@d982fec422852203cfb2053a8ec6ad302280d04d  # v0.8
         with:
           version: v0.17.1
+      - name: Login to GHCR and configure ko repo
+        shell: bash
+        run: |
+          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
+          # KO requires a repo target; ensure lowercase for GHCR
+          echo "KO_DOCKER_REPO=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"
🧹 Nitpick comments (4)
.github/workflows/ko-build-branch.yaml (4)

6-11: Trigger on push (branches) and optionally limit to service code changes

To meet “build and publish containers per-branch when service code changes,” add push triggers (and consider paths filters).

 "on":
   pull_request:
     branches:
       - main
+  push:
+    branches:
+      - '**'
+    paths:
+      - 'cmd/**'
+      - 'scripts/**'
+      - '**/*.go'
+      - 'go.mod'
+      - 'go.sum'
   workflow_dispatch:

If you only want non-main branch pushes, replace branches: ['**'] with branches-ignore: ['main'].


24-26: Optional: Enable Go module caching to speed builds

actions/setup-go v5 supports caching by module file. This reduces build times.

       - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5
         with:
           go-version-file: go.mod
+          cache: true

15-22: Optional: Add concurrency to cancel superseded runs per ref

Prevents wasting runners when new commits arrive on the same branch/PR.

 jobs:
+  concurrency:
+    group: ${{ github.workflow }}-${{ github.ref }}
+    cancel-in-progress: true
   publish:
     name: Publish Container

6-11: Missing cleanup workflow for branch images

The linked issue also calls for removing branch-specific images after merge. This PR doesn’t include that workflow.

Want me to add a follow-up workflow (e.g., on pull_request closed with merged == true) to delete GHCR tags matching the branch tag and remove manifests? I can draft a safe version that lists and deletes only tags prefixed by the sanitized branch name.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c1dec81 and df68134.

📒 Files selected for processing (1)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ko-build-branch.yaml

32-32: "github.head_ref" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions for more details

(expression)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: MegaLinter

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (5)
.github/workflows/ko-build-branch.yaml (5)

35-42: Use relative module paths to make the workflow portable (works in forks/renames)

Hardcoding the GitHub import path can break on forks or repo renames. ko supports building from relative paths.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \

43-50: Ditto: use a relative path for root-project-setup

For consistency and portability, prefer a relative path.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \

16-22: Gate publishing to avoid failures on forked PRs

Forked PRs have a read-only GITHUB_TOKEN and cannot push to GHCR; without gating, the job will fail when you add registry auth/KO_DOCKER_REPO. Add a job-level condition to publish only for non-fork PRs or non-PR events.

   publish:
     name: Publish Container
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
     runs-on: ubuntu-latest

27-29: Images won’t publish without KO_DOCKER_REPO and registry auth

ko requires KO_DOCKER_REPO to be set and registry auth to push images. Add a step to log in to GHCR and configure KO_DOCKER_REPO (lowercased).

       - uses: ko-build/setup-ko@d982fec422852203cfb2053a8ec6ad302280d04d  # v0.8
         with:
           version: v0.17.1
+      - name: Login to GHCR and configure ko repo
+        shell: bash
+        run: |
+          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
+          echo "KO_DOCKER_REPO=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"

30-34: Fix workflow tag generation for all trigger types

The current step uses only github.head_ref, which is empty for workflow_dispatch (and push) events, resulting in blank tags. It also embeds expressions directly in run, which Actionlint flags. Update to:

  • Branch off $GITHUB_REF_NAME for non–pull_request events.
  • Sanitize and truncate safely.
  • Fallback to SHA slice when the result is empty.
  • Expose context via env: and reference only shell variables.

File: .github/workflows/ko-build-branch.yaml
Lines: 30–34

-      - name: Prepare container tag
-        id: container_tag
-        run: |
-          container_tag="$(echo ${{ github.head_ref }} |  sed 's/[^_0-9a-zA-Z]/\-/g' | cut -c -127)"
-          echo "tag=$container_tag" >> $GITHUB_OUTPUT
+      - name: Prepare container tag
+        id: container_tag
+        env:
+          EVENT_NAME: ${{ github.event_name }}
+          HEAD_REF:   ${{ github.head_ref }}    # set on pull_request
+          REF_NAME:   ${{ github.ref_name }}    # set on push/workflow_dispatch
+          SHA:        ${{ github.sha }}
+        shell: bash
+        run: |
+          if [[ "$EVENT_NAME" == "pull_request" ]]; then
+            SRC="$HEAD_REF"
+          else
+            SRC="$REF_NAME"
+          fi
+          TAG="$(printf '%s' "$SRC" \
+            | tr '[:upper:]' '[:lower:]' \
+            | sed -E 's/[^0-9a-z._-]+/-/g' \
+            | sed -E 's/^-+|-+$//g' \
+            | cut -c1-128)"
+          if [[ -z "$TAG" ]]; then
+            TAG="${SHA:0:12}"
+          fi
+          echo "tag=$TAG" >> "$GITHUB_OUTPUT"
🧹 Nitpick comments (2)
.github/workflows/ko-build-branch.yaml (2)

24-26: Enable Go module caching for faster builds

actions/setup-go v5 supports built-in caching. This will materially speed up repeated builds.

       - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5
         with:
           go-version-file: go.mod
+          cache: true

6-11: Consider adding push trigger to build/publish branch images without a PR

Your objective mentions publishing per-branch when service code changes. If you want branch images even without a PR, add a push trigger (optionally with path filters).

 "on":
+  push:
+    branches:
+      - "**"
   pull_request:
     branches:
       - main
   workflow_dispatch:

If you only want to build on code changes, add a paths filter (e.g., cmd/, scripts/, go.mod, go.sum).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between df68134 and 5940a17.

📒 Files selected for processing (1)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/ko-build-branch.yaml

32-32: "github.head_ref" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions for more details

(expression)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: MegaLinter

bramwelt and others added 4 commits August 19, 2025 15:13
Fix quoting of environment variables.

Signed-off-by: Trevor Bramwell <[email protected]>
Signed-off-by: Trevor Bramwell <[email protected]>
Signed-off-by: Trevor Bramwell <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (4)
.github/workflows/ko-build-branch.yaml (4)

39-44: Use repo-relative build paths to improve portability and fork support

Hardcoding the module path ties builds to the upstream URL and breaks on forks. Use workspace-relative paths.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
             -t ${{ steps.container_tag.outputs.tag }} \
             --sbom spdx
-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \
             -B \
             --platform linux/amd64,linux/arm64 \
             -t ${{ github.sha }} \
             -t ${{ steps.container_tag.outputs.tag }} \
             --sbom spdx

Also applies to: 47-52


16-22: Gate publishing for forked PRs to avoid permissions failures

Forked PRs have read-only GITHUB_TOKEN for GHCR; pushes will fail. Gate the job to run only for non-fork PRs or non-PR events.

   publish:
     name: Publish Container
+    if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
     runs-on: ubuntu-latest

If you still want build validation for forks, consider a separate job that runs ko against ko.local (no push).


23-29: Images won’t publish without KO_DOCKER_REPO and registry auth

ko needs KO_DOCKER_REPO configured and valid auth to push. Currently missing, so builds will target ko.local or fail to publish.

Add a login step and set KO_DOCKER_REPO (lowercased) after setting up ko:

       - uses: ko-build/setup-ko@d982fec422852203cfb2053a8ec6ad302280d04d  # v0.8
         with:
           version: v0.17.1
+      - name: Login to GHCR and configure ko repo
+        shell: bash
+        run: |
+          echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
+          echo "KO_DOCKER_REPO=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_ENV"

30-36: Empty tag on workflow_dispatch and weak sanitization — make tag generation event-aware, sanitized, and safe

HEAD_REF is empty for workflow_dispatch (and push), producing an empty tag and failing ko. Also, prefer robust sanitization (lowercase, strip disallowed chars, trim to 128, fallback to SHA), and pass all contexts via env to avoid expression injection.

Apply this diff to replace the tag-prep step:

-      - name: Prepare container tag
-        id: container_tag
-        env:
-          HEAD_REF: "${{ github.head_ref }}"
-        run: |
-          container_tag=$(echo "$HEAD_REF" |  sed 's/[^_0-9a-zA-Z]/\-/g' | cut -c -127)
-          echo tag="$container_tag" >> "$GITHUB_OUTPUT"
+      - name: Prepare container tag
+        id: container_tag
+        env:
+          EVENT_NAME: ${{ github.event_name }}
+          HEAD_REF: ${{ github.head_ref }}     # set only on pull_request
+          REF_NAME: ${{ github.ref_name }}     # branch or tag name for non-PR events
+          SHA: ${{ github.sha }}
+        shell: bash
+        run: |
+          if [[ "$EVENT_NAME" == "pull_request" ]]; then
+            SRC="$HEAD_REF"
+          else
+            SRC="$REF_NAME"
+          fi
+          TAG="$(printf '%s' "$SRC" \
+            | tr '[:upper:]' '[:lower:]' \
+            | sed -E 's/[^0-9a-z._-]+/-/g' \
+            | sed -E 's/^-+|-+$//g' \
+            | cut -c1-128)"
+          if [[ -z "$TAG" ]]; then TAG="${SHA:0:12}"; fi
+          echo "tag=$TAG" >> "$GITHUB_OUTPUT"
🧹 Nitpick comments (3)
.github/workflows/ko-build-branch.yaml (3)

6-11: Consider adding push trigger and path filters to align with “per-branch when service code changes”

Right now only PRs to main and manual runs trigger builds. To build per-branch on code changes, add a push trigger with path filters.

 "on":
+  push:
+    branches:
+      - "**"
+    paths:
+      - cmd/**/*
+      - scripts/**/*
+      - go.mod
+      - go.sum
+      - .ko.yaml
+      - "**/*.go"
   pull_request:
     branches:
       - main
   workflow_dispatch:

37-44: Minor: step names say “for PR” but workflow also supports workflow_dispatch

Rename for clarity.

-      - name: Build project-api for PR
+      - name: Build project-api
...
-      - name: Build root-project-setup for PR
+      - name: Build root-project-setup

Also applies to: 45-52


1-53: Follow-up: branch-image cleanup workflow missing

PR objective mentions a separate workflow to remove branch-specific images after merge. Not in this PR. If intended separately, ignore; otherwise, I can draft a cleanup workflow (scheduled and/or on delete/closed events) targeting GHCR tags for merged branches.

Would you like me to add a second workflow that:

  • On pull_request.closed with merged=true: deletes ghcr tags for the branch
  • On schedule: prunes tags that don’t map to active branches
  • Uses gh api or ORAS with GHCR to list and delete tags safely?
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5940a17 and 52a73c8.

📒 Files selected for processing (1)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: MegaLinter

Updates the container branch publishing job to only allow publishing
containers from branches in this repository. This ensures PRs from forks
aren't allow to publish to this repositories container registry.

Bumps the checkout, setup-go, and setup-ko actions to the latest
version, and ensures all ko-build-* jobs are using the hash.

Signed-off-by: Trevor Bramwell <[email protected]>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
.github/workflows/ko-build-branch.yaml (2)

37-44: Build step looks correct; consider relative import path for portability.

Using the module import path works, but relative paths make forks/temporary module path changes less brittle.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/cmd/project-api \
+          ko build ./cmd/project-api \

Note: setup-ko already configures KO_DOCKER_REPO and GHCR auth, per our learning — no extra login needed.


45-52: Same portability nit for root-project-setup.

Mirror the relative path change for consistency.

-          ko build github.com/linuxfoundation/lfx-v2-project-service/scripts/root-project-setup \
+          ko build ./scripts/root-project-setup \
🧹 Nitpick comments (7)
.github/workflows/ko-build-tag.yaml (1)

47-47: Setup Go pinned — consider enabling cache.

Pin looks good. For faster releases, consider enabling module/cache to speed ko’s module resolution.

       - name: Setup Go
-        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5
+        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5
         with:
           go-version-file: go.mod
+          cache: true
.github/workflows/ko-build-branch.yaml (6)

6-10: Add manual dispatch to match PR objective.

The PR description mentions manual workflow dispatch. This workflow currently triggers only on pull_request to main. Add workflow_dispatch to allow on-demand builds.

 "on":
   pull_request:
     branches:
       - main
+  workflow_dispatch:

Confirm whether you also want to support re-running for non-main targets; if so, expand branches or use types/paths filters.


24-29: Toolchain pins are solid; consider enabling Go cache.

Pins look good and align with other workflows. Enabling cache trims CI time for repeated PR pushes.

       - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5  # v5
         with:
           go-version-file: go.mod
+          cache: true

30-36: Harden tag sanitization and add fallbacks.

Current sed replaces invalid chars and truncates to 127 chars. Improve resilience by:

  • Handling non-PR invocations (future-proof if triggers expand).
  • Lowercasing (optional but conventional for tags).
  • Stripping leading/trailing dashes to satisfy tag regex edge cases.
  • Falling back to short SHA if the result is empty.
-      - name: Prepare container tag
-        id: container_tag
-        env:
-          HEAD_REF: "${{ github.head_ref }}"
-        run: |
-          container_tag=$(echo "$HEAD_REF" | sed 's/[^_0-9a-zA-Z]/-/g' | cut -c -127)
-          echo tag="$container_tag" >> "$GITHUB_OUTPUT"
+      - name: Prepare container tag
+        id: container_tag
+        env:
+          EVENT_NAME: ${{ github.event_name }}
+          HEAD_REF: ${{ github.head_ref }}   # set on pull_request
+          REF_NAME: ${{ github.ref_name }}   # branch/tag for non-PR events
+          SHA: ${{ github.sha }}
+        shell: bash
+        run: |
+          if [[ "$EVENT_NAME" == "pull_request" ]]; then
+            SRC="$HEAD_REF"
+          else
+            SRC="$REF_NAME"
+          fi
+          TAG="$(printf '%s' "$SRC" \
+            | tr '[:upper:]' '[:lower:]' \
+            | sed -E 's/[^0-9a-z._-]+/-/g' \
+            | sed -E 's/^-+|-+$//g' \
+            | cut -c1-128)"
+          [[ -z "$TAG" ]] && TAG="${SHA:0:12}"
+          echo "tag=$TAG" >> "$GITHUB_OUTPUT"

14-22: Avoid duplicate publishes on rapid pushes: add concurrency group.

Multiple quick commits to the same PR branch will push the same tag repeatedly. Add a concurrency group per-branch and cancel in-progress runs.

 jobs:
   publish:
     name: Publish Container
     if: ${{ github.event.pull_request.head.repo.fork == false }}
     runs-on: ubuntu-latest
+    concurrency:
+      group: ${{ github.workflow }}-${{ github.event.pull_request.head.ref }}
+      cancel-in-progress: true

6-10: Optional: trigger only when relevant paths change.

Reduce CI noise and GHCR churn by limiting to service-related paths. Adjust as needed.

 "on":
   pull_request:
     branches:
       - main
+    paths:
+      - 'cmd/**'
+      - 'scripts/root-project-setup/**'
+      - 'go.mod'
+      - 'go.sum'
+      - 'ko.*'

1-53: Missing: cleanup workflow for branch-specific images after merge.

The linked issue asks for removing branch-specific containers after merge. This PR doesn’t add that workflow. Propose adding a follow-up workflow triggered when a PR is closed and merged to delete the branch tag from both images.

I can open a follow-up PR with a workflow like below. It uses GitHub’s API to delete GHCR tags matching the sanitized branch name prepared in this workflow.

# .github/workflows/ko-cleanup-branch.yaml
name: Cleanup Container Branch
on:
  pull_request:
    types: [closed]
permissions:
  contents: read
  packages: write
jobs:
  cleanup:
    if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
    runs-on: ubuntu-latest
    steps:
      - name: Compute sanitized tag
        id: tag
        env:
          HEAD_REF: ${{ github.event.pull_request.head.ref }}
        run: |
          TAG="$(printf '%s' "$HEAD_REF" \
            | tr '[:upper:]' '[:lower:]' \
            | sed -E 's/[^0-9a-z._-]+/-/g' \
            | sed -E 's/^-+|-+$//g' \
            | cut -c1-128)"
          echo "tag=$TAG" >> "$GITHUB_OUTPUT"

      - name: Delete branch tags in GHCR
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          ORG_REPO: ${{ github.repository }}
          TAG: ${{ steps.tag.outputs.tag }}
        run: |
          set -euo pipefail
          OWNER="$(cut -d'/' -f1 <<<"$ORG_REPO")"
          REPO="$(cut -d'/' -f2 <<<"$ORG_REPO")"
          for IMAGE in project-api scripts/root-project-setup; do
            PACKAGE="${OWNER}/${REPO}/${IMAGE}"
            # List container versions with this tag
            VERS=$(gh api -H "Accept: application/vnd.github+json" \
              "/orgs/${OWNER}/packages/container/${REPO}%2F${IMAGE}/versions?per_page=100" \
              --jq ".[] | select(.metadata.container.tags[]? == \"$TAG\") | .id") || true
            for ID in $VERS; do
              gh api -X DELETE -H "Accept: application/vnd.github+json" \
                "/orgs/${OWNER}/packages/container/${REPO}%2F${IMAGE}/versions/${ID}"
            done
          done

Note: Adjust org-level vs user-level endpoints if this repository is under an org (above uses orgs/OWNER). We can wire this up in a follow-up as needed.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 52a73c8 and 38b440e.

📒 Files selected for processing (3)
  • .github/workflows/ko-build-branch.yaml (1 hunks)
  • .github/workflows/ko-build-main.yaml (1 hunks)
  • .github/workflows/ko-build-tag.yaml (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: bramwelt
PR: linuxfoundation/lfx-v2-project-service#17
File: .github/workflows/ko-build-branch.yaml:22-29
Timestamp: 2025-08-20T19:42:18.314Z
Learning: The ko-build/setup-ko GitHub Action automatically sets KO_DOCKER_REPO=ghcr.io/${{ github.repository }} by default and handles authentication to GitHub Container Registry using the workflow token, so explicit login steps and KO_DOCKER_REPO configuration are not required.
📚 Learning: 2025-08-20T19:42:18.314Z
Learnt from: bramwelt
PR: linuxfoundation/lfx-v2-project-service#17
File: .github/workflows/ko-build-branch.yaml:22-29
Timestamp: 2025-08-20T19:42:18.314Z
Learning: The ko-build/setup-ko GitHub Action automatically sets KO_DOCKER_REPO=ghcr.io/${{ github.repository }} by default and handles authentication to GitHub Container Registry using the workflow token, so explicit login steps and KO_DOCKER_REPO configuration are not required.

Applied to files:

  • .github/workflows/ko-build-main.yaml
  • .github/workflows/ko-build-tag.yaml
  • .github/workflows/ko-build-branch.yaml
🔇 Additional comments (5)
.github/workflows/ko-build-main.yaml (1)

23-29: Additional SHA tag verification needed

The pinned SHAs for actions/setup-go and ko-build/setup-ko don’t clearly indicate their intended release tags based on the commit messages. Please confirm they map to the correct versions:

  • .github/workflows/ko-build-main.yamlactions/setup-go@d35c59a
    Commit message: “chore: update discussions url (#527)” does not reference a v5.x tag.
    → Verify by running:

    gh api repos/actions/setup-go/git/refs/tags/v5.4.0 -q .object.sha

    (or replace v5.4.0 with the exact minor/patch version you expect) and ensure it matches d35c59abb061a4a6fb18e82ac0862c26744d6ab5.

  • .github/workflows/ko-build-main.yamlko-build/setup-ko@d006021
    Commit message: “Merge pull request #46 … Bump actions/setup-go from 5.3.0 to 5.4.0 in the all group” doesn’t reference v0.9.
    → Verify by running:

    gh api repos/ko-build/setup-ko/git/refs/tags/v0.9.0 -q .object.sha

    to confirm it matches d006021bd0c28d1ce33a07e7943d48b079944c8d.

Once confirmed, these SHA-to-tag mappings will ensure the workflow uses the intended action versions.

.github/workflows/ko-build-tag.yaml (3)

31-31: Checkout pinned to v5 SHA — good.

Immutable pin helps prevent supply-chain drift in release publishing.


52-55: ko setup pinned; ko v0.18.0 aligned across workflows.

Alignment across main/branch/tag workflows avoids “works on one pipeline only” issues.


88-88: Release job’s checkout also pinned — consistent and good.

Thanks for keeping pins consistent across jobs.

.github/workflows/ko-build-branch.yaml (1)

17-21: Correctly gated for non-fork PRs.

Good call. PRs from forks have read-only GITHUB_TOKEN for packages; this avoids GHCR push failures.

Copy link
Contributor

@prabodhcs prabodhcs left a comment

Choose a reason for hiding this comment

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

LGTM

@bramwelt bramwelt merged commit 0d354cb into main Aug 26, 2025
6 checks passed
@bramwelt bramwelt deleted the bramwelt/publish-container-branch branch August 26, 2025 16:18
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.

2 participants