Skip to content

Fixed CI workflows for use in private repo#26686

Merged
kevinansfield merged 1 commit intomainfrom
fix-ci-for-private-repo
Mar 4, 2026
Merged

Fixed CI workflows for use in private repo#26686
kevinansfield merged 1 commit intomainfrom
fix-ci-for-private-repo

Conversation

@kevinansfield
Copy link
Copy Markdown
Member

Summary

  • Added contents: read permission to job_setup so checkout works in private repos (the implicit public repo read access doesn't apply here)
  • Replaced hardcoded TryGhost/Ghost repo reference with github.repository in the PR metadata API call
  • Added github.repository == 'TryGhost/Ghost' guard to all deploy/publish jobs so they skip cleanly on other repos: canary, publish_packages, deploy_tinybird_staging, deploy_tinybird_production, deploy_admin, trigger_cd, and create-release-branch
  • Consolidated Docker image push strategy: non-main repos use artifact-based image transfer (same path as fork PRs) so E2E tests still work without GHCR access
  • Renamed is-fork-pr/is-fork to use-artifact throughout ci.yml and load-docker-image action to accurately reflect the broadened semantics

@kevinansfield kevinansfield requested a review from rob-ghost March 4, 2026 12:43
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 4, 2026

Walkthrough

Replaces fork-detection gating with a required use-artifact input to control artifact-based vs registry-based image transfer; updates the load-docker-image action to support gunzip + docker load, list and verify the loaded image, and expose image-tag. CI workflow now passes and consumes use-artifact, scopes canary/deploy/publish steps to the TryGhost/Ghost repository, and replaces a hardcoded PR API URL with a dynamic ${{ github.repository }}-based URL. The create-release-branch job is restricted to the TryGhost/Ghost repository.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing CI workflows for use in private repositories.
Description check ✅ Passed The description is well-related to the changeset, providing clear details about permissions, repository guards, Docker image strategy, and variable renaming.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-ci-for-private-repo

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.

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (1)
.github/actions/load-docker-image/action.yml (1)

24-30: Decouple archive filename from artifact name for safer reuse.

Line 29 assumes the archive file is exactly ${artifact-name}.tar.gz. That works for the current caller, but it makes this generalized action brittle if artifact naming changes.

Proposed refactor
     - name: Download image artifact (artifact)
       if: inputs.use-artifact == 'true'
       uses: actions/download-artifact@v4
       with:
         name: ${{ inputs.artifact-name }}
+        path: _docker_image_artifact

     - name: Load image from artifact (artifact)
       if: inputs.use-artifact == 'true'
       shell: bash
       run: |
         echo "Loading Docker image from artifact..."
-        gunzip -c ${{ inputs.artifact-name }}.tar.gz | docker load
+        ARCHIVE="$(find _docker_image_artifact -maxdepth 1 -type f -name '*.tar.gz' | head -n1)"
+        if [ -z "$ARCHIVE" ]; then
+          echo "❌ No Docker image archive found in _docker_image_artifact"
+          exit 1
+        fi
+        gunzip -c "$ARCHIVE" | docker load
         echo "Available images after load:"
         docker images
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/actions/load-docker-image/action.yml around lines 24 - 30, The step
"Load image from artifact (artifact)" currently hardcodes the archive as `${{
inputs.artifact-name }}.tar.gz`, which couples archive filename to
artifact-name; add a new input (e.g., inputs.archive-filename) to action.yml and
change the run to use that input when building the gunzip/docker load pipeline
(fall back to a safe search or artifact-name + extension only if
archive-filename is empty), and update any docs/README to document the new
inputs; update references to inputs.artifact-name in the load step to use
inputs.archive-filename so callers can supply arbitrary archive names without
breaking reuse.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 66-68: The workflow currently assigns BASE_COMMIT from the GitHub
API and can silently set BASE_COMMIT=null; modify the step that sets BASE_COMMIT
so it validates the value after assignment (check for empty string or literal
"null"), emit a clear error message including the raw API response or status
when validation fails, and exit non‑zero to fail the job early; update the
snippet around the BASE_COMMIT assignment and the subsequent echo
"BASE_COMMIT=..." logic to perform this check and abort if BASE_COMMIT is not a
valid SHA.

---

Nitpick comments:
In @.github/actions/load-docker-image/action.yml:
- Around line 24-30: The step "Load image from artifact (artifact)" currently
hardcodes the archive as `${{ inputs.artifact-name }}.tar.gz`, which couples
archive filename to artifact-name; add a new input (e.g.,
inputs.archive-filename) to action.yml and change the run to use that input when
building the gunzip/docker load pipeline (fall back to a safe search or
artifact-name + extension only if archive-filename is empty), and update any
docs/README to document the new inputs; update references to
inputs.artifact-name in the load step to use inputs.archive-filename so callers
can supply arbitrary archive names without breaking reuse.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2e0385cd-b9d1-468d-8c4d-f48e540e4f9f

📥 Commits

Reviewing files that changed from the base of the PR and between d066dba and f28d814dc872d51c119cb10aa7b946bc14eb3f4e.

📒 Files selected for processing (3)
  • .github/actions/load-docker-image/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/create-release-branch.yml

Comment on lines +66 to 68
BASE_COMMIT=$(curl --location --request GET 'https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}' --header 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | jq -r .base.sha)
echo "Setting BASE_COMMIT to $BASE_COMMIT"
echo "BASE_COMMIT=$BASE_COMMIT" >> $GITHUB_ENV
Copy link
Copy Markdown
Contributor

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

🏁 Script executed:

cat -n .github/workflows/ci.yml | sed -n '60,75p'

Repository: TryGhost/Ghost

Length of output: 1066


🏁 Script executed:

grep -n "BASE_COMMIT" .github/workflows/ci.yml

Repository: TryGhost/Ghost

Length of output: 891


🏁 Script executed:

cat -n .github/workflows/ci.yml | sed -n '200,210p'

Repository: TryGhost/Ghost

Length of output: 742


🏁 Script executed:

# Check what happens with jq when parsing null values
echo '{"base": {"sha": null}}' | jq -r .base.sha
echo "---"
echo '{"base": {}}' | jq -r .base.sha
echo "---"
echo '{}' | jq -r .base.sha

Repository: TryGhost/Ghost

Length of output: 80


🏁 Script executed:

# Simulate API failure scenario
echo "Testing curl behavior with HTTP errors:"
echo "1. Without --fail flag (current code behavior):"
curl --silent --location 'https://httpbin.org/status/401' | head -c 100
echo -e "\n---"
echo "Exit code: $?"
echo -e "\n2. With --fail flag (proposed fix):"
curl --fail --silent 'https://httpbin.org/status/401' 2>&1 | head -c 100
echo -e "\n---"
echo "Exit code: $?"

Repository: TryGhost/Ghost

Length of output: 218


🏁 Script executed:

# Check the nx affected command documentation to understand what happens with --base=null
# First, let me see what version of nx is used
cat -n .github/workflows/ci.yml | sed -n '1,30p'

Repository: TryGhost/Ghost

Length of output: 1218


🏁 Script executed:

# Search for any validation or error handling around BASE_COMMIT usage
grep -B5 -A5 "BASE_COMMIT" .github/workflows/ci.yml | head -50

Repository: TryGhost/Ghost

Length of output: 2306


Fail fast if PR metadata lookup cannot resolve BASE_COMMIT.

Line 66 can silently produce BASE_COMMIT=null on API/auth/rate-limit failures, and downstream yarn nx affected commands then fail with misleading errors instead of catching the root cause immediately.

Proposed hardening
-          BASE_COMMIT=$(curl --location --request GET 'https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}' --header 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | jq -r .base.sha)
+          API_URL="${{ github.api_url }}/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}"
+          BASE_COMMIT=$(curl --fail --silent --show-error --location "$API_URL" \
+            --header "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
+            --header "Accept: application/vnd.github+json" | jq -r '.base.sha')
+          if [ -z "$BASE_COMMIT" ] || [ "$BASE_COMMIT" = "null" ]; then
+            echo "::error::Unable to resolve BASE_COMMIT from PR metadata"
+            exit 1
+          fi
           echo "Setting BASE_COMMIT to $BASE_COMMIT"
           echo "BASE_COMMIT=$BASE_COMMIT" >> $GITHUB_ENV
📝 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
BASE_COMMIT=$(curl --location --request GET 'https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}' --header 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | jq -r .base.sha)
echo "Setting BASE_COMMIT to $BASE_COMMIT"
echo "BASE_COMMIT=$BASE_COMMIT" >> $GITHUB_ENV
API_URL="${{ github.api_url }}/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}"
BASE_COMMIT=$(curl --fail --silent --show-error --location "$API_URL" \
--header "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
--header "Accept: application/vnd.github+json" | jq -r '.base.sha')
if [ -z "$BASE_COMMIT" ] || [ "$BASE_COMMIT" = "null" ]; then
echo "::error::Unable to resolve BASE_COMMIT from PR metadata"
exit 1
fi
echo "Setting BASE_COMMIT to $BASE_COMMIT"
echo "BASE_COMMIT=$BASE_COMMIT" >> $GITHUB_ENV
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 66 - 68, The workflow currently
assigns BASE_COMMIT from the GitHub API and can silently set BASE_COMMIT=null;
modify the step that sets BASE_COMMIT so it validates the value after assignment
(check for empty string or literal "null"), emit a clear error message including
the raw API response or status when validation fails, and exit non‑zero to fail
the job early; update the snippet around the BASE_COMMIT assignment and the
subsequent echo "BASE_COMMIT=..." logic to perform this check and abort if
BASE_COMMIT is not a valid SHA.

@ErisDS
Copy link
Copy Markdown
Member

ErisDS commented Mar 4, 2026

🤖 Velo CI Failure Analysis

Classification: 🟠 SOFT FAIL

  • Workflow: CI
  • Failed Step: Integration tests
  • Run: View failed run
    What failed: Test assertion failure in domain warming integration tests
    Why: The root cause of the failure is a test assertion failure in the domain warming integration tests. This is a code issue, as the test is failing due to an incorrect expectation in the test code, not an infrastructure problem.
    Action:
    The author should review the domain warming integration tests and update the expected values to match the actual behavior of the application. Once the test is fixed, the CI build should pass.

@ErisDS
Copy link
Copy Markdown
Member

ErisDS commented Mar 4, 2026

🤖 Velo CI Failure Analysis

Classification: 🟠 SOFT FAIL

  • Workflow: CI
  • Failed Step: Integration tests
  • Run: View failed run
    What failed: Test assertion failure: expected 332 to equal 392 in domain warming integration test
    Why: The root cause of the failure is a test assertion failure in the domain warming integration test. This is a code issue, as the test is checking the expected behavior of the application code and the failure indicates a mismatch between the expected and actual values.
    Action:
    The author should investigate the domain warming functionality and update the test to correctly assert the expected behavior, or fix the underlying code that is causing the test to fail.

- Added `contents: read` permission to job_setup so checkout works in private repos
- Replaced hardcoded `TryGhost/Ghost` repo reference with `github.repository` in PR metadata API call
- Added `github.repository == 'TryGhost/Ghost'` guard to deploy/publish jobs (canary, publish_packages, deploy_tinybird_staging, deploy_tinybird_production, deploy_admin, trigger_cd, create-release-branch) so they only run on the main repo
- Consolidated Docker push strategy: non-main repos use artifact-based image transfer (like fork PRs) so E2E tests still work without GHCR access
- Renamed `is-fork-pr`/`is-fork` to `use-artifact` to accurately reflect the broadened semantics
@kevinansfield kevinansfield force-pushed the fix-ci-for-private-repo branch from f28d814 to 87de8ca Compare March 4, 2026 16:19
@kevinansfield kevinansfield enabled auto-merge (squash) March 4, 2026 16:20
Copy link
Copy Markdown
Contributor

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

♻️ Duplicate comments (1)
.github/workflows/ci.yml (1)

66-68: ⚠️ Potential issue | 🟠 Major

Fail fast when PR metadata lookup cannot resolve BASE_COMMIT.

Line 66 can still produce empty/null on API/auth/rate-limit failures, then downstream nx affected --base=... fails later with a misleading root cause.

Proposed hardening
-          BASE_COMMIT=$(curl --location --request GET 'https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}' --header 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | jq -r .base.sha)
+          API_URL="${{ github.api_url }}/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}"
+          BASE_COMMIT=$(curl --fail --silent --show-error --location "$API_URL" \
+            --header "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
+            --header "Accept: application/vnd.github+json" | jq -r '.base.sha')
+          if [ -z "$BASE_COMMIT" ] || [ "$BASE_COMMIT" = "null" ]; then
+            echo "::error::Unable to resolve BASE_COMMIT from PR metadata"
+            exit 1
+          fi
           echo "Setting BASE_COMMIT to $BASE_COMMIT"
           echo "BASE_COMMIT=$BASE_COMMIT" >> $GITHUB_ENV
#!/bin/bash
# Read-only verification: inspect whether PR metadata step fails fast on API/JSON failures.
sed -n '63,75p' .github/workflows/ci.yml
rg -n --type=yaml -C2 'BASE_COMMIT=.*curl|jq -r \.base\.sha|--fail|github\.api_url|Unable to resolve BASE_COMMIT' .github/workflows/ci.yml
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 66 - 68, The BASE_COMMIT assignment
step can yield empty/null on API/auth/rate-limit failures; update the block that
sets BASE_COMMIT (the line assigning BASE_COMMIT=$(curl ... | jq -r .base.sha)
and the subsequent echo lines) to make the curl call fail fast (e.g. enable
--fail/--show-error) and immediately validate the resolved $BASE_COMMIT value:
if it is empty/null or "null", print a clear error (e.g. "Unable to resolve
BASE_COMMIT from PR metadata") to stderr and exit non‑zero instead of exporting
to GITHUB_ENV and continuing to run downstream commands like nx affected
--base=..., so the workflow fails fast on API/JSON errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.github/workflows/ci.yml:
- Around line 66-68: The BASE_COMMIT assignment step can yield empty/null on
API/auth/rate-limit failures; update the block that sets BASE_COMMIT (the line
assigning BASE_COMMIT=$(curl ... | jq -r .base.sha) and the subsequent echo
lines) to make the curl call fail fast (e.g. enable --fail/--show-error) and
immediately validate the resolved $BASE_COMMIT value: if it is empty/null or
"null", print a clear error (e.g. "Unable to resolve BASE_COMMIT from PR
metadata") to stderr and exit non‑zero instead of exporting to GITHUB_ENV and
continuing to run downstream commands like nx affected --base=..., so the
workflow fails fast on API/JSON errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c3d74e9-1a9f-49e1-b738-b73ac01c8bba

📥 Commits

Reviewing files that changed from the base of the PR and between f28d814dc872d51c119cb10aa7b946bc14eb3f4e and 87de8ca.

📒 Files selected for processing (3)
  • .github/actions/load-docker-image/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/create-release-branch.yml

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.21%. Comparing base (85880f6) to head (87de8ca).
⚠️ Report is 12 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #26686      +/-   ##
==========================================
+ Coverage   73.19%   73.21%   +0.02%     
==========================================
  Files        1530     1532       +2     
  Lines      120510   120518       +8     
  Branches    14574    14576       +2     
==========================================
+ Hits        88209    88240      +31     
+ Misses      31280    31272       -8     
+ Partials     1021     1006      -15     
Flag Coverage Δ
admin-tests 53.87% <ø> (-0.02%) ⬇️
e2e-tests 73.21% <ø> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@kevinansfield kevinansfield merged commit be8c65e into main Mar 4, 2026
34 checks passed
@kevinansfield kevinansfield deleted the fix-ci-for-private-repo branch March 4, 2026 16:44
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.

3 participants