Extract staging jobs into a separate workflow#4701
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (5)
WalkthroughAdds four reusable GitHub Actions workflows (bootstrap, build images, scan images, staging) and updates the main CI/CD workflow to call these workflows for staging and production pipelines. ChangesWorkflow Extraction & Refactoring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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/run-ci-cd.yaml:
- Around line 240-253: The scan job is currently using the unversioned Docker
Hub tags (backend_tag/frontend_tag) instead of the canonical versioned ECR URIs
produced by the build; modify the build workflow (run-build-images.yaml) to emit
outputs for the final ECR image URIs (e.g. outputs: ecr_backend_uri and
ecr_frontend_uri populated with the full
{AWS_ACCOUNT_ID}.dkr.ecr...:{release_version} values) and then change the
consumer in this workflow (the step that uses
./.github/workflows/run-build-images.yaml and the downstream scan job) to read
and pass those outputs (needs.<build_job>.outputs.ecr_backend_uri and
needs.<build_job>.outputs.ecr_frontend_uri) into the scanner instead of using
the hard-coded backend_tag/frontend_tag fields so the scanner validates the
exact versioned artifacts.
In @.github/workflows/run-scan-images.yaml:
- Around line 22-31: Validate that inputs release_tag and sbom_artifact_name are
non-empty before executing branches that use them: when upload_to_release is
true ensure release_tag is provided before running the gh release upload command
(and fail the job or skip with a clear error if empty), and when
upload_to_release is false ensure sbom_artifact_name is provided before calling
actions/upload-artifact (again fail or skip with an explanatory message if
empty); update the workflow conditionals or add pre-check steps that reference
the input variables release_tag, sbom_artifact_name and the flag
upload_to_release to prevent invoking gh release upload or upload-artifact with
empty values.
In @.github/workflows/run-staging.yaml:
- Line 125: The RELEASE_VERSION environment variable is being set from a
non-existent job output `needs.set-release-version.outputs.release_version`;
replace that with the workflow input `release_version` provided via
`workflow_call`. Update the value for RELEASE_VERSION to reference the input
(e.g., use the `${{ inputs.release_version }}` syntax) so the job uses the
declared workflow input instead of the undefined
`needs.set-release-version.outputs.release_version`.
- Around line 53-55: The staging deployment "if" guard is unreachable because it
checks github.event_name values even though this workflow is invoked via
workflow_call; remove the event_name checks so the if only evaluates the
repository (github.repository == 'OWASP/Nest') or other valid conditions. Also
fix the undefined job reference: either add a job named set-release-version that
sets outputs.release_version or replace uses of
needs.set-release-version.outputs.release_version with the workflow input (e.g.,
inputs.release_version) or an output from an existing job such as
needs.bootstrap-nest-staging-infrastructure.outputs.release_version; update all
references to release_version accordingly.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7f588e64-7b6e-481e-ba06-f1528dd1b1f4
📒 Files selected for processing (5)
.github/workflows/run-bootstrap-infrastructure.yaml.github/workflows/run-build-images.yaml.github/workflows/run-ci-cd.yaml.github/workflows/run-scan-images.yaml.github/workflows/run-staging.yaml
| uses: ./.github/workflows/run-build-images.yaml | ||
| with: | ||
| release_version: ${{ needs.set-release-version.outputs.release_version }} | ||
| aws_role_session_name: GitHubActions-BuildProductionImages | ||
| aws_role_name: nest-production-terraform | ||
| backend_tag: owasp/nest:backend-production | ||
| backend_cache_ref: owasp/nest:backend-production-cache | ||
| backend_uid: '1002' | ||
| backend_gid: '1002' | ||
| backend_ecr_repo: nest-production-backend | ||
| frontend_tag: owasp/nest:frontend-production | ||
| frontend_cache_ref: owasp/nest:frontend-production-cache | ||
| frontend_ecr_repo: nest-production-frontend | ||
| secrets: inherit |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== production caller wiring =="
sed -n '230,273p' .github/workflows/run-ci-cd.yaml | nl -ba
echo
echo "== build workflow outputs / published image refs =="
sed -n '1,260p' .github/workflows/run-build-images.yaml | nl -ba | \
rg -n -C2 '(workflow_call|outputs:|backend_ecr_repo|frontend_ecr_repo|release_version|docker/build-push-action|tags:|push:)'
echo
echo "== scan workflow inputs / image consumption =="
sed -n '1,260p' .github/workflows/run-scan-images.yaml | nl -ba | \
rg -n -C2 '(workflow_call|inputs:|backend_image_name|frontend_image_name|trivy|image-ref|sbom)'Repository: OWASP/Nest
Length of output: 146
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check if the files exist
echo "=== Checking file existence ==="
ls -la .github/workflows/run-ci-cd.yaml .github/workflows/run-build-images.yaml .github/workflows/run-scan-images.yaml 2>&1 || true
# Get line counts to understand file sizes
echo
echo "=== File line counts ==="
wc -l .github/workflows/run-ci-cd.yaml .github/workflows/run-build-images.yaml .github/workflows/run-scan-images.yaml 2>&1 || trueRepository: OWASP/Nest
Length of output: 516
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the production caller wiring (lines 230-273)
echo "=== Production caller wiring (lines 230-273 of run-ci-cd.yaml) ==="
sed -n '230,273p' .github/workflows/run-ci-cd.yaml 2>&1 || echo "File not found or error reading"Repository: OWASP/Nest
Length of output: 1708
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the build workflow file to find outputs and image refs
echo "=== Build workflow (run-build-images.yaml) - first 300 lines ==="
head -300 .github/workflows/run-build-images.yaml 2>&1 || echo "File not found"Repository: OWASP/Nest
Length of output: 7317
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the scan workflow file to find inputs and image consumption
echo "=== Scan workflow (run-scan-images.yaml) - first 300 lines ==="
head -300 .github/workflows/run-scan-images.yaml 2>&1 || echo "File not found"Repository: OWASP/Nest
Length of output: 2846
Wire the scan workflow to consume the canonical image URIs from the build workflow.
The build workflow publishes images to two registries: unversioned Docker Hub tags (owasp/nest:backend-production, owasp/nest:frontend-production) and versioned ECR URIs ({AWS_ACCOUNT_ID}.dkr.ecr.{AWS_REGION}.amazonaws.com/nest-production-backend:{release_version}, etc.). The scan workflow is hard-coded to scan only the unversioned Docker Hub tags, which are overwritten on each release and lack traceability to the canonical versioned artifacts.
The build workflow must expose the final ECR image URIs as outputs, and the scan workflow must be updated to consume those outputs instead of the parallel, unversioned tag scheme. This ensures the scan validates the exact same versioned images that are published to production.
🤖 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/run-ci-cd.yaml around lines 240 - 253, The scan job is
currently using the unversioned Docker Hub tags (backend_tag/frontend_tag)
instead of the canonical versioned ECR URIs produced by the build; modify the
build workflow (run-build-images.yaml) to emit outputs for the final ECR image
URIs (e.g. outputs: ecr_backend_uri and ecr_frontend_uri populated with the full
{AWS_ACCOUNT_ID}.dkr.ecr...:{release_version} values) and then change the
consumer in this workflow (the step that uses
./.github/workflows/run-build-images.yaml and the downstream scan job) to read
and pass those outputs (needs.<build_job>.outputs.ecr_backend_uri and
needs.<build_job>.outputs.ecr_frontend_uri) into the scanner instead of using
the hard-coded backend_tag/frontend_tag fields so the scanner validates the
exact versioned artifacts.
| release_tag: | ||
| description: Release tag for uploading SBOMs | ||
| required: false | ||
| type: string | ||
| default: '' | ||
| sbom_artifact_name: | ||
| description: Artifact name for SBOMs | ||
| required: false | ||
| type: string | ||
| default: '' |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n .github/workflows/run-scan-images.yamlRepository: OWASP/Nest
Length of output: 3392
Validate conditional upload inputs to prevent runtime failures.
release_tag and sbom_artifact_name default to empty strings but are used unconditionally in their respective branches. If upload_to_release is true with an empty release_tag (line 75), the gh release upload command fails. If upload_to_release is false with an empty sbom_artifact_name (line 83), the upload-artifact action fails.
Add input validation before these steps execute:
Proposed fix
- name: Generate SBOM for frontend image
run: |
make sbom-frontend-image FRONTEND_IMAGE_NAME=${{ inputs.frontend_image_name }}
+ - name: Validate upload inputs
+ run: |
+ if [[ "${{ inputs.upload_to_release }}" == "true" && -z "${{ inputs.release_tag }}" ]]; then
+ echo "release_tag is required when upload_to_release=true" >&2
+ exit 1
+ fi
+ if [[ "${{ inputs.upload_to_release }}" != "true" && -z "${{ inputs.sbom_artifact_name }}" ]]; then
+ echo "sbom_artifact_name is required when upload_to_release=false" >&2
+ exit 1
+ fi
+
- name: Upload SBOMs to release
- if: inputs.upload_to_release
+ if: ${{ inputs.upload_to_release && inputs.release_tag != '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ inputs.release_tag }}" \
backend-sbom-${{ env.RELEASE_VERSION }}.cdx.json \
frontend-sbom-${{ env.RELEASE_VERSION }}.cdx.json
- name: Upload SBOMs as artifact
- if: ${{ !inputs.upload_to_release }}
+ if: ${{ !inputs.upload_to_release && inputs.sbom_artifact_name != '' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ inputs.sbom_artifact_name }}🤖 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/run-scan-images.yaml around lines 22 - 31, Validate that
inputs release_tag and sbom_artifact_name are non-empty before executing
branches that use them: when upload_to_release is true ensure release_tag is
provided before running the gh release upload command (and fail the job or skip
with a clear error if empty), and when upload_to_release is false ensure
sbom_artifact_name is provided before calling actions/upload-artifact (again
fail or skip with an explanatory message if empty); update the workflow
conditionals or add pre-check steps that reference the input variables
release_tag, sbom_artifact_name and the flag upload_to_release to prevent
invoking gh release upload or upload-artifact with empty values.
| if: | | ||
| (github.repository == 'OWASP/Nest' && | ||
| (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/run-staging.yaml"
echo "== Trigger types defined in workflow =="
rg -n '^\s*on:|^\s*workflow_call:|^\s*workflow_dispatch:|^\s*schedule:' "$FILE"
echo
echo "== Event-name guards in jobs =="
rg -n 'github\.event_name' "$FILE"
echo
echo "Expected: workflow defines workflow_call, while guarded jobs require schedule/workflow_dispatch."Repository: OWASP/Nest
Length of output: 425
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/run-staging.yaml"
echo "== Searching for set-release-version job definition =="
rg -n 'set-release-version' "$FILE"
echo
echo "== All job definitions in workflow =="
rg -n '^\s*[a-zA-Z0-9_-]+:' "$FILE" | grep -E '^\s*[0-9]+:\s*[a-zA-Z0-9_-]+:\s*$'
echo
echo "== References to needs object =="
rg -n 'needs\.' "$FILE"Repository: OWASP/Nest
Length of output: 1150
🏁 Script executed:
#!/bin/bash
FILE=".github/workflows/run-staging.yaml"
echo "== Context around line 125 and deploy-staging-nest job =="
sed -n '63,130p' "$FILE"Repository: OWASP/Nest
Length of output: 2703
Fix unreachable staging deployment conditions and undefined job reference.
This workflow is triggered only via workflow_call (line 4), but the conditions at lines 69-71 check for schedule or workflow_dispatch events—which will never occur. The if guards must be updated to remove the event-name checks.
Additionally, line 125 references needs.set-release-version.outputs.release_version, but no set-release-version job is defined in this workflow. Only bootstrap-nest-staging-infrastructure is listed as a dependency. Either add the set-release-version job or provide the release_version from the workflow input.
Suggested fix
bootstrap-nest-staging-infrastructure:
name: Prepare Staging Infrastructure
if: github.repository == 'OWASP/Nest'
deploy-staging-nest:
name: Plan and Deploy Nest Staging
if: github.repository == 'OWASP/Nest'
needs:
- bootstrap-nest-staging-infrastructure
- set-release-version
env:
RELEASE_VERSION: ${{ needs.set-release-version.outputs.release_version }}or if set-release-version is not available, use the workflow input:
RELEASE_VERSION: ${{ needs.set-release-version.outputs.release_version }}
+ RELEASE_VERSION: ${{ inputs.release_version }}🤖 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/run-staging.yaml around lines 53 - 55, The staging
deployment "if" guard is unreachable because it checks github.event_name values
even though this workflow is invoked via workflow_call; remove the event_name
checks so the if only evaluates the repository (github.repository ==
'OWASP/Nest') or other valid conditions. Also fix the undefined job reference:
either add a job named set-release-version that sets outputs.release_version or
replace uses of needs.set-release-version.outputs.release_version with the
workflow input (e.g., inputs.release_version) or an output from an existing job
such as needs.bootstrap-nest-staging-infrastructure.outputs.release_version;
update all references to release_version accordingly.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feature/ci-cd-optimization #4701 +/- ##
===========================================================
Coverage 98.80% 98.80%
===========================================================
Files 528 528
Lines 16805 16805
Branches 2364 2364
===========================================================
Hits 16605 16605
Misses 115 115
Partials 85 85
Flags with carried forward coverage won't be shown. Click here to find out more. Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
6 issues found across 5 files
Confidence score: 2/5
- High-confidence, high-severity workflow regressions make this risky to merge as-is:
run-bootstrap-infrastructure.yamlcan apply staging bootstrap changes to production IAM/policies because target environment isn’t passed into tfvars. run-staging.yamlreferencesneeds.set-release-versionthat does not exist, so staging deploys may ignore the caller-provided release version and produce incorrect releases.run-ci-cd.yamlandrun-scan-images.yamlintroduce additional operational risk by dropping environment bindings/protections, making release asset upload non-idempotent on reruns, and requesting broadercontents: writepermissions than needed.- Pay close attention to
.github/workflows/run-bootstrap-infrastructure.yaml,.github/workflows/run-staging.yaml,.github/workflows/run-ci-cd.yaml, and.github/workflows/run-scan-images.yaml- environment targeting, release-version wiring, protection/secret scoping, and rerun/permission safety need correction before merge.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/run-bootstrap-infrastructure.yaml">
<violation number="1" location=".github/workflows/run-bootstrap-infrastructure.yaml:54">
P1: Pass the target environment into this bootstrap tfvars. As written, Terraform falls back to `['staging', 'production']`, so the staging bootstrap job also updates production IAM roles and policies.</violation>
</file>
<file name=".github/workflows/run-staging.yaml">
<violation number="1" location=".github/workflows/run-staging.yaml:41">
P2: This scan path only needs read access because `upload_to_release` is hard-coded to `false`; granting `contents: write` unnecessarily broadens the token for the called workflow.</violation>
<violation number="2" location=".github/workflows/run-staging.yaml:125">
P1: Use the reusable workflow input here; `needs.set-release-version` does not exist in this workflow, so the staging deploy will not use the caller's release version.</violation>
</file>
<file name=".github/workflows/run-scan-images.yaml">
<violation number="1" location=".github/workflows/run-scan-images.yaml:44">
P2: This reusable job always requests `contents: write`, even for staging runs that only upload artifacts. Split the release upload into a separate write-scoped job or keep this scan job read-only so the scan steps do not run with an unnecessarily powerful token.</violation>
<violation number="2" location=".github/workflows/run-scan-images.yaml:75">
P1: This release upload is not idempotent: rerunning the workflow for the same tag will fail once these SBOM asset names already exist. Add `--clobber` or delete the old assets before uploading.</violation>
</file>
<file name=".github/workflows/run-ci-cd.yaml">
<violation number="1" location=".github/workflows/run-ci-cd.yaml:240">
P1: These reusable-workflow calls drop the original staging/production environment binding for the extracted build/bootstrap jobs, so environment protections and environment-scoped secrets/vars no longer apply.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".github/workflows/run-scan-images.yaml">
<violation number="1" location=".github/workflows/run-scan-images.yaml:84">
P2: Keep the release tag quoted here; unquoted shell expansion can drop an empty optional tag and misparse the upload command.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/run-build-images.yaml:
- Around line 186-194: The CI job currently sets timeout-minutes: 10 for the
Docker build/report step ("Create Docker image size report"), which can be too
short for cold caches; update the job's timeout-minutes value from 10 to a
higher value (suggest 15 or 20) to reduce intermittent build timeouts by
increasing the overall job timeout for the Docker image build steps.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: f645d8d3-b66d-4f92-9259-9187eb3002a8
📒 Files selected for processing (3)
.github/workflows/run-build-images.yaml.github/workflows/run-ci-cd.yaml.github/workflows/run-scan-images.yaml
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/run-ci-cd.yaml:
- Around line 117-139: Caller workflow is passing five secrets to the reusable
workflow that aren't declared in the callee's on.workflow_call.secrets; update
the reusable workflow run-staging.yaml by adding BOOTSTRAP_AWS_ACCESS_KEY_ID,
BOOTSTRAP_AWS_SECRET_ACCESS_KEY, BOOTSTRAP_TF_STATE_BUCKET_NAME, GITHUB_TOKEN,
and TF_STATE_BUCKET_NAME under its on.workflow_call.secrets: block (or remove
those secrets from the caller if they aren't needed) so the secret bindings
match between the caller and the reusable workflow.
In @.github/workflows/run-scan-images.yaml:
- Around line 86-89: Quote the $RELEASE_TAG variable in the gh release upload
invocation to prevent word-splitting/globbing (i.e., use "$RELEASE_TAG" instead
of $RELEASE_TAG) so the command gh release upload "$RELEASE_TAG"
backend-sbom-$RELEASE_VERSION.cdx.json frontend-sbom-$RELEASE_VERSION.cdx.json
safely handles tags with spaces or special characters.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 422bab08-3141-4ac7-a3e9-fc27a4695b86
📒 Files selected for processing (5)
.github/workflows/run-bootstrap-infrastructure.yaml.github/workflows/run-build-images.yaml.github/workflows/run-ci-cd.yaml.github/workflows/run-scan-images.yaml.github/workflows/run-staging.yaml
There was a problem hiding this comment.
1 issue found across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 3 files (changes from recent commits).
Requires human review: Auto-approval blocked by 8 unresolved issues from previous reviews.
Re-trigger cubic
There was a problem hiding this comment.
0 issues found across 3 files (changes from recent commits).
Requires human review: Auto-approval blocked by 5 unresolved issues from previous reviews.
Re-trigger cubic
|




Proposed change
Resolves #4684
Add the PR description here.
Checklist
make check-testlocally: all warnings addressed, tests passed