Repository navigation
feat: read the org update policy from the synced standards copy - #1074
kyle-sexton wants to merge 3 commits into
Conversation
bump-versions takes cooldownDays per change class from the standards dependabot-policy copy at .github/standards/dependabot-policy/policy.json when the policy file sets none; a policy file that still sets them keeps its own, and with neither prepare fails closed. The Dependabot auto-merge gate (reusable and merge-queue paths) takes its publisher allowlist from that copy (tier auto publishers plus the github-actions and own fast track) when the caller leaves the input at its default. The reusable reads it at the base commit; an absent copy keeps today's allowlist, an unreadable one arms nothing. Adds check-dependabot-policy, a port of the standards analyzer with the cooldown-class and fast-track exclude rules, and this repository's own version-bump policy with a daily maintenance-bump-pinned-versions run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Q1HHi6JACp77x2ZbE7
bump-versions rates a minor move below 1.0 as major and keeps the minor number under line: major, as the Dependabot gate's breaksBelowOne does, and never arms auto-merge on a bump that holds a major move. check-dependabot-policy follows standards' floor semantics: semver-major-days, when set, is at least the major class, and the cooldown exclude must be a subset of the ecosystem's fast track. Its policy schema accepts schemaVersion 2 and up and ignores unknown top-level, fastTrack and autoMerge keys. The auto-merge gate also applies the synced policy's autoMerge.ecosystems and this repository's autoMerge.reviewOnly entries, which only narrow. Dependabot now tracks the checker's lockfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Q1HHi6JACp77x2ZbE7
- arm_auto_merge takes the bump's rows and calls has_major itself, so the major hold no longer rides on a dict key a caller has to set. - disarm_auto_merge raises unless gh's --disable-auto succeeds or the pull request reads back with no arm, so a bump rebuilt to a major never keeps an earlier arm. - The queue holds ajv and yaml, the check-dependabot-policy runtime that consumers run in ci-status, for review. - The checker's npm Dependabot entry runs weekly, as the policy requires. - Tests: a publish_bump-level hold for a major and a 0.x minor row, both disarm outcomes, and the queue's disarm under a malformed or unreadable synced policy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VQb9Q1HHi6JACp77x2ZbE7
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
claude-review reviewed No findings. I read every hunk of all 24 changed files. The lane has no shell, so I ran no tests; the PR description's test counts and lint results are the author's and unverified. Checked and found sound:
Manifest items: none, because the diff changes no Closing issue: none ("No related issue"), so no acceptance criteria to check. Spend: the daily Embedded instructions in the PR context: none. Observations, not findings (the author lists them as follow-ups):
|
| REVIEW_ONLY_DEPENDENCIES: "[]" | ||
| # The check-dependabot-policy action's runtime: consumers run that | ||
| # checker in ci-status, so a bump to it waits for review. | ||
| REVIEW_ONLY_DEPENDENCIES: '["ajv","yaml"]' |
There was a problem hiding this comment.
The review-only list holds only the checker's two direct dependencies, ajv and yaml. The checker's runtime tree has four more locked packages that the list leaves out: fast-uri, fast-deep-equal, json-schema-traverse and require-from-string (check-dependabot-policy/package-lock.json). fast-uri is a runtime dependency of ajv.
The test the queue holds every runtime dependency of the policy checker for review compares the list only with package.json dependencies, so it cannot see the transitive packages.
Path: a Dependabot update (a security update to a transitive package, where the cooldown does not apply) names one of those packages. The gate only checks reviewOnly.includes(name) at gate.cjs:196, and a patch or minor npm_and_yarn update passes. The queue then arms it with no review, and the new code runs in every consumer's ci-status in phase 4.
This is low likelihood and nothing is enabled yet. You could add the transitive names, or derive the list from the lockfile in the test, so the stated intent that the checker runtime is never auto-merged holds.
severity: SUGGESTION
claude-lane: claude-security-review
|
claude-security-review reviewed Security review of #1074 at f9c98a2. I read every hunk of all 24 files. I found no CRITICAL issues and one SUGGESTION. This is the first review of this lane for this pull request, so it is not blocking-only. critical-findings: 0 What I checked
Owner-threat-model note (one line, no hold). The new daily workflow arms auto-merge on third-party tool pins, several marked Spend. The daily workflow and its checks use Actions minutes and no paid plan or billing setting, so there is no cost hold. Instruction-surface lens. The diff deletes no standing instruction. The protected-class register was not needed. Finding
|
No related issue: phase 2 of the org update policy (standards#987, owner decisions 2026-11-11)
session: GitHub Support
Summary
ci-workflows now runs the org dependency-update policy from the copy of standards
components/dependabot-policy/policy.json(schemaVersion 2) that the standards sync places at.github/standards/dependabot-policy/policy.json. It no longer relies on its own hard-coded defaults.bump-versions takes
cooldownDaysper change class from that copy when the caller's.github/version-bump/policy.yamlsets none. A policy.yaml that still setscooldownDayskeeps its own values until phase 4 removes them. With neither source present,preparefails closed and never assumes a cooldown.Dependabot auto-merge, through both the reusable
pr-automerge-dependabot.ymland this repository'spr-automerge-dependabot-queue.yml, builds its publisher allowlist from the copy when the caller leavespublisher-allowlistat its default. The list is the copy'stier: autopublishers plusfastTrack.github-actionsandfastTrack.own. The reusable reads the copy through the contents API at the pull request's base commit, so the PR cannot change it.New composite action
check-dependabot-policyis a port of standards'dependabot-policy.mjs. It adds two rules that standards'dependabot-policy.mjsat 2303d43 lacks:semver-major-days, when set, must be at least themajorclass.cooldown.excludeentry must be in the ecosystem'sfastTracklist, plusownfor github-actions.The existing floor still holds
default-daysat or above thepatchclass.A consumer calls it as a step inside
ci-status. It is not enabled anywhere yet; that is phase 4.This repository's own
.github/version-bump/policy.yamlhas 20 tool entries in 4 groups. It also lists 7 pins the bot leaves to a person, each with the reason. A new dailymaintenance-bump-pinned-versions.ymlworkflow runs it.ci-workflows does not receive the synced policy.json today. Its target block in standards
distribution/sync-manifest.yml(lines 515-548 at 2303d43) does not list thedependabot-policycomponent, and.github/standards/here holds onlyrunner-policy-contract. Until a standards sync-manifest target adds it (phase 4, or a follow-up):Fix
bump.py:load_policyresolvescooldownDaysonce. Both readers use that value:cooldown_daysand thepython-orgsource's uv cooldown. A new--dependabot-policyflag and matching action input default to the synced path.gate.cjs:resolvePublisherAllowlistholds the shared resolution.runEventreads the copy atpull_request.base.sha, andqueue.cjsreads the copy in the checked-out main. Neither thepublisher-allowlistdefault nor the reusable'sworkflow_callinputs changed:automerge-lockstep.mjsparses that default;runner,package-auto-mergeandreview-only-dependencies.check-dependabot-policy:dependabot-policy.schema.jsonand the test fixturefixtures/policy.jsonare byte-identical to standards' files at 2303d43.policy.schema.jsonis standards' schema withadditionalProperties: falseremoved in three places (top level,fastTrack,autoMerge) andschemaVersionrelaxed fromconst: 2tominimum: 2, so a newer synced copy with added keys still validates.package.jsonand lockfile with the sameajv8.20.0 andyaml2.9.1 pins.RUNNER_TEMP.policy.yaml:line: major; Python is held atline: minor). A merged bump reaches every@maincaller, and the owner's decision sends majors to review, while the engine arms auto-merge on every bump.node-runtime), zizmor (follows dotfiles), govulncheck (go.sum hash), osv-scanner and slsa-verifier (automaticMerge: false), osslsigncode (Ubuntu archive).pr-require-checks.ymltest-contractsnow installs the engine's pinned yq and runs the new action's tests.Verification
All run locally on this branch:
python3 -B -m unittest discover -s .github/actions/bump-versions -p 'test_*.py': 76 tests, OK.node --test .github/scripts/pr-automerge-dependabot.test.cjs: 75 pass.node --test .github/scripts/pr-automerge-dependabot-queue.test.cjs: 41 pass. The new cases cover:package.jsondependencies.node --test .github/actions/check-dependabot-policy/check-dependabot-policy.test.mjs: 49 pass. Before the new rules were added, the 41 ported standards tests passed. Flipping one new rule's comparison turns tests red.node --test .github/scripts/node-version-agreement.test.cjspasses; it now also covers the new action'snode-version.run.sh, and zizmor 1.30.0 offline on the new workflow and the action. actionlint 1.7.12 (upstream) reports only the known$/refs, which the kjanat fork used in CI accepts.What CI cannot exercise here. This PR's lanes call the reusables at
@main, and nothing runs live from a PR:bump-versions prepare, which makes network calls and runs baregh. The verify blocks (checksums, assetFile digests, npm signature, PyPI, PSGallery, python.org) are untested until the first run with the synced file. Runworkflow_dispatchwithdry-run: truefirst.check-dependabot-policyaction end to end in a consumer.Related
cooldownDays,fastTrack).dependabot-policy.mjsbecome a pointer? Recommended yes, once a consumer runs this action inside ci-status (phase 4): then standards keeps data only, as decided. Until then the two copies can drift. The schemas here derive from standards' too (one byte-identical, one relaxed), and standards' README already says the analyzer moves here.dependabot-policyfor ci-workflows.Follow-ups (no code change here)
actions/*,github/*andanthropics/*.melodic-software/*needs adding there in lockstep withfastTrack.own(owner decision D125).line: major.line: majornow keeps the minor number below 1.0, so a 0.x tool's minor releases are never prepared, even though majors now go to review anyway. Whether to lift the cap for 0.x tools is a phase-3 decision.autoMerge.ecosystems; a consumer whose synced copy predates schemaVersion 2 may lack an ecosystem there (uv absent would stop uv auto-merge). Check every consumer's synced copy before phase 4.daily, which the new checker reports asschedule-not-standard. It predates this PR (main since feat(workflows): Claude lane feature set — config currency, cadence, retry, kill-switches, copy (PR-B, 2b-2i) #280) and is left for the phase that enables the checker here.fastTrack. A pinned@anthropic-ai/claude-codewould wait the 3-day patch cooldown instead of fast-tracking. No such pin exists today; phase 3 or 4 handles it.Review fixes (follow-up commit)
0.x minors: below 1.0 a minor move is now class
major, andline: majorkeeps the minor number. This matches the Dependabot gate'sbreaksBelowOne.Majors:
arm_auto_mergeno longer arms a bump that holds any major move. The PR still opens for review.Checker rules beyond standards: the checker adds two rules that standards'
dependabot-policy.mjsat 2303d43 lacks:semver-major-days, when set, must be at least themajorclass (cooldown-major-below-major-class).cooldown.excludemust be a subset of the ecosystem's fast track (cooldown-exclude-outside-fast-track).default-daysstays held at or above thepatchclass by the existing floor. Thepolicy.schema.jsonhere acceptsschemaVersion2 and above and ignores unknown top-level,fastTrackandautoMergekeys.Gate: a synced policy's
autoMerge.ecosystemsand itsautoMerge.reviewOnlyentries for this repository now narrow what is armed, whatever the input.Dependabot:
dependabot.ymlgains an npm entry for the action's lockfile, on the policy'sweeklyschedule.Second review fixes (f9c98a2)
arm_auto_mergetakes the bump's rows and callshas_majoritself; thehasMajordict key is gone. Apublish_bump-level test with a major row and with a 0.x minor row (0.24.2 -> 0.25.0) asserts--disable-autois called and--auto --squashnever is. With thehas_majorcall removed, both subtests fail.disarm_auto_mergeaccepts a failedgh pr merge --disable-autoonly when the pull request then reads back with noautoMergeRequest; any other failure raises, so a bump rebuilt to a major never keeps an earlier arm. Both outcomes are tested. The not-armed case is identified by reading the PR's state, not by matching gh's error text, which neither gh's source nor GitHub's docs state.REVIEW_ONLY_DEPENDENCIESto["ajv","yaml"], thecheck-dependabot-policyruntime that phase 4 runs in every consumer'sci-status, so neither is auto-merged. The phase-4 home is a standardsautoMerge.reviewOnlyentry for ci-workflows; the env value can go once the synced copy carries it.🤖 Generated with Claude Code
https://claude.ai/code/session_01VQb9Q1HHi6JACp77x2ZbE7