ci(security): retry the semgrep install fail-closed (transient ResolutionImpossible reded the queue) - #1889
Merged
Conversation
added 2 commits
October 1, 2026 02:59
…utionImpossible reded the queue) Merge-group run 36832387843 (job 110271740736) failed the blocking "semgrep (project SAST rules)" gate at install time: pip reported ResolutionImpossible with "no matching distributions" for pydantic-core at every version from 2.33.0 to 2.46.5. That is an empty index read, not a new release. The same pin resolved pydantic-core 2.46.5 on the same runner image six minutes later (job 110273573584), an hour earlier on the same queue head, and in a clean local Python 3.14 venv. Both semgrep install sites (the standalone job and the repo-scan composite, kept byte-identical) now retry up to three times with a 15s/30s backoff and exit 1 after the third failure. semgrep==1.172.0 is unchanged, and the scan step is untouched. No hash lock: semgrep is out of [dependency-groups] by recorded decision (ADR 0034 section 3, the [otel] conflict), and a lock would not have prevented this failure, since pip still reads the index per package.
Runs the committed retry loop under bash -e with python and sleep stubbed: a recovered install reaches the scan, and three failures exit 1 without reaching it. A mutation that swaps `exit 1` for `break` reds the fail-closed test. Also from code review: retries now annotate with ::warning::, and the comment no longer says the repo-scan copy failed in run 36832387843 (only the standalone semgrep job did).
Collaborator
Author
wshallwshall
enabled auto-merge
October 1, 2026 08:04
The new test reads a CI workflow, not engine source, so it belongs in tests/tooling_manifest.txt. test_tooling_partition.py reded on its absence.
Collaborator
Author
|
QA addendum: head 2dbe7a6 adds tests/test_semgrep_install_retry.py to tests/tooling_manifest.txt (manifest-only, not re-reviewed); test_tooling_partition.py plus the new test: 43 passed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What broke
Merge-group run 36832387843 (job 110271740736) failed the blocking
semgrep (project SAST rules)gate at install time. pip reportedResolutionImpossible, with "no matching distributions available for your environment: pydantic-core" at every pydantic-core version from 2.33.0 to 2.46.5. The log shows a 37-second stall just before.Root cause: a transient empty index read, not a new release
semgrep==1.172.0pin resolvedpydantic-core==2.46.5six minutes later, on the same runner image (ubuntu24/20260927.320), in job 110273573584.So this was one bad read, and a re-run alone would have passed.
The fix
Both semgrep install sites (the standalone job and the repo-scan composite, still byte-identical) now retry up to three times, with a 15s and then 30s backoff, and annotate each retry with
::warning::. It stays fail-closed: after the third failure the step exits 1 and the scan never runs.semgrep==1.172.0is unchanged, and so is the scan command.tests/test_semgrep_install_retry.pyruns the committed loop underbash -ewithpythonandsleepstubbed. A recovered install reaches the scan. Three failures exit 1 without reaching it. Swappingexit 1forbreakturns the fail-closed test red.Why not a hash lock (the brief's first choice)
[dependency-groups]on purpose. ADR 0034 section 3 records the[otel]conflict, andtests/test_ci_venv_pinning.pysays the same. Aci/locks/lock would mean reopening that decision.--require-hashes, pip still reads the index page for every package, and that read is what came back empty.Checks run
security.yml,semgreporci/locks, plus the new file:562 passed, 1 skipped.exit 1):1 failed, 4 passed.ruff check(All checks passed),ruff format --check, andmypyon the new test (no issues).actionlintis not installed here.Ran 5 rules on 435 files: 0 findings.code-reviewsubagent at xhigh: three low findings, no blockers. Two are fixed in the second commit (the comment wording and the::warning::annotation). The third (no test pinned fail-closed) is fixed by the new test.Legs to read on the PR:
semgrep (project SAST rules)andrepo-scan, which run the edited steps.