Skip to content

fix(validate-go-project): scan for vulnerabilities on the default branch - #779

Merged
devantler merged 7 commits into
mainfrom
claude/govulncheck-main-coverage-6373
Jul 28, 2026
Merged

fix(validate-go-project): scan for vulnerabilities on the default branch#779
devantler merged 7 commits into
mainfrom
claude/govulncheck-main-coverage-6373

Conversation

@devantler

@devantler devantler commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🤖 Generated by the Agentic Engineer

Why

A Go repository's default branch could report green while its vulnerability scan had not run — so the portfolio learned about a live vulnerability from unrelated pull requests failing, rather than from the branch that was actually vulnerable.

This is not theoretical. An advisory published against a dependency KSail already pinned made KSail's main vulnerable without a single line changing. main kept showing green, and the first anyone saw of it was two unrelated pull requests going red for something their authors had not done.

A second, smaller gap sits next to it: changing the allowlist that decides which advisories are accepted skipped the very scan that reads it.

What

The allowlist fix applies immediately. Editing the allowlist now re-runs the vulnerability scan — and only that scan, so an administrative decision to accept an advisory can't be held up by an unrelated failure elsewhere in the repo.

Default-branch scanning ships switched off. The scan can now run on every default-branch invocation rather than only when Go files happen to change — which is what closes the gap, because a scan's answer depends on the published advisory database as much as on the code. But turning that on means a default branch that was green can go red without anyone changing anything, in every consumer at once. So it is an opt-in setting, defaulting to off: a consumer that passes nothing behaves exactly as it does today.

Rolling it out consumer by consumer, then making it the default and removing the switch, is tracked in #788.

Notes for review

  • No consumer has to change anything to merge this, and nothing behaves differently until a consumer opts in.
  • Both gaps are trigger conditions rather than logic, so the existing self-tests could never see them and they could regress silently. A contract test now pins them, and every one of its assertions was individually disabled to confirm it actually fails when the property is broken.
  • The dead-code job carries the same pull-request-only gate and is deliberately left alone — its verdict depends only on the code, so it has no equivalent way to go stale.

Fixes #758
Part of #757
Part of devantler-tech/ksail#6373

The govulncheck job carried `github.event_name == 'pull_request'`, so it never
ran on the default branch in any consumer repo. A vulnerability scan's verdict
depends on the vulnerability database as well as the diff, so an advisory
published after a merge makes already-merged, unchanged code vulnerable — and a
pull_request-only scan structurally cannot report that.

Measured on ksail: GO-2026-6061 (reachable, google.golang.org/grpc < v1.82.1)
was published 2026-07-27T15:30Z against a dependency main already pinned. main
kept reporting green; the advisory surfaced only as a failure on unrelated PRs.

Separately, `.govulncheck-allow.txt` was missing from the `go` path filter, so a
commit whose only purpose is to change which advisories the gate accepts skipped
the gate that reads it (ksail c3522e89: allowlist-only push to main → scan
skipped).

Both are trigger-condition regressions that leave a consumer's default branch
silently unscanned, so a contract self-test now asserts them.

Part of devantler-tech/ksail#6373
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

MegaLinter analysis: Success

Descriptor Linter Files Fixed Errors Warnings Elapsed time
✅ COPYPASTE jscpd yes no no 0.49s
✅ GO revive 2 0 0 11.73s
✅ REPOSITORY betterleaks yes no no 0.65s
✅ REPOSITORY checkov yes no no 20.25s
✅ REPOSITORY gitleaks yes no no 0.19s
✅ REPOSITORY git_diff yes no no 0.04s
✅ REPOSITORY osv-scanner yes no no 0.61s
✅ REPOSITORY secretlint yes no no 0.9s
✅ REPOSITORY syft yes no no 3.3s
✅ REPOSITORY trivy yes no no 13.04s
✅ REPOSITORY trivy-sbom yes no no 0.21s
✅ REPOSITORY trufflehog yes no no 5.18s

Notices

📣 MegaLinter 9.5.0 is out! Discover the new features and security recommendations in the release announcement. (Skip this info by defining SECURITY_SUGGESTIONS: false)

See detailed reports in MegaLinter artifacts

Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)

  • Documentation: Custom Flavors
  • Command: npx mega-linter-runner@9.6.0 --custom-flavor-setup --custom-flavor-linters COPYPASTE_JSCPD,GO_REVIVE,REPOSITORY_CHECKOV,REPOSITORY_GIT_DIFF,REPOSITORY_GITLEAKS,REPOSITORY_BETTERLEAKS,REPOSITORY_OSV_SCANNER,REPOSITORY_SECRETLINT,REPOSITORY_SYFT,REPOSITORY_TRIVY,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@devantler: I’ll review the changes in #779.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Go path filter now includes root and nested .govulncheck-allow.txt files. The Govulncheck job runs on default-branch pushes even without Go-file changes, while retaining repository exclusions. A new shell test validates the gate structure and path-filter coverage. CI runs this test and includes its result in the required-check aggregation.

Possibly related issues

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately summarizes the main change: enabling default-branch vulnerability scans.
Description check ✅ Passed The description is clearly related to the workflow changes and explains the default-branch scan and allowlist trigger updates.

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.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit reported "Review limit reached" at 44ca39bd84 (stated window: 25 minutes) — its ack said it would review, but the summary carries the rate limited by coderabbit.ai marker, so no gate-satisfying artifact exists at this head. Recording the completed no-gate outcome and advancing to Codex rather than waiting out the window.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44ca39bd84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/validate-go-project.yaml Outdated
Comment thread .github/workflows/validate-go-project.yaml Outdated
Comment thread .github/workflows/validate-go-project.yaml
Comment thread .github/tests/test-govulncheck-main-coverage.sh Outdated
Codex review on #779 found the fix was incomplete in the same way the fix
itself describes, plus a guard that could not detect it.

Removing `event_name == 'pull_request'` let the default branch reach the
scan, but `needs.changes.outputs.go` still gated it. A default-branch push
touching no Go path (a README edit) therefore leaves the scan skipped, and
the branch keeps reporting green while a newly-published advisory already
applies to its unchanged code — the same time-vs-diff error one level down.
The path filter is now OR-ed with a default-branch clause: on the default
branch every invocation scans; on pull requests and topic branches the path
filter still applies, so per-PR cost is unchanged.

The guard asserted only the ABSENCE of one forbidden expression, so it
passed a workflow restricted to `workflow_dispatch` while printing a
success message claiming default-branch coverage (verified against the
previous test). It now asserts the intended condition positively: no
event_name equality at all, a default-branch clause present, and the path
filter OR-ed with it rather than AND-ed alongside. Six ablations, each RED.

`.govulncheck-allow.txt` also matched only at the repo root, so an
allowlist edit inside a nested module selected by `working-directory`
skipped the scan that reads it; the nested pattern is now covered too.
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@devantler: I’ll review the changes in #779.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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/tests/test-govulncheck-main-coverage.sh:
- Around line 33-42: Add a negative self-test alongside the existing test flow
in the script, invoking it with a deliberately invalid fixture workflow kept
outside the gate’s normal scan scope. Assert that the guard exits non-zero and
emits the expected finding, covering event-gated if conditions or disallowed go
filters while preserving the current positive self-test.
- Around line 93-110: Extend Check 3 in the test’s top-level condition
validation to whitelist ref-related predicates: reject any top-level conjunct
referencing github.ref or github.event_name unless it belongs to the OR-group
containing the default_branch clause. Preserve the existing path-filter grouping
checks, and ensure predicates such as ref exclusions or release-only checks
cause the guard to fail.

In @.github/workflows/validate-go-project.yaml:
- Around line 387-390: Update the remaining self-repository exclusion checks in
the workflow’s downstream job conditions to use “devantler-tech/actions” instead
of “devantler-tech/reusable-workflows”. Keep the existing changes and
default-branch conditions unchanged so dependency failures remain visible in the
aggregate result.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c281ad98-3890-4c5a-bf78-f490814e08c5

📥 Commits

Reviewing files that changed from the base of the PR and between f18cce6 and 5b92234.

📒 Files selected for processing (3)
  • .github/tests/test-govulncheck-main-coverage.sh
  • .github/workflows/ci.yaml
  • .github/workflows/validate-go-project.yaml
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
.github/tests/**

📄 CodeRabbit inference engine (AGENTS.md)

Place deliberately bad fixtures for gating-workflow tests outside the gate's normal scan scope.

Files:

  • .github/tests/test-govulncheck-main-coverage.sh
.github/workflows/*.yaml

📄 CodeRabbit inference engine (AGENTS.md)

.github/workflows/*.yaml: Keep all GitHub Actions workflows under .github/workflows/.
Reusable workflows must use the workflow_call trigger.
Pin every remote action reference to a full commit SHA with a version comment; do not use remote self-references.
Include step-security/harden-runner as the first step of every reusable-workflow job, with egress-policy: audit.
Set top-level workflow permissions to {} and grant permissions per job.
Set persist-credentials: false on actions/checkout unless the job must push.
Workflows used as organization-level rulesets must include pull_request and merge_group triggers in addition to workflow_call.
For reusable workflows referencing a sibling action, check out the workflow repository at ${{ job.workflow_sha }} into .devantler-tech-actions, then invoke the action locally; remove the checkout before workspace-wide scans or commits.
New reusable-workflow jobs, steps, or behaviors must be behind a default-off boolean opt-in input and guarded with if: ${{ inputs.<enable-x> }}.
When a workflow supports both workflow_dispatch and workflow_call, normalize boolean inputs with inputs.<enable-x> == true || inputs.<enable-x> == 'true'.
Test both enabled and disabled states of every feature flag with CI test jobs.
Gating reusable workflows must have both a passing self-test and a failing-input self-test that verifies the expected finding; non-gating workflows require happy-path coverage.
Preserve tested consumer contracts, such as validate-go-project.yaml honoring .govulncheck-allow.txt; update the corresponding self-tests whenever the implementation changes.

Files:

  • .github/workflows/ci.yaml
  • .github/workflows/validate-go-project.yaml
.github/workflows/ci.yaml

📄 CodeRabbit inference engine (AGENTS.md)

.github/workflows/ci.yaml: Add a test job for every action and reusable workflow, using local paths such as uses: ./<action> or uses: ./.github/workflows/<workflow>.yaml.
Wire every new test job into ci-required-checks both through needs: and the job-results input of aggregate-job-checks.

Files:

  • .github/workflows/ci.yaml
🔇 Additional comments (4)
.github/workflows/validate-go-project.yaml (1)

75-82: LGTM!

.github/tests/test-govulncheck-main-coverage.sh (2)

113-136: LGTM!


46-47: 🩺 Stability & Availability

No change needed for yq -r.

The repository uses mikefarah yq consistently with -r, and scalar extraction already returns raw strings from the installed runner image.

			> Likely an incorrect or invalid review comment.
.github/workflows/ci.yaml (1)

2235-2253: LGTM!

Also applies to: 2745-2745, 2836-2836

Comment thread .github/tests/test-govulncheck-main-coverage.sh
Comment thread .github/tests/test-govulncheck-main-coverage.sh Outdated
Comment thread .github/workflows/validate-go-project.yaml Outdated
…guard

CodeRabbit review on #779.

The trigger guard is itself a gate, and its checks are structural string
analysis over a GitHub expression — unusually easy to make silently vacuous.
Per this repo's both-tests convention it now has a blocks-on-bad-input
counterpart: five fixtures, one per failure mode, each asserted to fail WITH
THE EXPECTED MESSAGE so an operational error cannot false-pass. It also
asserts the guard still passes the real workflow, so a reject-everything
guard fails too. That sanity arm immediately caught a real regression while
being written.

Check 3 did not catch the "ref predicate that excludes the default branch"
case the file's own header claims to catch: a top-level
`&& github.ref != 'refs/heads/main'` satisfied every assertion while making
default-branch runs unreachable. Top-level ref predicates are now rejected —
the legitimate default-branch clause lives inside the OR-group and has
already been stripped by that point, so anything left is an extra conjunct.

The group extraction used a regex bounded with `[^()]*`, which cannot match a
group containing nested parentheses and so silently returned the innermost
one. Replaced with a balance scan that takes the outermost group.

The govulncheck gate's default-branch arm now tests `go == 'false'` rather
than being unconditional. An empty output means the `changes` job did not run
at all; only an explicit 'false' proves the filter ran and found no Go paths.
Keying on the explicit value keeps the gate independent of how skipped-needs
propagate, which is the substance of the third review finding.
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Verification record

Exercised the gate's real behaviour rather than reasoning about it. A trigger condition has no cheap runtime surface — I cannot push to a consumer's main to watch it — so the closest observation is to evaluate the actual expression, parsed from the workflow (never re-typed, which would only test my transcription), across the context matrix that matters. Substitution is fail-closed: anything that does not reduce to booleans prints UNREDUCED instead of guessing. That guard fired on my first attempt and caught a broken substitution, so the numbers below are from a run that provably reduced.

Before (44ca39b) → after (30552d6), same evaluator, same contexts:

Context ref go before after
consumer PR, Go changed refs/pull/1/merge true RUN RUN
consumer PR, no Go change refs/pull/1/merge false skip skip
consumer MAIN, Go changed refs/heads/main true RUN RUN
consumer MAIN, README-only push refs/heads/main false skip RUN
consumer MAIN, changes skipped refs/heads/main (empty) skip skip
consumer topic branch, no Go refs/heads/topic false skip skip
archived reusable-workflows refs/heads/main true skip skip

Exactly one row changes, and it is the defect row. That is the whole claim of this PR, stated as a diff rather than a description:

  • the default branch now scans when a non-Go commit lands, which is when a newly-published advisory would otherwise go unreported;
  • per-PR cost is provably unchanged — both pull-request rows are identical, so no developer waits longer;
  • the changes-skipped row stays skip, which is the third review finding closed by construction rather than by relying on how skipped-needs propagate;
  • the self-exclusion still holds.

Also verified in real CI at 30552d6: [Test] Govulncheck - Default-Branch & Allowlist Trigger Coverage and the new [Test] Govulncheck Trigger Guard - Blocks On Bad Input both pass, alongside the four pre-existing govulncheck guards (no regression). lint-ci-coverage-parity passes locally, confirming the ci-required-checks needs ↔ job-results sync. actionlint findings: 8 at base, 8 at head, identical — measured on both files at the same paths, since a linter pointed outside its expected path reports a false zero. shellcheck clean on both scripts.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

@devantler: I’ll review the updated changes in #779.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit reports "Review limit reached … we couldn't start this review", next review available in 41 minutes. Its command reply said "Review finished" — that is the acknowledgement, not the outcome; the limit is stated only in the summary body. No review object or inline comment was produced at this head.

A stated retry window still means the lane is not delivering now, so advancing to Codex rather than parking a finished change behind a provider's quota.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 30552d63c2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/validate-go-project.yaml Outdated
Comment thread .github/workflows/validate-go-project.yaml
…n opt-in input

The default-branch scan changes behaviour in every consumer repository at once,
and its intended consequence is that a green default branch can go red. Per
AGENTS.md (*Shipping a new capability behind an opt-in flag*) it now ships behind
`scan-default-branch`, default false, to be rolled out caller-by-caller before the
default flips and the input is removed (#788).

With the flag off, the gate reproduces the behaviour shipped today: the scan runs
on pull requests when the path filter matches, and nowhere else.

Also isolates the allowlist trigger. `.govulncheck-allow.txt` was added to the
shared `go` filter, whose output go-mod-tidy, golangci-lint, deadcode, the test
matrix and coverage all consume — so an allowlist-only commit ran all of them in
every consumer, and an administrative risk-acceptance could be blocked by an
unrelated pre-existing failure. It now has its own `govulncheck` filter output,
OR-ed into this job alone.

The trigger guard is re-aimed at the flagged shape. It no longer rejects any
`event_name` equality (the flag-off arm legitimately carries one) but rejects a
TOP-LEVEL one, and adds the backward-compatibility property directly: every
OR-arm the input does not gate must still be restricted to pull requests, so a
caller that passes nothing cannot acquire new behaviour. The input must also
exist, be boolean, and default to false.

Fixtures are now generated from one base by generate.sh, so each differs from
`good.yaml` only in its defect, and `good.yaml` is asserted to PASS — a guard
that rejects everything fails the suite just as a guard that accepts everything
does. Every assertion and helper was ablated independently; all 16 go red.
…arameters

Adding the `scan-default-branch` both-states self-test reintroduced actions#587
in a new form. The two [Test] jobs call this reusable workflow from the SAME
caller workflow on the SAME ref, differing only by one input, so they computed an
identical concurrency group and `cancel-in-progress` made the second cancel the
first: nine jobs of the flag-off invocation were cancelled and CI - Required
Checks went red.

`github.workflow` separates a caller's self-test from the org-required direct
run, but it cannot separate two calls from the same caller. The group now also
carries the invocation's inputs, so two invocations differing in any input are
different logical invocations. Only reruns of the same invocation still supersede.

Adding a discriminator can only split groups further, never merge two that were
separate, so this direction of change cannot reintroduce #587 itself.

The lockstep guard is strengthened accordingly: it now reads the workflow_call
input list and requires EVERY input to appear in the group, so a future input
that distinguishes two invocations cannot be added without also distinguishing
their groups. Verified positive, plus three ablations (drop the flag, drop
pr-owner, drop github.workflow) each going red, and a fourth confirming that
adding a new input while leaving the group alone fails the guard.
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== PR metadata =='
gh pr view 779 --repo devantler-tech/actions \
  --json number,title,baseRefName,headRefName,headRefOid,files \
  --jq '{number, title, baseRefName, headRefName, headRefOid, files: [.files[].path]}'

echo
echo '== Merge-base and changed files =='
base_ref="$(gh pr view 779 --repo devantler-tech/actions --json baseRefOid --jq '.baseRefOid')"
printf 'base=%s\nhead=%s\n' "$base_ref" "$(git rev-parse HEAD)"
git diff --name-status "$base_ref"...HEAD
git diff --check "$base_ref"...HEAD

echo
echo '== Structural outlines =='
ast-grep outline .github/workflows/validate-go-project.yaml --items all || true
ast-grep outline .github/workflows/ci.yaml --items all || true

echo
echo '== Changed workflow and test content =='
git diff --unified=80 "$base_ref"...HEAD -- \
  .github/workflows/validate-go-project.yaml \
  .github/workflows/ci.yaml \
  .github/tests/test-govulncheck-main-coverage.sh \
  .github/tests/test-govulncheck-trigger-guard-blocks-on-bad-input.sh

Length of output: 82853


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Relevant workflow sections =='
nl -ba .github/workflows/validate-go-project.yaml | sed -n '1,180p'
nl -ba .github/workflows/validate-go-project.yaml | sed -n '330,470p'

echo
echo '== Contract-test harnesses =='
nl -ba .github/tests/test-govulncheck-main-coverage-blocks.sh
printf '\n-- main guard (remainder / closing section) --\n'
nl -ba .github/tests/test-govulncheck-main-coverage.sh | sed -n '150,310p'

echo
echo '== Fixture inventory and content =='
for f in .github/tests/govulncheck-main-coverage-fixture/*; do
  printf '\n--- %s ---\n' "$f"
  nl -ba "$f"
done

echo
echo '== All reusable-workflow call sites and input references =='
rg -n -C 5 --glob '*.y*ml' \
  '(uses:[[:space:]]*\./\.github/workflows/validate-go-project\.yaml|uses:[[:space:]]*devantler-tech/actions/\.github/workflows/validate-go-project\.yaml|scan-default-branch)' \
  .

echo
echo '== README changes =='
git diff --unified=50 "$(git merge-base HEAD origin/main)"...HEAD -- README.md

echo
echo '== YAML parse / expression reference checks =='
yq -e '.' .github/workflows/validate-go-project.yaml >/dev/null
yq -e '.' .github/workflows/ci.yaml >/dev/null
rg -n -C 2 'govulncheck|changes\.outputs\.govulncheck|changes\.outputs\.go|scan-default-branch' \
  .github/workflows/validate-go-project.yaml .github/workflows/ci.yaml

Length of output: 1726


🏁 Script executed:

#!/bin/bash
set -euo pipefail

number() { awk '{printf "%6d\t%s\n", NR, $0}'; }
slice() { awk -v start="$2" -v end="$3" 'NR >= start && NR <= end {printf "%6d\t%s\n", NR, $0}' "$1"; }

echo '== Relevant workflow sections =='
slice .github/workflows/validate-go-project.yaml 1 180
slice .github/workflows/validate-go-project.yaml 330 470

echo
echo '== Contract-test harnesses =='
number < .github/tests/test-govulncheck-main-coverage-blocks.sh
printf '\n-- main guard (remainder / closing section) --\n'
slice .github/tests/test-govulncheck-main-coverage.sh 150 310

echo
echo '== Fixture inventory and content =='
for f in .github/tests/govulncheck-main-coverage-fixture/*; do
  printf '\n--- %s ---\n' "$f"
  number < "$f"
done

echo
echo '== All reusable-workflow call sites and input references =='
rg -n -C 5 --glob '*.y*ml' \
  '(uses:[[:space:]]*\./\.github/workflows/validate-go-project\.yaml|uses:[[:space:]]*devantler-tech/actions/\.github/workflows/validate-go-project\.yaml|scan-default-branch)' \
  .

echo
echo '== README changes =='
base_ref="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
git diff --unified=50 "$base_ref"...HEAD -- README.md

echo
echo '== YAML parse / expression reference checks =='
yq -e '.' .github/workflows/validate-go-project.yaml >/dev/null
yq -e '.' .github/workflows/ci.yaml >/dev/null
echo 'YAML parse: OK'
rg -n -C 2 'govulncheck|changes\.outputs\.govulncheck|changes\.outputs\.go|scan-default-branch' \
  .github/workflows/validate-go-project.yaml .github/workflows/ci.yaml

Length of output: 74479


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base_ref="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"

echo '== README diff =='
git diff --unified=80 "$base_ref"...HEAD -- README.md

echo
echo '== CI additions and required-check aggregation =='
git diff --unified=35 "$base_ref"...HEAD -- .github/workflows/ci.yaml | \
  sed -n '/test-validate-go-project-scan-default-branch/,+90p; /test-govulncheck-main-coverage:/,+130p; /ci-required-checks:/,+230p'

echo
echo '== Reusable-workflow invocations and all new-input references =='
grep -RInE \
  '(validate-go-project\.ya?ml|scan-default-branch)' \
  --include='*.yaml' --include='*.yml' .github README.md || true

echo
echo '== YAML parser checks =='
yq -e '.' .github/workflows/validate-go-project.yaml >/dev/null
yq -e '.' .github/workflows/ci.yaml >/dev/null
echo 'YAML parse: OK'

echo
echo '== PR checks and review comments =='
gh pr view 779 --repo devantler-tech/actions \
  --json statusCheckRollup,reviews,comments \
  --jq '{
    checks: [.statusCheckRollup[]? | {name: .name, conclusion: .conclusion, status: .status}],
    reviews: [.reviews[]? | {author: .author.login, state: .state, body: .body}],
    comments: [.comments[]? | {author: .author.login, body: .body}]
  }'

echo
echo '== Whitespace errors =='
git diff --check "$base_ref"...HEAD

Length of output: 35807


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Pull request status =='
gh pr view 779 --repo devantler-tech/actions \
  --json headRefOid,mergeable,reviewDecision,statusCheckRollup \
  --jq '{
    head: .headRefOid,
    mergeable,
    reviewDecision,
    checks: [
      .statusCheckRollup[]? |
      {
        name: .name,
        status: .status,
        conclusion: .conclusion,
        detailsUrl: .detailsUrl
      }
    ]
  }'

echo
echo '== Existing reviews and inline review comments =='
gh api "repos/devantler-tech/actions/pulls/779/reviews" \
  --jq '.[] | {user: .user.login, state: .state, body: .body}' || true
gh api "repos/devantler-tech/actions/pulls/779/comments" \
  --jq '.[] | {user: .user.login, path: .path, line: .line, body: .body}' || true

Length of output: 80901


@devantler Reviewed the latest head. The workflow gate, dedicated govulncheck filter, negative-fixture coverage, and CI aggregation look sound; the relevant new CI checks are passing.

One documentation follow-up: README.md still states that .govulncheck-allow.txt must be “at the repo root.” The workflow now also supports a nested allowlist in the selected working-directory, so please update that sentence to document both supported locations.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit acknowledged the request for 9d7eb17b712886aae1839d11b3e361ec724fb595 at 16:07:00Z and produced no review object, inline
finding, or updated summary at that head in the ~18 minutes since. Its measured envelope on this PR
earlier today was ~3 minutes. No quota marker is present, so this is a stall rather than a stated
rate limit. Advancing to Codex per the lane order; if CodeRabbit lands a result later it still
satisfies the gate first.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d7eb17b71

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/validate-go-project.yaml Outdated
Comment thread .github/workflows/validate-go-project.yaml
Comment thread .github/tests/test-govulncheck-main-coverage.sh
…an at the right allowlist

Codex review on #779 raised three findings at 9d7eb17; all three verified against the
code and fixed here.

P1 — the allowlist trigger was not opt-in. Adding `needs.changes.outputs.govulncheck`
to the pull-request arm scheduled the 20-minute scan for every consumer the moment this
merges, including callers that pass nothing. AGENTS.md requires new behaviour behind a
default-off input with zero change for callers that omit it, so the allowlist term is now
AND-ed with `inputs.scan-default-branch` and the input's description covers both
behaviours it gates.

P1 — the scan did not read the allowlist that triggered it. The new
`**/.govulncheck-allow.txt` pattern lets a nested module's allowlist fire the scan, but
`allow-file` was a bare checkout-root-relative literal. The action resolves its path
inputs from the checkout root, not from `work-dir` — pinned by the allowlist self-test in
ci.yaml, which passes `work-dir: .github/tests/govulncheck-allowlist` alongside a fully
prefixed `allow-file`. `defaults.run.working-directory` does not close the gap either: it
governs `run:` steps only, so the detection step saw the nested file while the scanner was
sent to the root. It is now composed from `inputs.working-directory`, matching the sibling
`go-version-file` input.

P2 — the guard proved neither property. Measured: the suite passed unchanged on the
pre-fix head while printing "nothing new runs unopted, and allowlist edits trigger the
scan that reads them", so it asserted exactly the two properties that were violated. Two
checks are added. Check 9 requires the innermost parenthesised group holding the allowlist
term to also hold the flag, AND-ed — a co-occurrence test would accept
`(flag || govulncheck == 'true')`, where the trigger fires with the flag off. Check 10
requires `allow-file` to be composed from `inputs.working-directory`.

Both are pinned by new bad fixtures (`allowlist-trigger-not-flag-gated`,
`allow-file-not-working-dir-relative`) so the blocks test proves they bite in CI, not only
locally. The fixture generator now models the action step, and every fixture's
pull-request arm carries the gated form so each still differs from the control in exactly
one field — except `flag-not-referenced`, which keeps the ungated arm on purpose, since
injecting the flag there would stop the assertion it exists to pin from firing.

Verified: both self-tests green; each fix independently ablated back to RED with the
matching diagnostic; actionlint 3 findings at head against 3 at the merge-base (all
pre-existing, lines 790/873/874); shellcheck clean.
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

All three Codex findings at 9d7eb17b71 are fixed in 6d357b4. Each was verified against the code
before acting, and each fix was ablated back to RED to prove the guard now bites.

P1 — allowlist trigger not opt-in. Valid. Confirmed the input is new in this PR and defaults to
false, so gating the allowlist term behind it gives every existing caller literally zero behaviour
change, which is what AGENTS.md requires. The term is now AND-ed with inputs.scan-default-branch,
and the input description covers both behaviours it gates.

P1 — nested allowlist not read by the scanner. Valid, and confirmed from this repo rather than
assumed: the allowlist self-test in ci.yaml passes work-dir: .github/tests/govulncheck-allowlist
alongside a fully prefixed allow-file: .github/tests/govulncheck-allowlist/.govulncheck-allow.txt,
which pins that the action resolves its path inputs from the checkout root, not from work-dir.
defaults.run.working-directory does not cover it either — it governs run: steps only, so the
detection step resolved the nested allowlist while the scanner was sent to the root. allow-file is
now composed from inputs.working-directory, matching the sibling go-version-file input.

P2 — the guard proved neither property. Valid, and worse than reported. Measured directly: the
suite passed unchanged on the pre-fix head, while printing "nothing new runs unopted, and
allowlist edits trigger the scan that reads them ✅"
— it asserted exactly the two properties that
were being violated.

Two checks were added rather than one. Check 9 requires the innermost parenthesised group holding the
allowlist term to also hold the flag, AND-ed — a co-occurrence test would accept
(flag || govulncheck == 'true'), where the trigger fires with the flag off, which is the shape the
finding warned about. Check 10 requires allow-file to be composed from inputs.working-directory.

Both are pinned by new bad fixtures — allowlist-trigger-not-flag-gated and
allow-file-not-working-dir-relative — so the blocks test proves they bite in CI, not just locally.
The generator now models the action step, and every fixture's pull-request arm carries the gated form
so each still differs from the control in exactly one field. One deliberate exception:
flag-not-referenced keeps the ungated arm, because injecting the flag there would make the flag
referenced and stop the very assertion that fixture exists to pin.

Verification: both self-tests green; gating ablated → check 9 fires; allow-file ablated → check
10 fires; actionlint 3 findings at head vs 3 at the merge-base (all pre-existing, lines 790/873/874);
shellcheck clean.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

All three findings from the previous review are fixed in 6d357b4 and their threads resolved. CI at
this head: 98 of 100 checks complete, 0 non-green; the two still running are the unrelated
Delete Workflow Runs tests.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

base_ref="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
printf '== Revisions ==\nbase=%s\nhead=%s\n' "$base_ref" "$(git rev-parse HEAD)"

printf '\n== Changed files and whitespace ==\n'
git diff --name-status "$base_ref"...HEAD
git diff --check "$base_ref"...HEAD

printf '\n== Changed workflow and contract-test diff ==\n'
git diff --unified=100 "$base_ref"...HEAD -- \
  .github/workflows/validate-go-project.yaml \
  .github/workflows/ci.yaml \
  .github/tests/test-govulncheck-main-coverage.sh \
  .github/tests/test-govulncheck-main-coverage-blocks.sh \
  .github/tests/govulncheck-main-coverage-fixture

printf '\n== Workflow outline ==\n'
ast-grep outline .github/workflows/validate-go-project.yaml --items all || true

printf '\n== Relevant workflow sections ==\n'
rg -n -C 12 \
  'scan-default-branch|govulncheck|allow-file|working-directory|paths-filter|\.govulncheck-allow' \
  .github/workflows/validate-go-project.yaml .github/workflows/ci.yaml

printf '\n== Contract-test sources and fixtures ==\n'
fd -t f . .github/tests/govulncheck-main-coverage-fixture .github/tests 2>/dev/null | \
  sort | grep -E 'govulncheck-(main-coverage|trigger-guard)|govulncheck-main-coverage-fixture' | \
  while IFS= read -r file; do
    printf '\n--- %s ---\n' "$file"
    nl -ba "$file"
  done

printf '\n== Reusable workflow call sites and input usages ==\n'
rg -n -C 6 --glob '*.yml' --glob '*.yaml' \
  '(uses:[[:space:]]*(\./)?\.github/workflows/validate-go-project\.yaml|scan-default-branch:|allow-file:|working-directory:)' \
  .

printf '\n== YAML parse ==\n'
yq -e '.' .github/workflows/validate-go-project.yaml >/dev/null
yq -e '.' .github/workflows/ci.yaml >/dev/null
echo 'YAML parse: OK'

printf '\n== Current PR status and review artifacts ==\n'
gh pr view 779 --repo devantler-tech/actions \
  --json headRefOid,mergeable,reviewDecision,statusCheckRollup \
  --jq '{
    head: .headRefOid,
    mergeable,
    reviewDecision,
    checks: [.statusCheckRollup[]? | {name, status, conclusion}]
  }'
gh api 'repos/devantler-tech/actions/pulls/779/comments' \
  --jq '.[] | {user: .user.login, path, line, body}' || true

Length of output: 181822


🏁 Script executed:

#!/bin/bash
set -euo pipefail

number() { awk '{printf "%6d  %s\n", NR, $0}'; }

printf '== Contract guard ==\n'
number < .github/tests/test-govulncheck-main-coverage.sh

printf '\n== Negative-fixture runner ==\n'
number < .github/tests/test-govulncheck-main-coverage-blocks.sh

printf '\n== Fixture contents ==\n'
for file in .github/tests/govulncheck-main-coverage-fixture/*; do
  [ -f "$file" ] || continue
  printf '\n--- %s ---\n' "$file"
  number < "$file"
done

printf '\n== Relevant CI job definitions ==\n'
awk 'NR >= 2000 && NR <= 2050 {printf "%6d  %s\n", NR, $0}
     NR >= 2408 && NR <= 2462 {printf "%6d  %s\n", NR, $0}
     NR >= 2735 && NR <= 2785 {printf "%6d  %s\n", NR, $0}
     NR >= 2920 && NR <= 3080 {printf "%6d  %s\n", NR, $0}' \
  .github/workflows/ci.yaml

printf '\n== All validate-go-project reusable-workflow callers ==\n'
rg -n -C 8 --glob '*.yaml' --glob '*.yml' \
  'uses:[[:space:]]*(\./)?\.github/workflows/validate-go-project\.yaml' .

printf '\n== Guard-related symbols outside the guard and fixtures ==\n'
rg -n -C 3 \
  'scan-default-branch|outputs\.govulncheck|allow-file:.*working-directory|govulncheck-main-coverage' \
  .github --glob '!tests/test-govulncheck-main-coverage.sh' \
  --glob '!tests/test-govulncheck-main-coverage-blocks.sh' \
  --glob '!tests/govulncheck-main-coverage-fixture/**'

printf '\n== YAML parsing ==\n'
yq -e '.' .github/workflows/validate-go-project.yaml >/dev/null
yq -e '.' .github/workflows/ci.yaml >/dev/null
echo 'YAML parse: OK'

printf '\n== Current PR checks/review decision ==\n'
gh pr view 779 --repo devantler-tech/actions \
  --json headRefOid,mergeable,reviewDecision,statusCheckRollup \
  --jq '{
    head: .headRefOid,
    mergeable,
    reviewDecision,
    checks: [.statusCheckRollup[]? | {name, status, conclusion}]
  }'

Length of output: 107001


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== Reusable workflow references ==\n'
rg -n -C 4 --glob '*.yaml' --glob '*.yml' \
  'validate-go-project\.yaml' . || true

printf '\n== Workflow-call input declarations ==\n'
yq -r '.["on"].workflow_call.inputs | to_entries[] |
  "\(.key): type=\(.value.type), default=\(.value.default // "<none>")"' \
  .github/workflows/validate-go-project.yaml

printf '\n== YAML parse ==\n'
yq -e '.' .github/workflows/validate-go-project.yaml >/dev/null
yq -e '.' .github/workflows/ci.yaml >/dev/null
echo 'YAML parse: OK'

printf '\n== Current PR status ==\n'
gh pr view 779 --repo devantler-tech/actions \
  --json headRefOid,mergeable,reviewDecision,statusCheckRollup \
  --jq '{
    head: .headRefOid,
    mergeable,
    reviewDecision,
    non_green: [
      .statusCheckRollup[]? |
      select(
        .status != "COMPLETED"
        or (.conclusion != "SUCCESS" and .conclusion != "SKIPPED" and .conclusion != "NEUTRAL")
      ) |
      {name, status, conclusion}
    ],
    govulncheck_checks: [
      .statusCheckRollup[]? |
      select(.name | test("Govulncheck|Validate Go Project - Default-Branch"; "i")) |
      {name, status, conclusion}
    ]
  }'

printf '\n== Existing inline review comments at latest head ==\n'
gh api 'repos/devantler-tech/actions/pulls/779/comments' \
  --jq '.[] | {user: .user.login, commit_id, path, line, body}' || true

Length of output: 1811


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '== Current PR status ==\n'
gh pr view 779 --repo devantler-tech/actions \
  --json headRefOid,mergeable,reviewDecision,statusCheckRollup \
  --jq '{
    head: .headRefOid,
    mergeable,
    reviewDecision,
    non_green: [
      .statusCheckRollup[]? |
      select(
        .status != "COMPLETED"
        or (.conclusion != "SUCCESS" and .conclusion != "SKIPPED" and .conclusion != "NEUTRAL")
      ) |
      {name, status, conclusion}
    ],
    govulncheck_checks: [
      .statusCheckRollup[]? |
      select(.name | test("Govulncheck|Validate Go Project - Default-Branch"; "i")) |
      {name, status, conclusion}
    ]
  }'

printf '\n== Inline review comments ==\n'
gh api 'repos/devantler-tech/actions/pulls/779/comments' \
  --jq '.[] | {user: .user.login, commit_id, path, line, body}' || true

printf '\n== Review states ==\n'
gh api 'repos/devantler-tech/actions/pulls/779/reviews' \
  --jq '.[] | {user: .user.login, commit_id, state, body}' || true

Length of output: 1403


🏁 Script executed:

#!/bin/bash
set -euo pipefail

gh pr view 779 --repo devantler-tech/actions \
  --json headRefOid,mergeable,reviewDecision,statusCheckRollup \
  --jq '{
    head: .headRefOid,
    mergeable,
    reviewDecision,
    non_green: [
      .statusCheckRollup[]? |
      select(
        .status != "COMPLETED"
        or (.conclusion != "SUCCESS" and .conclusion != "SKIPPED" and .conclusion != "NEUTRAL")
      ) |
      {name: (.name // "<unnamed>"), status, conclusion}
    ],
    relevant_checks: [
      .statusCheckRollup[]? |
      select((.name // "") | test("Govulncheck|Validate Go Project - Default-Branch"; "i")) |
      {name, status, conclusion}
    ]
  }'

printf '\n== Inline review comments ==\n'
gh api 'repos/devantler-tech/actions/pulls/779/comments' \
  --jq '.[] | {user: .user.login, commit_id, path, line, body}' || true

Length of output: 58139


@devantler Reviewed 6d357b4ca7d29abe138f87d6550429c29fa01c0e — no new findings.

The corrected default-off opt-in, dedicated allowlist filter, working-directory-relative allow-file, failure-mode fixtures, and required-check wiring are consistent. The relevant Govulncheck contract/negative tests and the opted-in reusable-workflow test are all passing, and the PR is mergeable.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

CodeRabbit produced no gate-satisfying artifact at this head — advancing to Codex.

It was requested at 6d357b4ca7 at 17:07Z and acknowledged at 17:09Z, but ~2.5h later there is still no review object at this head, and its only auto-generated summary comment predates the head and carries no between <base> and <head> range — so it is a walkthrough, not a review completion. Per the lane ladder that is a completed no-gate rather than a finding to fix.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d357b4ca7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci.yaml
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Codex's P2 at this head is answered and its thread resolved. The resolution changed no file by design — the requested pre-merge exercise cannot exist in a pull_request context — so the head is deliberately unchanged and no empty commit was created to move it.

Skipping CodeRabbit on account-wide evidence rather than on this PR's history. Its per-developer quota is exhausted right now: a request on monorepo#2532 at 19:36:14Z came back at 19:36:56Z with Review limit reached … we couldn't start this review. The limit is per-developer and shared across every lane on this account, so a request here would be knowingly futile rather than a lane worth trying.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: 6d357b4ca7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Readiness evaluation — promoting

1. Programmatically tested. All checks green, 0 failing, 0 pending; mergeStateStatus: CLEAN; 0 unresolved threads. The contract self-test [Test] Govulncheck - Default-Branch & Allowlist Trigger Coverage runs in this PR's own CI and asserts the gate positively — no event_name equality, a default-branch clause present, and the path filter OR-ed rather than AND-ed — with six ablations each proven RED.

2. Reviewed. Codex green at 6d357b4ca7, which equals the current head (Codex Review: Didn't find any major issues, 19:41:57Z). CodeRabbit was tried first per lane priority and is quota-exhausted account-wide, recorded as cr:no-gate above.

3. Tried and evaluated as a user — with a stated limit. The two halves differ:

  • The path-filter half and the trigger-guard half are exercised for real: the self-test job runs the guard against the actual workflow file in this PR's CI.

  • The default-branch arm cannot be exercised pre-merge at all. In a pull_request run github.ref is a merge ref, so no job here can evaluate it under a representative context; any synthetic context I built would be a second model of GitHub's evaluator, not stronger evidence. So for that half I traced the enacting path instead, and I am saying so explicitly rather than implying it was run.

    What I checked, on the consumer this defect was measured on: ksail's .github/workflows/ci.yaml triggers on: push: branches: [main], and its ci-go job gates the call as (github.event_name == 'push' && github.ref == 'refs/heads/main') || (pull_request && …). So the caller does reach this workflow on a push to main, and the removed event_name == 'pull_request' clause was the binding constraint.

Outstanding post-merge verification — merge is not the proof. That caller pins this workflow by SHA (@2cc7273a, v10.2.9), so coverage on ksail starts only after a release here and the consumer's pin bump. The real confirmation is 🛡️ Vulnerability Scan executing rather than skipping on ksail's first push-to-main run at the bumped pin.

@devantler
devantler marked this pull request as ready for review July 28, 2026 19:43
@devantler
devantler merged commit b557930 into main Jul 28, 2026
136 checks passed
@devantler
devantler deleted the claude/govulncheck-main-coverage-6373 branch July 28, 2026 19:43
@github-project-automation github-project-automation Bot moved this from 🫴 Ready to ✅ Done in 🌊 Project Board Jul 28, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Agentic Engineer

Correction to the post-merge verification I named above — merged as b557930029.

I described the outstanding check as "🛡️ Vulnerability Scan executing rather than skipping on ksail's first push-to-main run at the bumped pin". That is incomplete: the default-branch arm ships behind scan-default-branch, default false (rollout tracked in #788), so bumping the pin alone changes nothing — a consumer that passes nothing keeps exactly today's behaviour, which is what makes the change backward-compatible.

The correct sequence to verify is therefore: release here → consumer bumps the pin → consumer opts in with scan-default-branch: true → only then does a push-to-main run execute the scan. Checking for the scan before that opt-in would read a correctly-skipped job as a regression.

The half that is live for every consumer at the bumped pin, with no flag, is the path-filter fix: an allowlist-only change now triggers the scan that reads it.

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

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

govulncheck skips a change to its own allowlist, so allowlist edits are never validated

1 participant