Skip to content

DAT-21268: Persist vulnerability scan results to scan-results branch#514

Open
jandroav wants to merge 3 commits intomainfrom
DAT-21268-persist-scan-results
Open

DAT-21268: Persist vulnerability scan results to scan-results branch#514
jandroav wants to merge 3 commits intomainfrom
DAT-21268-persist-scan-results

Conversation

@jandroav
Copy link
Contributor

Summary

  • Adds scripts/persist-scan-results.sh to download scan artifacts and commit them to a persistent scan-results branch
  • Adds a persist-results job to the published images scanning workflow that runs after all scans complete
  • Changes contents permission from read to write to allow pushing to the scan-results branch

This enables the Liquibase Security dashboard to read historical scan data via GitHub Contents API, replacing the 7-day artifact retention window.

Branch structure

scan-results/
  manifest.json
  liquibase/liquibase/<tag>/
    trivy-surface.json
    trivy-deep.json
    grype-results.json
    metadata.json
  liquibase/liquibase-secure/<tag>/
    ...

Test plan

  • Trigger workflow manually: gh workflow run "Published Images Vulnerability Scanning"
  • Verify scan-results branch is created with manifest.json and versioned scan data
  • Verify manifest.json lists all scanned images and tags
  • Verify each version directory contains trivy-surface.json, trivy-deep.json, grype-results.json, metadata.json

🤖 Generated with Claude Code

After vulnerability scans complete, a new persist-results job downloads
all scan artifacts and commits them to a scan-results branch. This gives
the Liquibase Security dashboard persistent access to historical scan
data via GitHub Contents API, replacing the 7-day artifact retention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jandroav jandroav requested a review from Copilot March 10, 2026 09:49
@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

Warning

Rate limit exceeded

@jandroav has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 44 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 33b7b963-6e0e-4c11-88a6-6f34fa4e2fd5

📥 Commits

Reviewing files that changed from the base of the PR and between 821fe47 and f698082.

📒 Files selected for processing (2)
  • .github/workflows/trivy-scan-published-images.yml
  • scripts/persist-scan-results.sh
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch DAT-21268-persist-scan-results

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.

@claude
Copy link
Contributor

claude bot commented Mar 10, 2026

Claude finished @jandroav's task in 1m 57s —— View job


Code Review: DAT-21268 - Persist vulnerability scan results

  • Gather context and read changed files
  • Review .github/workflows/trivy-scan-published-images.yml
  • Review scripts/persist-scan-results.sh
  • Post review findings

Overall the implementation is clean and well-structured. Two issues worth addressing:

  1. Hardcoded image prefixes (scripts/persist-scan-results.sh:113-120) — The case statement only handles liquibase-liquibase and liquibase-liquibase-secure. New images added to the scan matrix will be silently skipped. Fix this →

  2. Version sort breaks for non-semver tags (scripts/persist-scan-results.sh:160-164) — tonumber? // 0 maps non-numeric tag segments to 0, so tags like latest or 5.0.1-beta may sort incorrectly in manifest.json. Fix this →

echo "Warning: unknown image prefix: $IMAGE, skipping" >&2
continue
;;
esac
Copy link
Contributor

Choose a reason for hiding this comment

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

The image prefix mapping is hardcoded to only two images. If new images are added to the scanning matrix, they'll be silently skipped (only a warning is printed). Consider making this data-driven or failing loudly on unknown prefixes instead of continue.

.images |= with_entries(
.value |= sort_by(split(".") | map(tonumber? // 0)) | reverse
)
')
Copy link
Contributor

Choose a reason for hiding this comment

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

The version sort uses tonumber? // 0 to handle non-numeric semver parts. Tags like latest, 6.0, or pre-release identifiers (e.g., 5.0.1-beta) will have their non-numeric segments mapped to 0, potentially causing incorrect sort ordering. Consider filtering to pure semver tags before sorting, or using string-based sort as a fallback.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds automation to persist published-image vulnerability scan artifacts into a long-lived scan-results branch (for consumption via GitHub Contents API), extending access beyond the default artifact retention period.

Changes:

  • Introduces scripts/persist-scan-results.sh to collect scan artifacts, update a manifest.json, and push results to scan-results.
  • Updates the published-images scanning workflow to add a persist-results job that runs after scans and pushes results to the branch.
  • Adjusts GitHub Actions contents permissions to enable branch pushes.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
scripts/persist-scan-results.sh New script to assemble artifact outputs, write per-tag metadata, maintain a manifest, and commit/push to scan-results.
.github/workflows/trivy-scan-published-images.yml Adds the persistence job and elevates contents permission to support pushing scan results.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 22 to 24
permissions:
contents: read
contents: write
actions: read
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

Workflow-level contents: write broadens token permissions for all jobs, but only persist-results needs push access. Consider keeping workflow permissions at contents: read and setting job-level permissions (persist-results: permissions: contents: write) to follow least-privilege.

Copilot uses AI. Check for mistakes.
The artifacts directory was passed as a relative path but the script
cd's into a temporary git worktree, breaking the glob. Convert to
absolute path at the start. Also fix grep -c exit code handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@claude
Copy link
Contributor

claude bot commented Mar 10, 2026

Claude finished @jandroav's task in 2m 9s —— View job


Code Review: DAT-21268 - Persist vulnerability scan results

  • Gather context
  • Read changed files
  • Review findings
  • Post review

What's fixed in the latest commit (6cc985e)

ARTIFACTS_DIR is now resolved to an absolute path before cd-ing into the worktree (scripts/persist-scan-results.sh:34). Without this fix the relative path scan-artifacts passed from the workflow would become invalid once cd "$WORKTREE_DIR" runs. Good catch.


Remaining issues

1. Hardcoded image prefixes still not addressed (scripts/persist-scan-results.sh:99–120)

The for PREFIX loop and case statement still only handle liquibase-liquibase and liquibase-liquibase-secure. Any new image added to the scan matrix will be silently skipped with a warning — no failure to alert. Fix this →

2. Non-semver version sort (scripts/persist-scan-results.sh:163)

.value |= sort_by(split(".") | map(tonumber? // 0)) | reverse

tonumber? // 0 maps any non-numeric segment to 0. Tags like latest become [0], and pre-release identifiers like 5.0.1-beta have "1-beta" mapped to 0, causing them to sort as 5.0.0 — before 5.0.1. Fix this →

3. Workflow-level contents: write (.github/workflows/trivy-scan-published-images.yml:22–24)

Only persist-results needs contents: write; the generate-matrix and vulnerability-scan jobs do not. Per least-privilege best practice, move contents: write to a permissions: block on the persist-results job and restore the workflow-level contents: read. (I cannot modify workflow files directly — this requires a manual change.)


Clarification on Copilot's CHANGED_COUNT comment

The Copilot review mentioned || echo 0 producing a double-0, but the current code at line 177 uses || true (not || echo 0). With set -euo pipefail, when grep -c finds no matches it exits 1 and outputs "0"|| true suppresses the non-zero exit without emitting extra output, so CHANGED_COUNT correctly gets "0". No issue here.

Add parentheses around `sort_by(...) | reverse` so that `reverse`
applies to the sorted array inside each image entry, not to the
outer `with_entries` object — which caused "Cannot index object
with number" at runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@claude
Copy link
Contributor

claude bot commented Mar 10, 2026

Claude finished @jandroav's task in 1m 7s —— View job


Code Review: DAT-21268 - Persist vulnerability scan results

  • Gather context
  • Read changed files
  • Review findings
  • Post review

What's fixed in the latest commit (f698082)

The jq operator precedence bug was correctly fixed. Previously, reverse was being applied to each tag's version segments array (making the sort key for 5.0.1 be [1, 0, 5]). Now it's properly parenthesized:

.value |= (sort_by(split(".") | map(tonumber? // 0)) | reverse)

This sorts the full list of tags ascending by semver, then reverses the list to get descending order. Good fix.


Remaining issues

1. Hardcoded image prefixes (scripts/persist-scan-results.sh:99–121) — unchanged

The for PREFIX in "liquibase-liquibase-secure" "liquibase-liquibase" loop and case statement still only handle two images. New images added to the scan matrix will be silently skipped. Fix this →

2. Workflow-level contents: write (.github/workflows/trivy-scan-published-images.yml:22–24) — unchanged

Only persist-results needs contents: write; generate-matrix and vulnerability-scan jobs do not. Move the permission to a job-level permissions: block on persist-results and restore the workflow-level permission to contents: read. (I cannot modify workflow files directly — please make this change manually.)


Notes on non-issues

  • Non-semver sort: latest maps to [0] which sorts to the end after reverse — this is correct and acceptable behavior.
  • CHANGED_COUNT || true: Current code correctly uses || true to suppress grep -c non-zero exit when there are no matches. No issue.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants