Conversation
📝 WalkthroughWalkthroughThis PR restructures GitHub Actions CI by introducing workspace-scoped change detection ( ChangesCI Workflow Refactoring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (5)
.github/workflows/validate/sdks.yml (1)
18-19: ⚡ Quick winDisable credential persistence in checkout.
Line 19 should set
persist-credentials: falseso tokens are not left in local git config for later steps.Suggested patch
- name: 📥 Checkout Code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false🤖 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/validate/sdks.yml around lines 18 - 19, The checkout step "📥 Checkout Code" currently uses actions/checkout@... without disabling credential persistence; update the checkout step (the step named "📥 Checkout Code" that uses actions/checkout) to add persist-credentials: false so the runner does not store tokens in the local git config for subsequent steps..github/workflows/validate/docs.yml (1)
18-19: ⚡ Quick winDisable credential persistence in checkout.
Line 19 should set
persist-credentials: falseto reduce token exposure in job steps.Suggested patch
- name: 📥 Checkout Code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false🤖 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/validate/docs.yml around lines 18 - 19, The checkout step named "📥 Checkout Code" (uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5) should disable credential persistence by adding the key persist-credentials: false to that step; update the step configuration to include persist-credentials: false so the job does not automatically expose the checkout token to subsequent steps..github/workflows/validate/tools.yml (1)
19-20: ⚡ Quick winHarden both checkout steps by disabling credential persistence.
Lines 20 and 41 should use
persist-credentials: falseto prevent token persistence across subsequent shell steps.Suggested patch
- name: 📥 Checkout Code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false ... - name: 📥 Checkout Code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: falseAlso applies to: 40-41
🤖 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/validate/tools.yml around lines 19 - 20, The GitHub Actions checkout steps (the step named "📥 Checkout Code" and the other checkout step using actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5) must be hardened by adding persist-credentials: false to each step; update both checkout step definitions to include the persist-credentials: false key under their step configuration to prevent the runner from persisting the checkout token into subsequent shell steps..github/workflows/validate/backend.yml (1)
155-157: ⚡ Quick winGate integration tests on fast checks to reduce wasted CI runtime.
test-integrationcurrently waits only forbuild; it still runs even whenverify-mocksorlinthas already failed.Suggested fix
- needs: [build] + needs: [verify-mocks, lint, build]🤖 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/validate/backend.yml around lines 155 - 157, The test-integration job currently only depends on build (job name: test-integration), so it still runs even if earlier fast checks like verify-mocks or lint fail; update the job's needs list to include those fast-check jobs (e.g., add verify-mocks and lint to the needs array for test-integration) so GitHub Actions will gate integration tests on their success and avoid wasted CI runtime..github/workflows/validate/e2e.yml (1)
237-245: ⚡ Quick winFail fast when
Sample Appis missing.Continuing with an empty
sample_app_idpushes a setup failure downstream into opaque Playwright failures. Failing here improves signal.🧭 Proposed refactor
if [ -z "$SAMPLE_APP_ID" ] || [ "$SAMPLE_APP_ID" == "null" ]; then echo "⚠️ Warning: Sample App not found in applications list" echo "Available applications:" echo "$APPS_RESPONSE" | jq -r '(.applications // [])[] | " - \(.name) (\(.id))"' - echo "sample_app_id=" >> $GITHUB_OUTPUT + exit 1 else echo "✓ Sample App ID extracted: $SAMPLE_APP_ID" echo "sample_app_id=$SAMPLE_APP_ID" >> $GITHUB_OUTPUT fi🤖 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/validate/e2e.yml around lines 237 - 245, The script currently continues when SAMPLE_APP_ID is empty which causes downstream opaque failures; update the if branch that checks SAMPLE_APP_ID to fail fast by writing a clear failure message, optionally printing APPS_RESPONSE for debugging, setting sample_app_id in GITHUB_OUTPUT to an empty or omitted value, and immediately exiting with a non-zero status (exit 1); target the conditional that references SAMPLE_APP_ID, APPS_RESPONSE and GITHUB_OUTPUT and replace the current warning branch with the error log + exit 1 so the workflow stops early when Sample App is missing.
🤖 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/pr-builder.yml:
- Around line 154-159: Replace the broad secrets: inherit on the validate-e2e
job with an explicit secrets mapping to only forward the required E2E secrets;
in the validate-e2e job (the job named "validate-e2e" that uses
./.github/workflows/validate/e2e.yml) map each secret individually
(PLAYWRIGHT_BASE_URL, PLAYWRIGHT_ADMIN_USERNAME, PLAYWRIGHT_ADMIN_PASSWORD,
PLAYWRIGHT_TEST_USER_USERNAME, PLAYWRIGHT_TEST_USER_PASSWORD,
SAMPLE_APP_USERNAME, SAMPLE_APP_PASSWORD) so the reusable workflow receives only
those values instead of inheriting all repository secrets.
In @.github/workflows/validate/backend.yml:
- Around line 22-23: The checkout steps currently use
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 without disabling
credential persistence; update each checkout step (the ones using
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 and the other checkout
occurrences) to set persist-credentials: false so Git authentication tokens are
not stored in the workspace Git config, ensuring each checkout step in the
workflow includes that option.
- Line 166: The CI uses floating service image tags "image: postgres:latest" and
"image: redis:latest" which makes tests nondeterministic; update those service
image entries (the lines containing "image: postgres:latest" and "image:
redis:latest") to pinned, explicit versions or digests (for example a specific
major/minor tag like postgres:15-alpine or a sha256 digest) so the workflow uses
a stable, reproducible image; ensure both occurrences are updated and consider
documenting the chosen versions in the workflow comments.
- Line 137: Replace the mutable tag uses: codecov/codecov-action@v5 with the
full commit SHA for the v5 release you intend to use (pin both occurrences of
the action found in the workflow). Locate the two occurrences of "uses:
codecov/codecov-action@v5" and update them to "uses:
codecov/codecov-action@<full-commit-sha>" using the commit SHA from the
codecov-action v5 release page so the workflow references an immutable commit.
In @.github/workflows/validate/e2e.yml:
- Around line 164-175: The readiness liveness probe uses curl without the --fail
flag so HTTP 4xx/5xx responses still count as success; update each curl
invocation that checks https://localhost:8090/health/liveness (the two blocks
around the initial wait loop and the later checks referenced in the comment) to
include --fail (or -f) and -s -k (e.g., curl -sf -k ...) so curl exits non-zero
on HTTP error responses, and apply the same change to the other occurrences
noted (lines referenced as the blocks at 164-175, 266-277, 309-320) to ensure
the workflow fails when the service returns 4xx/5xx.
- Around line 21-22: Three checkout steps currently use actions/checkout@...
without disabling credential persistence; update each checkout step (the ones
using actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5) to include
persist-credentials: false so the workflow token is not left in the runner’s git
config for the job duration; locate the three occurrences (around the blocks at
the earlier, middle, and later checkout steps referenced in the diff) and add
the persist-credentials: false key under each checkout step's configuration.
In @.github/workflows/validate/frontend.yml:
- Around line 22-23: Update each GitHub Actions checkout step that uses
actions/checkout@... (e.g., the steps named "📥 Checkout Code" and the other
checkout occurrences) to include persist-credentials: false in the step's with:
block so credentials are not persisted into the workspace; locate the checkout
steps by the uses: actions/checkout@... entries and add a with:
persist-credentials: false for each occurrence noted in the review.
- Line 245: Replace the mutable action tag "uses: codecov/codecov-action@v5"
with a specific 40-character commit SHA for the v5 release (e.g. "uses:
codecov/codecov-action@<COMMIT_SHA>") wherever that tag appears (the two
occurrences of the string "uses: codecov/codecov-action@v5"); update both usages
so the workflow pins to an immutable commit SHA instead of the floating "v5"
tag.
- Around line 44-57: The jq pipeline that computes REMAINING from AUDIT_RESULT
can fail and produce an empty/invalid REMAINING, so change the logic around the
jq invocation that references AUDIT_RESULT and IGNORE_GHSAS to explicitly check
jq’s exit status (or use jq -e) and treat a jq failure as an error: capture the
jq exit code after the REMAINING assignment and if non-zero either exit with a
non-zero status (fail the job) or set REMAINING to a safe numeric value and then
fail; ensure the code paths around REMAINING (the subsequent [ "$REMAINING" -gt
0 ] test and the error reporting that prints the filtered advisories) only run
when jq succeeded so a jq parse/shape error cannot produce a false "all clear".
---
Nitpick comments:
In @.github/workflows/validate/backend.yml:
- Around line 155-157: The test-integration job currently only depends on build
(job name: test-integration), so it still runs even if earlier fast checks like
verify-mocks or lint fail; update the job's needs list to include those
fast-check jobs (e.g., add verify-mocks and lint to the needs array for
test-integration) so GitHub Actions will gate integration tests on their success
and avoid wasted CI runtime.
In @.github/workflows/validate/docs.yml:
- Around line 18-19: The checkout step named "📥 Checkout Code" (uses:
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5) should disable
credential persistence by adding the key persist-credentials: false to that
step; update the step configuration to include persist-credentials: false so the
job does not automatically expose the checkout token to subsequent steps.
In @.github/workflows/validate/e2e.yml:
- Around line 237-245: The script currently continues when SAMPLE_APP_ID is
empty which causes downstream opaque failures; update the if branch that checks
SAMPLE_APP_ID to fail fast by writing a clear failure message, optionally
printing APPS_RESPONSE for debugging, setting sample_app_id in GITHUB_OUTPUT to
an empty or omitted value, and immediately exiting with a non-zero status (exit
1); target the conditional that references SAMPLE_APP_ID, APPS_RESPONSE and
GITHUB_OUTPUT and replace the current warning branch with the error log + exit 1
so the workflow stops early when Sample App is missing.
In @.github/workflows/validate/sdks.yml:
- Around line 18-19: The checkout step "📥 Checkout Code" currently uses
actions/checkout@... without disabling credential persistence; update the
checkout step (the step named "📥 Checkout Code" that uses actions/checkout) to
add persist-credentials: false so the runner does not store tokens in the local
git config for subsequent steps.
In @.github/workflows/validate/tools.yml:
- Around line 19-20: The GitHub Actions checkout steps (the step named "📥
Checkout Code" and the other checkout step using
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5) must be hardened by
adding persist-credentials: false to each step; update both checkout step
definitions to include the persist-credentials: false key under their step
configuration to prevent the runner from persisting the checkout token into
subsequent shell 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: CHILL
Plan: Pro Plus
Run ID: 84857f0f-475b-4a00-b59a-18565ae7ec83
📒 Files selected for processing (8)
.github/workflows/pr-builder.yml.github/workflows/validate/backend.yml.github/workflows/validate/docs.yml.github/workflows/validate/e2e.yml.github/workflows/validate/frontend.yml.github/workflows/validate/sdks.yml.github/workflows/validate/tools.ymlbuild.ps1
| validate-e2e: | ||
| name: 🎭 E2E | ||
| needs: detect-changes | ||
| if: ${{ needs.detect-changes.outputs.backend == 'true' || needs.detect-changes.outputs.frontend == 'true' || needs.detect-changes.outputs.e2e == 'true' }} | ||
| uses: ./.github/workflows/validate/e2e.yml | ||
| secrets: inherit |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify which secrets are actually referenced by the reusable E2E workflow.
rg -n '\${{\s*secrets\.' .github/workflows/validate/e2e.ymlRepository: thunder-id/thunderid
Length of output: 166
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/e2e.yml"
echo "== File =="
ls -la "$FILE"
echo
echo "== Literal references to reusable secrets (e.g. \${{ secrets.NAME }} ) =="
rg -nF '${{ secrets.' "$FILE" -C 2 || true
echo
echo "== All occurrences of 'secrets.' in the file (broader pattern) =="
rg -n 'secrets\.' "$FILE" -C 1 || true
echo
echo "== Extract unique secret names referenced =="
python3 - <<'PY'
import re, pathlib
p = pathlib.Path(".github/workflows/validate/e2e.yml")
txt = p.read_text()
names = sorted(set(re.findall(r"\$\{\{\s*secrets\.([A-Za-z0-9_]+)\s*\}\}", txt)))
print("\n".join(names) if names else "(none found)")
PYRepository: thunder-id/thunderid
Length of output: 2259
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/e2e.yml"
python3 - <<'PY'
import re, pathlib
txt = pathlib.Path("$FILE").read_text()
# Match patterns like: ${{ secrets.NAME || ... }} and ${ { secrets.NAME }}
names = sorted(set(re.findall(r"\$\{\{\s*secrets\.([A-Za-z0-9_]+)", txt)))
print("\n".join(names) if names else "(none found)")
PYRepository: thunder-id/thunderid
Length of output: 596
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE_E2E=".github/workflows/validate/e2e.yml"
FILE_PR=".github/workflows/pr-builder.yml"
echo "== Reusable workflow secrets references (unique names) =="
python3 - <<PY
import re, pathlib
txt = pathlib.Path("${FILE_E2E}").read_text()
names = sorted(set(re.findall(r"\$\{\{\s*secrets\.([A-Za-z0-9_]+)", txt)))
print("\n".join(names) if names else "(none found)")
PY
echo
echo "== Literal references to reusable secrets in e2e.yml =="
rg -nF '${{ secrets.' "$FILE_E2E" -C 1
echo
echo "== Confirm pr-builder.yml around validate-e2e =="
rg -n 'validate-e2e:' "$FILE_PR" -n -C 3Repository: thunder-id/thunderid
Length of output: 1414
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE_E2E=".github/workflows/validate/e2e.yml"
FILE_PR=".github/workflows/pr-builder.yml"
echo "== All literal occurrences of \${{ secrets. in e2e.yml =="
rg -nF '${{ secrets.' "$FILE_E2E"
echo
echo "== pr-builder.yml validate-e2e job secrets forwarding =="
rg -n "validate-e2e:|secrets:" "$FILE_PR" -n -C 2Repository: thunder-id/thunderid
Length of output: 1220
Scope E2E secrets instead of inheriting all secrets.
File: .github/workflows/pr-builder.yml (lines 154-159)
validate-e2e:
name: 🎭 E2E
needs: detect-changes
if: ${{ needs.detect-changes.outputs.backend == 'true' || needs.detect-changes.outputs.frontend == 'true' || needs.detect-changes.outputs.e2e == 'true' }}
uses: ./.github/workflows/validate/e2e.yml
secrets: inheritsecrets: inherit (line 159) forwards every available secret to the reusable E2E workflow; that workflow only consumes: PLAYWRIGHT_BASE_URL, PLAYWRIGHT_ADMIN_USERNAME, PLAYWRIGHT_ADMIN_PASSWORD, PLAYWRIGHT_TEST_USER_USERNAME, PLAYWRIGHT_TEST_USER_PASSWORD, SAMPLE_APP_USERNAME, SAMPLE_APP_PASSWORD. Prefer explicit secret mapping for least privilege.
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 154-159: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block
(excessive-permissions)
[warning] 158-158: secrets unconditionally inherited by called workflow (secrets-inherit): this reusable workflow
(secrets-inherit)
🤖 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/pr-builder.yml around lines 154 - 159, Replace the broad
secrets: inherit on the validate-e2e job with an explicit secrets mapping to
only forward the required E2E secrets; in the validate-e2e job (the job named
"validate-e2e" that uses ./.github/workflows/validate/e2e.yml) map each secret
individually (PLAYWRIGHT_BASE_URL, PLAYWRIGHT_ADMIN_USERNAME,
PLAYWRIGHT_ADMIN_PASSWORD, PLAYWRIGHT_TEST_USER_USERNAME,
PLAYWRIGHT_TEST_USER_PASSWORD, SAMPLE_APP_USERNAME, SAMPLE_APP_PASSWORD) so the
reusable workflow receives only those values instead of inheriting all
repository secrets.
| - name: 📥 Checkout Code | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 |
There was a problem hiding this comment.
Harden checkout by disabling credential persistence.
These jobs execute repository code after checkout; keeping Git auth in local config is avoidable exposure.
Suggested fix
- name: 📥 Checkout Code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+ with:
+ persist-credentials: falseAlso applies to: 57-58, 74-75, 188-189
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 22-23: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 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/validate/backend.yml around lines 22 - 23, The checkout
steps currently use actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
without disabling credential persistence; update each checkout step (the ones
using actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 and the other
checkout occurrences) to set persist-credentials: false so Git authentication
tokens are not stored in the workspace Git config, ensuring each checkout step
in the workflow includes that option.
| if-no-files-found: error | ||
|
|
||
| - name: 📊 Upload Unit Test Coverage Report to Codecov | ||
| uses: codecov/codecov-action@v5 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check if the file exists and inspect the content around lines 137 and 232
wc -l .github/workflows/validate/backend.ymlRepository: thunder-id/thunderid
Length of output: 107
🏁 Script executed:
# Read the specific lines mentioned in the review
sed -n '130,145p' .github/workflows/validate/backend.yml
sed -n '225,240p' .github/workflows/validate/backend.ymlRepository: thunder-id/thunderid
Length of output: 1234
🏁 Script executed:
# Search for all occurrences of codecov-action in the file to understand context
rg 'codecov-action' .github/workflows/validate/backend.yml -B 2 -A 2Repository: thunder-id/thunderid
Length of output: 396
🌐 Web query:
codecov codecov-action v5 release full commit SHA github
💡 Result:
For codecov/codecov-action version v5 (e.g., the v5.0.0 release), the release tag v5.0.0 corresponds to the commit full SHA: - v5.0.0 full commit SHA: 1ea6f4f4f6a5a0d6c7e4d6f0e3c3d5c7c1e2d3f4 [1] Notes: - The official GitHub releases page for tag v5.0.0 is the authoritative place to map the tag to the underlying commit. [1] If you meant a different v5.x.y release (e.g., v5.4.0), tell me the exact tag and I’ll return its full commit SHA as well.
Citations:
Pin codecov/codecov-action to a full commit SHA instead of @v5.
Version tags like @v5 are mutable and can change over time, weakening supply-chain guarantees in CI. Pin both occurrences (lines 137 and 232) to the full commit SHA of the v5 release you intend to use. For example, v5.0.0 resolves to commit 1ea6f4f4f6a5a0d6c7e4d6f0e3c3d5c7c1e2d3f4. Check the codecov-action releases page for the current v5 release and its corresponding commit SHA.
Suggested fix
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@<full_commit_sha>(Apply to both line 137 and line 232)
📝 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.
| uses: codecov/codecov-action@v5 | |
| uses: codecov/codecov-action@<actual_commit_sha_here> |
🧰 Tools
🪛 zizmor (1.25.2)
[error] 137-137: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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/validate/backend.yml at line 137, Replace the mutable tag
uses: codecov/codecov-action@v5 with the full commit SHA for the v5 release you
intend to use (pin both occurrences of the action found in the workflow). Locate
the two occurrences of "uses: codecov/codecov-action@v5" and update them to
"uses: codecov/codecov-action@<full-commit-sha>" using the commit SHA from the
codecov-action v5 release page so the workflow references an immutable commit.
| fail-fast: false | ||
| services: | ||
| postgres: | ||
| image: postgres:latest |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/backend.yml"
echo "== Checking file exists =="
ls -la "$FILE"
echo
echo "== Showing lines around 160-190 =="
nl -ba "$FILE" | sed -n '140,210p'
echo
echo "== Searching for ':latest' in the workflow =="
rg -n --fixed-string ":latest" "$FILE" || true
echo
echo "== Searching for postgres/redis image references =="
rg -n "image:\s*(postgres|redis):" "$FILE" || trueRepository: thunder-id/thunderid
Length of output: 277
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/backend.yml"
echo "== Showing lines around 160-190 (with line numbers via awk) =="
awk 'NR>=140 && NR<=210 {printf "%d\t%s\n", NR, $0}' "$FILE"
echo
echo "== Searching for ':latest' in the workflow =="
rg -n --fixed-string ":latest" "$FILE" || true
echo
echo "== Searching for postgres/redis image references =="
rg -n "image:\s*(postgres|redis):" "$FILE" || trueRepository: thunder-id/thunderid
Length of output: 3124
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/backend.yml"
echo "== Searching for all ':latest' occurrences in the workflow =="
rg -n ":latest" "$FILE" || true
echo
echo "== Showing exact service blocks for postgres/redis (lines 160-190) =="
awk 'NR>=155 && NR<=190 {printf "%d\t%s\n", NR, $0}' "$FILE"Repository: thunder-id/thunderid
Length of output: 1359
Pin Postgres/Redis service images in integration tests (avoid :latest).
.github/workflows/validate/backend.yml uses floating tags at lines 166 (postgres:latest) and 179 (redis:latest), which can make CI nondeterministic as upstream images change.
Suggested fix
- image: postgres:latest
+ image: postgres:<version>`@sha256`:<digest>
...
- image: redis:latest
+ image: redis:<version>`@sha256`:<digest>🧰 Tools
🪛 zizmor (1.25.2)
[error] 166-166: unpinned image references (unpinned-images): container image is pinned to latest
(unpinned-images)
🤖 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/validate/backend.yml at line 166, The CI uses floating
service image tags "image: postgres:latest" and "image: redis:latest" which
makes tests nondeterministic; update those service image entries (the lines
containing "image: postgres:latest" and "image: redis:latest") to pinned,
explicit versions or digests (for example a specific major/minor tag like
postgres:15-alpine or a sha256 digest) so the workflow uses a stable,
reproducible image; ensure both occurrences are updated and consider documenting
the chosen versions in the workflow comments.
| - name: 📥 Checkout Code | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Show the relevant parts of the workflow with line numbers
FILE=".github/workflows/validate/e2e.yml"
echo "== File: $FILE =="
if [ -f "$FILE" ]; then
nl -ba "$FILE" | sed -n '1,220p'
else
echo "Missing: $FILE"
exit 1
fi
# 2) Find all checkout steps using the pinned v4 SHA in this repo (and confirm if persist-credentials is already set)
echo
echo "== All actions/checkout occurrences with the pinned SHA in .github/workflows =="
rg -n "actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5" .github/workflows -S || true
echo
echo "== Any checkout steps in this file that already set persist-credentials =="
rg -n "actions/checkout@|persist-credentials" "$FILE" -S || true
# 3) Check for any git operations that might require credentials/token after checkout
echo
echo "== git push / auth / GITHUB_TOKEN usage in this file =="
rg -n "git push|GITHUB_TOKEN|persist-credentials|checkout.*token|token:" "$FILE" -S || trueRepository: thunder-id/thunderid
Length of output: 172
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/e2e.yml"
echo "== File: $FILE =="
if [ ! -f "$FILE" ]; then
echo "Missing: $FILE"
exit 1
fi
# Show enough of the workflow to include all checkout steps and nearby context
cat -n "$FILE" | sed -n '1,220p'
echo
echo "== All actions/checkout occurrences with the pinned SHA in .github/workflows =="
rg -n "actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5" .github/workflows -S || true
echo
echo "== Any checkout steps in this file that already set persist-credentials =="
rg -n "persist-credentials" "$FILE" -S || true
rg -n "uses: actions/checkout@" "$FILE" -S || true
echo
echo "== Any git push / auth / GITHUB_TOKEN usage in this file =="
rg -n "git push|GITHUB_TOKEN|persist-credentials|checkout.*token|token:" "$FILE" -S || trueRepository: thunder-id/thunderid
Length of output: 16148
🌐 Web query:
actions/checkout persist-credentials default value
💡 Result:
The default value for the persist-credentials input in the actions/checkout GitHub Action is true [1][2][3]. When this setting is enabled (the default), the action configures the repository's local Git configuration to include the authentication token or SSH key used for the checkout [1][4]. This allows subsequent steps in your workflow to execute authenticated Git commands (such as git fetch or git push) automatically [1][3]. The action is designed to remove these credentials from the Git configuration during post-job cleanup [1][4]. If you wish to prevent the action from configuring these credentials in the local Git configuration, you can explicitly set persist-credentials to false [1][5].
Citations:
- 1: https://github.com/actions/checkout/?tab=readme-ov-file
- 2: actions/checkout@c170eef
- 3: https://github.com/actions/checkout
- 4: https://github.com/actions/checkout/blob/85e6279cec87321a52edac9c87bce653a07cf6c2/README.md
- 5: https://github.com/actions/checkout/tree/v6.0.2?tab=readme-ov-file
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/e2e.yml"
echo "== Line count =="
wc -l "$FILE"
echo
echo "== actions/checkout@... occurrences in e2e.yml =="
rg -n "uses:\s*actions/checkout@" "$FILE" -S
echo
echo "== persist-credentials occurrences in e2e.yml =="
rg -n "persist-credentials" "$FILE" -S || trueRepository: thunder-id/thunderid
Length of output: 462
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/e2e.yml"
echo "== git-related commands in e2e.yml =="
rg -n "(^|\s)git\s+(push|fetch|pull|clone|config)|GITHUB_TOKEN|token:" "$FILE" -S || true
echo
echo "== persist-credentials in the repo (to see if any pattern exists) =="
rg -n "persist-credentials\s*:\s*(false|true)" .github/workflows -S || trueRepository: thunder-id/thunderid
Length of output: 172
Disable credential persistence for all actions/checkout steps in .github/workflows/validate/e2e.yml
.github/workflows/validate/e2e.yml uses actions/checkout@... # v4 in three places without persist-credentials, so the action falls back to its default (persist-credentials: true). Adding persist-credentials: false reduces how long the workflow token is configured in the runner’s local git settings while the job executes repo-provided commands.
🔒 Proposed fix
- name: 📥 Checkout Code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+ with:
+ persist-credentials: false
@@
- name: 📥 Checkout Code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+ with:
+ persist-credentials: false
@@
- name: 📥 Checkout Code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+ with:
+ persist-credentials: falseAlso applies to: 88-89, 116-117
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 21-22: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 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/validate/e2e.yml around lines 21 - 22, Three checkout
steps currently use actions/checkout@... without disabling credential
persistence; update each checkout step (the ones using
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5) to include
persist-credentials: false so the workflow token is not left in the runner’s git
config for the job duration; locate the three occurrences (around the blocks at
the earlier, middle, and later checkout steps referenced in the diff) and add
the persist-credentials: false key under each checkout step's configuration.
| if curl -s -k https://localhost:8090/health/liveness > /dev/null; then | ||
| echo "Server is UP!" | ||
| break | ||
| fi | ||
| echo "Still waiting ($i/60)..." | ||
| sleep 2 | ||
| done | ||
|
|
||
| if ! curl -s -k https://localhost:8090/health/liveness > /dev/null; then | ||
| echo "Server failed to start within 2 minutes" | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/e2e.yml"
echo "== File exists? =="
ls -la "$FILE" || true
echo
echo "== Snippet around lines 150-190 =="
nl -ba "$FILE" | sed -n '150,190p'
echo
echo "== Snippet around lines 250-300 (covers 266-277) =="
nl -ba "$FILE" | sed -n '250,300p'
echo
echo "== Snippet around lines 300-340 (covers 309-320) =="
nl -ba "$FILE" | sed -n '300,340p'
echo
echo "== Find all curl health/liveness probes =="
rg -n --fixed-string "health/liveness" "$FILE" || true
echo
echo "== Find all curl probes to localhost:3000 (if any) =="
rg -n --fixed-string "https://localhost:3000" "$FILE" || trueRepository: thunder-id/thunderid
Length of output: 266
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/e2e.yml"
echo "== Snippet around lines 150-190 =="
awk 'NR>=150 && NR<=190 {printf "%5d %s\n", NR, $0}' "$FILE"
echo
echo "== Snippet around lines 250-300 (covers 266-277) =="
awk 'NR>=250 && NR<=300 {printf "%5d %s\n", NR, $0}' "$FILE"
echo
echo "== Snippet around lines 300-340 (covers 309-320) =="
awk 'NR>=300 && NR<=340 {printf "%5d %s\n", NR, $0}' "$FILE"
echo
echo "== Find all curl health/liveness probes =="
rg -n "curl .*health/liveness" "$FILE" || true
echo
echo "== Find all curl probes to localhost:3000 =="
rg -n "curl .*https://localhost:3000" "$FILE" || true
echo
echo "== Check whether any uses curl -sSf anywhere in this workflow file =="
rg -n "curl .* -sSf" "$FILE" || trueRepository: thunder-id/thunderid
Length of output: 6906
Fail readiness probes on HTTP 4xx/5xx
Current probes use curl -s -k without -f, so HTTP error responses (4xx/5xx) can still satisfy the if condition and let the workflow proceed before the service is actually ready.
File: .github/workflows/validate/e2e.yml
Lines: 164-175
if curl -s -k https://localhost:8090/health/liveness > /dev/null; then
echo "Server is UP!"
break
fi
echo "Still waiting ($i/60)..."
sleep 2
done
if ! curl -s -k https://localhost:8090/health/liveness > /dev/null; then
echo "Server failed to start within 2 minutes"
exit 1
fiAlso applies to: 266-277, 309-320
✅ Proposed fix
- if curl -s -k https://localhost:8090/health/liveness > /dev/null; then
+ if curl -sSf -k https://localhost:8090/health/liveness > /dev/null; then
@@
- if ! curl -s -k https://localhost:8090/health/liveness > /dev/null; then
+ if ! curl -sSf -k https://localhost:8090/health/liveness > /dev/null; then
@@
- if curl -s -k https://localhost:8090/health/liveness > /dev/null; then
+ if curl -sSf -k https://localhost:8090/health/liveness > /dev/null; then
@@
- if ! curl -s -k https://localhost:8090/health/liveness > /dev/null; then
+ if ! curl -sSf -k https://localhost:8090/health/liveness > /dev/null; then
@@
- if curl -s -k https://localhost:3000 > /dev/null 2>&1; then
+ if curl -sSf -k https://localhost:3000 > /dev/null 2>&1; then
@@
- if ! curl -s -k https://localhost:3000 > /dev/null 2>&1; then
+ if ! curl -sSf -k https://localhost:3000 > /dev/null 2>&1; then🤖 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/validate/e2e.yml around lines 164 - 175, The readiness
liveness probe uses curl without the --fail flag so HTTP 4xx/5xx responses still
count as success; update each curl invocation that checks
https://localhost:8090/health/liveness (the two blocks around the initial wait
loop and the later checks referenced in the comment) to include --fail (or -f)
and -s -k (e.g., curl -sf -k ...) so curl exits non-zero on HTTP error
responses, and apply the same change to the other occurrences noted (lines
referenced as the blocks at 164-175, 266-277, 309-320) to ensure the workflow
fails when the service returns 4xx/5xx.
| - name: 📥 Checkout Code | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 |
There was a problem hiding this comment.
Set persist-credentials: false on checkout steps.
All these jobs run project scripts after checkout; disabling persisted git credentials is a safer default.
Suggested fix
- name: 📥 Checkout Code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
+ with:
+ persist-credentials: falseAlso applies to: 71-74, 107-108, 143-144, 185-186, 229-230
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 22-23: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🤖 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/validate/frontend.yml around lines 22 - 23, Update each
GitHub Actions checkout step that uses actions/checkout@... (e.g., the steps
named "📥 Checkout Code" and the other checkout occurrences) to include
persist-credentials: false in the step's with: block so credentials are not
persisted into the workspace; locate the checkout steps by the uses:
actions/checkout@... entries and add a with: persist-credentials: false for each
occurrence noted in the review.
| AUDIT_RESULT=$(npm audit --json --audit-level=high 2>&1) || true | ||
| REMAINING=$(echo "$AUDIT_RESULT" | jq --argjson ignored "$IGNORED_GHSAS" ' | ||
| [.vulnerabilities[].via[] | select(type == "object") | ||
| | select(.severity == "high" or .severity == "critical") | ||
| | select(.url | test($ignored | join("|")) | not) | ||
| ] | length | ||
| ') | ||
| if [ "$REMAINING" -gt 0 ]; then | ||
| echo "❌ Found $REMAINING unignored high/critical advisories in $app:" | ||
| echo "$AUDIT_RESULT" | jq --argjson ignored "$IGNORED_GHSAS" ' | ||
| [.vulnerabilities[].via[] | select(type == "object") | ||
| | select(.severity == "high" or .severity == "critical") | ||
| | select(.url | test($ignored | join("|")) | not) | ||
| ] | unique_by(.url) | .[] | "\(.severity): \(.name) - \(.url)" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the workflow file around the referenced lines
FILE=".github/workflows/validate/frontend.yml"
echo "== File: $FILE =="
python3 - <<'PY'
import itertools
file_path=".github/workflows/validate/frontend.yml"
start=1
end=200
with open(file_path,'r',encoding='utf-8') as f:
for i,line in enumerate(f,1):
if 40 <= i <= 120:
print(f"{i:4d}: {line.rstrip()}")
if i>120:
break
PY
# Extract any other jq/npm audit usage in the repo (to understand broader context)
echo
echo "== Search for npm audit --json usage =="
rg -n "npm audit --json" .github/workflows || true
echo
echo "== Search for jq parsing of .vulnerabilities[].via[] =="
rg -n "\\.vulnerabilities\\[\\]\\.via\\[\\]" .github/workflows || trueRepository: thunder-id/thunderid
Length of output: 4010
🏁 Script executed:
#!/bin/bash
set -euo pipefail
JQ_EXPR='
[.vulnerabilities[].via[] | select(type == "object")
| select(.severity == "high" or .severity == "critical")
| select(.url | test($ignored | join("|")) | not)
] | length
'
# Reuse same jq invocation style as the workflow
JQ_BASE=(jq --argjson ignored '["ghsa-ignored-example"]' "$JQ_EXPR")
echo "== Case 1: Valid JSON with empty vulnerabilities =="
payload='{"vulnerabilities":{}}'
printf '%s\n' "$payload" | "${JQ_BASE[@]}"
echo "exit=$?"
echo "== Case 2: Missing vulnerabilities key =="
payload='{"meta":{}}'
printf '%s\n' "$payload" | "${JQ_BASE[@]}"
echo "exit=$?"
echo "== Case 3: vulnerabilities is null =="
payload='{"vulnerabilities":null}'
printf '%s\n' "$payload" | "${JQ_BASE[@]}"
echo "exit=$?"
echo "== Case 4: via is missing/empty =="
payload='{"vulnerabilities":{"a":{"via":[]}}}'
printf '%s\n' "$payload" | "${JQ_BASE[@]}"
echo "exit=$?"
echo "== Case 5: via is a string (shape mismatch) =="
payload='{"vulnerabilities":{"a":{"via":"not-an-array"}}}'
printf '%s\n' "$payload" | "${JQ_BASE[@]}"
echo "exit=$?"
echo "== Case 6: Invalid JSON (npm audit error text) =="
payload='npm audit failed'
# show jq exit code without stopping
set +e
printf '%s\n' "$payload" | "${JQ_BASE[@]}"
echo "jq_exit=$?"
set -e
echo "== Case 7: via contains object(s) with high/critical but url missing =="
payload='{"vulnerabilities":{"a":{"via":[{"severity":"high","name":"x"}]}}}'
printf '%s\n' "$payload" | "${JQ_BASE[@]}"
echo "exit=$?"Repository: thunder-id/thunderid
Length of output: 243
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/frontend.yml"
echo "== Show relevant workflow context around the audit loop =="
python3 - <<'PY'
import itertools
path=".github/workflows/validate/frontend.yml"
start=1
end=90
with open(path,'r',encoding='utf-8') as f:
for i,line in enumerate(f,1):
if 25 <= i <= 80:
print(f"{i:4d}: {line.rstrip()}")
PY
echo
echo "== Re-run jq shape tests, capturing exit codes without aborting =="
JQ_EXPR='
[.vulnerabilities[].via[] | select(type == "object")
| select(.severity == "high" or .severity == "critical")
| select(.url | test($ignored | join(\"|\")) | not)
] | length
'
IGNORED='["ghsa-ignored-example"]'
run_case () {
local label="$1"
local payload="$2"
echo
echo "-- $label --"
set +e
printf '%s\n' "$payload" | jq --argjson ignored "$IGNORED" "$JQ_EXPR"
local code=$?
echo "exit=$code"
set -e
}
run_case "Case 1: valid JSON with empty vulnerabilities" '{"vulnerabilities":{}}'
run_case "Case 2: missing vulnerabilities key" '{"meta":{}}'
run_case "Case 3: vulnerabilities is null" '{"vulnerabilities":null}'
run_case "Case 4: via is []" '{"vulnerabilities":{"a":{"via":[]}}}'
run_case "Case 5: via is string (shape mismatch)" '{"vulnerabilities":{"a":{"via":"not-an-array"}}}'
run_case "Case 6: via contains object with high but url missing" '{"vulnerabilities":{"a":{"via":[{"severity":"high","name":"x"}]}}}'
echo
echo "== Invalid npm audit text (not JSON) -> jq behavior =="
set +e
printf '%s\n' "npm audit failed" | jq --argjson ignored "$IGNORED" "$JQ_EXPR" >/dev/null
echo "exit=$?"
set -eRepository: thunder-id/thunderid
Length of output: 4763
🏁 Script executed:
#!/bin/bash
set -euo pipefail
IGNORED='["ghsa-ignored-example"]'
# Exact jq program from workflow (no extra escaping)
JQ_PROG='
[.vulnerabilities[].via[] | select(type == "object")
| select(.severity == "high" or .severity == "critical")
| select(.url | test($ignored | join("|")) | not)
] | length
'
echo "== jq exit codes for shape variants (standalone) =="
run_jq () {
local label="$1"
local payload="$2"
echo
echo "-- $label --"
set +e
out="$(printf '%s\n' "$payload" | jq --argjson ignored "$IGNORED" "$JQ_PROG" 2>&1)"
code=$?
printf '%s\n' "$out"
echo "exit=$code"
set -e
}
run_jq "Case 1: vulnerabilities = {}" '{"vulnerabilities":{}}'
run_jq "Case 2: vulnerabilities missing" '{"meta":{}}'
run_jq "Case 3: vulnerabilities = null" '{"vulnerabilities":null}'
run_jq "Case 4: via = []" '{"vulnerabilities":{"a":{"via":[]}}}'
run_jq "Case 5: via = not array" '{"vulnerabilities":{"a":{"via":"not-an-array"}}}'
run_jq "Case 6: high/critical via object but missing url" '{"vulnerabilities":{"a":{"via":[{"severity":"high","name":"x"}]}}}'
run_jq "Case 7: invalid JSON text" 'npm audit failed'
echo
echo "== bash -e behavior when jq fails in command substitution =="
set +e
set -e
test_script () {
local payload="$1"
echo
echo "-- payload: $payload --"
set +e
# emulates: REMAINING=$(echo "$AUDIT_RESULT" | jq ... )
REMAINING=$(printf '%s\n' "$payload" | jq --argjson ignored "$IGNORED" "$JQ_PROG" )
jq_code=$?
echo "jq_exit=$jq_code REMAINING='${REMAINING}'"
set -e
echo "script continued"
}
set +e
test_script '{"vulnerabilities":{}}'
test_script '{"meta":{}}'
test_script '{"vulnerabilities":null}'
test_script '{"vulnerabilities":{"a":{"via":"not-an-array"}}}'
test_script 'npm audit failed'
set -e
echo
echo "done"Repository: thunder-id/thunderid
Length of output: 1468
🏁 Script executed:
#!/bin/bash
set -e
echo "case: REMAINING empty"
REMAINING=''
if [ "$REMAINING" -gt 0 ]; then
echo "in if"
else
echo "in else (no exit)"
fi
echo "after if (should only print if not exited)"Repository: thunder-id/thunderid
Length of output: 217
Fix sample-app npm audit parsing so jq failures don’t lead to a false “all clear”
In .github/workflows/validate/frontend.yml (lines ~44-60), REMAINING=$(echo "$AUDIT_RESULT" | jq ...) doesn’t handle jq parse/shape errors. When jq fails, REMAINING ends up empty; the subsequent [ "$REMAINING" -gt 0 ] doesn’t reliably stop the step, so the job can incorrectly print the ✅ success message (false pass).
Suggested fix
- AUDIT_RESULT=$(npm audit --json --audit-level=high 2>&1) || true
- REMAINING=$(echo "$AUDIT_RESULT" | jq --argjson ignored "$IGNORED_GHSAS" '
- [.vulnerabilities[].via[] | select(type == "object")
- | select(.severity == "high" or .severity == "critical")
- | select(.url | test($ignored | join("|")) | not)
- ] | length
- ')
+ AUDIT_RESULT=$(npm audit --json --audit-level=high 2>&1 || true)
+ REMAINING=$(echo "$AUDIT_RESULT" | jq --argjson ignored "$IGNORED_GHSAS" -r '
+ def expected_vulns:
+ if (.vulnerabilities | type) == "object" then .vulnerabilities
+ else error("unexpected npm audit JSON: missing/invalid .vulnerabilities")
+ end;
+
+ [
+ (expected_vulns | to_entries[] | .value
+ | if (.via | type) == "array" then .via[] else empty end
+ )
+ | select(type == "object")
+ | select((.severity == "high") or (.severity == "critical"))
+ | select((.url // "") | test($ignored | join("|")) | not)
+ ] | length
+ ') || {
+ echo "❌ Unable to parse npm audit JSON for $app"
+ echo "$AUDIT_RESULT"
+ exit 1
+ }🤖 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/validate/frontend.yml around lines 44 - 57, The jq
pipeline that computes REMAINING from AUDIT_RESULT can fail and produce an
empty/invalid REMAINING, so change the logic around the jq invocation that
references AUDIT_RESULT and IGNORE_GHSAS to explicitly check jq’s exit status
(or use jq -e) and treat a jq failure as an error: capture the jq exit code
after the REMAINING assignment and if non-zero either exit with a non-zero
status (fail the job) or set REMAINING to a safe numeric value and then fail;
ensure the code paths around REMAINING (the subsequent [ "$REMAINING" -gt 0 ]
test and the error reporting that prints the filtered advisories) only run when
jq succeeded so a jq parse/shape error cannot produce a false "all clear".
| path: coverage/gate | ||
|
|
||
| - name: 📊 Upload `@thunderid/console` Unit Test Coverage Report to Codecov | ||
| uses: codecov/codecov-action@v5 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/frontend.yml"
echo "== Exists? =="
ls -l "$FILE" || exit 1
echo
echo "== Matching codecov action usage =="
rg -n --hidden --no-ignore-vcs "uses:\s*codecov/codecov-action@" "$FILE" || true
echo
echo "== Show lines around 245 and 257 =="
nl -ba "$FILE" | sed -n '230,270p'Repository: thunder-id/thunderid
Length of output: 391
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/validate/frontend.yml"
echo "== Show lines around 245 and 257 =="
# Prefer cat -n; fallback to sed+grep for line numbers if needed.
if command -v cat >/dev/null 2>&1 && cat -n "$FILE" >/dev/null 2>&1; then
cat -n "$FILE" | sed -n '235,265p'
else
sed -n '235,265p' "$FILE" | nl -ba -w2 -s': ' || true
fi
echo
echo "== Full matching lines (with context) =="
rg -n "uses:\s*codecov/codecov-action@" "$FILE" -n -C 3Repository: thunder-id/thunderid
Length of output: 1945
🌐 Web query:
codecov/codecov-action v5 full_commit_sha
💡 Result:
To set Codecov’s “commit SHA” used by codecov/codecov-action v5, you use the action input override_commit (not full_commit_sha). In action v5, override_commit is defined as: “Commit SHA (with 40 chars)” [1]. The repository input table also lists override_commit as an optional input with that description [2]. Example: - uses: codecov/codecov-action@v5 with: override_commit: ${{ github.sha }} Related (parent SHA) input: commit_parent lets you override the parent SHA: “SHA (with 40 chars) of what should be the parent of this commit.” [3][2]. If you saw “wrong commit sha” behavior, there is an open issue reporting that Action v5 may consider a different SHA than expected even without setting commit_parent or override_commit [4]. So, for your query “codecov/codecov-action v5 full_commit_sha”, the authoritative answer from the v5 action definition is: there is no documented input named full_commit_sha; the documented input to override the commit SHA is override_commit. [1][2]
Citations:
- 1: https://github.com/codecov/codecov-action/blob/v5.5.2/action.yml
- 2: https://github.com/codecov/codecov-action
- 3: codecov/codecov-action@v4.6.0...v5.0.0
- 4: Action v5 considers the wrong commit sha codecov/codecov-action#1651
🌐 Web query:
codecov/codecov-action tag v5 commit SHA
💡 Result:
The v5.0.0 release of codecov/codecov-action is associated with the commit SHA 2a61338c201d4a0468305041048b25d48797f748 [1]. While you can reference tags like v5 in your GitHub Actions workflow file (e.g., uses: codecov/codecov-action@v5), it is considered a best practice to pin your actions to a specific commit SHA to ensure immutability and security [2]. If you intend to pin your workflow to the initial v5.0.0 release, you should use the SHA provided above [1]. For later versions within the v5 release line, you can find the corresponding commit SHAs by viewing the repository's tags or release history on GitHub [3]. Note that the v5 series has been succeeded by v6.0.0 and later versions as of 2026 [4][5].
Citations:
- 1: https://github.com/codecov/codecov-action/releases/tag/v5.0.0
- 2: Action v5 considers the wrong commit sha codecov/codecov-action#1651
- 3: https://github.com/codecov/codecov-action/releases
- 4: https://github.com/codecov/codecov-action/releases/tag/v6.0.0
- 5: https://github.com/codecov/codecov-action/releases/tag/v5.5.4
🌐 Web query:
https://github.com/codecov/codecov-action/tree/v5 commit SHA
💡 Result:
The codecov/codecov-action repository does not have a single, static commit SHA for all of v5 because v5 is a major version (or "tag") that receives updates [1][2]. GitHub Action tags are mutable references; they point to the latest commit associated with that specific tag version [3][4]. To find the specific commit SHA for a v5 release: 1. Visit the official GitHub repository releases page for codecov-action at https://github.com/codecov/codecov-action/releases [1]. 2. Locate the specific v5 release (e.g., v5.0.0, v5.5.2, etc.) [1][2]. 3. Click the tag link or the release commit link to view the associated full 40-character commit SHA [3][5]. Because v5 has evolved through multiple patch releases (e.g., v5.0.1, v5.0.7, v5.5.2) [6][7][2], the commit SHA changes whenever the maintainers update the v5 tag [3]. If you require immutability for security or consistency, you should identify the exact SHA of the specific v5 release version you intend to use and pin your workflow to that 40-character identifier [3][4][5]. For example, an issue recorded in the repository shows a user pinning to a specific v5 SHA: codecov/codecov-action@9688725 [8]. Note that this specific SHA corresponds to an earlier point in the v5 lifecycle and may not represent the current latest v5 release [8][2]. You can verify the current SHA for any tag by using the GitHub CLI command: gh api repos/codecov/codecov-action/git/refs/tags/v5.x.x --jq '.object.sha' [3].
Citations:
- 1: https://github.com/codecov/codecov-action/releases/tag/v5.0.0
- 2: https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md
- 3: https://safeguard.sh/resources/blog/how-to-pin-github-actions-to-shas-correctly
- 4: https://stackoverflow.com/questions/78903499/how-do-i-pin-an-action-to-a-specific-sha
- 5: https://www.stepsecurity.io/blog/pinning-github-actions-for-enhanced-security-a-complete-guide
- 6: codecov/codecov-action@v4...v5
- 7: codecov/codecov-action@v4.6.0...v5.0.7
- 8: Action v5 considers the wrong commit sha codecov/codecov-action#1651
Pin codecov/codecov-action to an immutable commit SHA
.github/workflows/validate/frontend.yml uses the mutable tag codecov/codecov-action@v5 for both uploads (lines 245 and 257). Pin to a specific 40-character commit SHA (for the exact v5.x.y you want) instead of the floating v5 tag.
Suggested fix
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@<40_char_commit_sha_for_v5_x_y>
...
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@<40_char_commit_sha_for_v5_x_y>Also applies to: 257-257
🧰 Tools
🪛 zizmor (1.25.2)
[error] 245-245: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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/validate/frontend.yml at line 245, Replace the mutable
action tag "uses: codecov/codecov-action@v5" with a specific 40-character commit
SHA for the v5 release (e.g. "uses: codecov/codecov-action@<COMMIT_SHA>")
wherever that tag appears (the two occurrences of the string "uses:
codecov/codecov-action@v5"); update both usages so the workflow pins to an
immutable commit SHA instead of the floating "v5" tag.
|
Hey @kavix, Thanks a lot for the PR. If not, lets trigger few PRs agains your forks |
Purpose
The PR builder CI workflow previously built and validated all workspaces (backend, frontend, docs, SDKs, tools, E2E tests) on every pull request, even when only a subset of files changed. This mixed concerns in a single monolithic workflow file, slowed down PR feedback, and consumed unnecessary CI resources.
This PR restructures the PR builder around workspace-scoped validation:
.github/workflows/validate/(backend.yml,frontend.yml,docs.yml,sdks.yml,tools.yml,e2e.yml)..github/workflows/pr-builder.ymlbecomes a lean orchestrator delegating validation to the appropriate reusable workflows.Approach
dorny/paths-filterin.github/workflows/pr-builder.ymlto define path patterns forbackend,frontend,docs,sdks,tools,e2e, andpowershellchanges..github/workflows/validate/triggered viaworkflow_call:backend.yml: Mock verification, backend linting, product/backend coverage build, integration tests (sqlite/postgres/redis).frontend.yml: pnpm/npm audit, frontend linting and formatting check, frontend packages tests, console & gate apps coverage tests.docs.yml: Docusaurus documentation build.sdks.yml: JavaScript SDKs build.tools.yml: Tests/compilation fortools/i18n-extractor(Go) andtools/npx-thunderid(Node/TypeScript).e2e.yml: Playwright E2E tests (including dedicated product build and sample app staging setup).secrets: inherit) to the E2E validator for running tests.Related Issues
Related PRs
Security checks
Summary by CodeRabbit