Skip to content

ci: a Dependabot minor or patch update of the dependency files merges without a review (ADR-1126) - #953

Merged
cdeust merged 3 commits into
mainfrom
ci/risk-tier
Nov 9, 2026
Merged

cdeust merged 3 commits into
mainfrom
ci/risk-tier

Conversation

@cdeust

@cdeust cdeust commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Contexte

Les PR Dependabot ne peuvent jamais fusionner seules : claude-review.yml ne les relit pas (acteur dependabot[bot], pas de secrets), donc aucun Verdict: approve, et le résolveur les retient (ADR-1121). Le 9 novembre, #931, #933, #934, #935 et #949 étaient vertes et retenues depuis deux jours.

Changement (ADR-1126, amende ADR-1121)

Le résolveur calcule un niveau de risque à partir du changement, comme le décrit Anthropic (https://claude.dev/blog/solving-code-review-at-anthropic/). Une PR est à bas risque si tout ceci est vrai :

  • auteur dependabot[bot], chaque commit de dependabot[bot] avec signature vérifiée par GitHub ;
  • chaque update-type déclaré est semver-minor ou semver-patch ;
  • seuls uv.lock ou pyproject.toml changent.

Une telle PR fusionne sans verdict, sur contrôles requis verts (merge, CodeQL). Tout le reste garde le chemin relu : mise à jour majeure, fichier de workflow, Dockerfile, branche Dependabot poussée par quelqu'un d'autre. Les labels hold et do-not-merge retiennent toujours.

Effet attendu sur les PR ouvertes

Métrique

PR Dependabot mineures ou correctives fusionnées sans intervention : 0 aujourd'hui, toutes après. Garde-fou à suivre : reverts après ces fusions.

Tests

tests_py/scripts/test_ci_low_risk_tier.py (9 tests) : chaque condition seule refuse le niveau ; une PR à bas risque fusionne sans review ; toute autre est retenue.

Cette PR modifie un workflow : elle attend la fusion du propriétaire.


Generated by Claude Code

… without a review (ADR-1126)

The resolver computes a risk tier from the change: Dependabot author and signed
commits, only semver-minor or semver-patch update types, only uv.lock or
pyproject.toml. Such a PR merges on green required checks; every other PR keeps
the verdict gate of ADR-1121. Follows the change-based risk tiers of
https://claude.dev/blog/solving-code-review-at-anthropic/.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYsWnKSjpX4oNV19PCF
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-09T22:41:12.188246Z 6fad8f6 New commits
🔒 Security Review ✅ Completed 2026-11-09T22:44:06.794941Z 6fad8f6 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 5ec3aea53e

ℹ️ 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 on lines +387 to +390
signed = (detail.get("verification") or {}).get("verified") is True
author = (commit.get("author") or {}).get("login")
if author != "dependabot[bot]" or not signed:
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Authenticate the committer before bypassing review

A contributor who can push to an existing Dependabot branch can author a commit using Dependabot's public email, retain a patch/minor metadata line, and sign it with their own GitHub-registered key. GitHub's signature verification does not establish the author's consent (signature verification documentation), so this commit can have author.login == "dependabot[bot]" and verification.verified == true while its committer is human. The resolver accepts that combination and skips review for arbitrary changes to pyproject.toml or uv.lock, defeating the stated safeguard for human-modified Dependabot branches. Validate the authenticated committer/signing identity as Dependabot as well, and add a regression test with a verified, bot-attributed commit whose committer is human.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmé et corrigé. L'auteur git n'est qu'un e-mail déclaré et verified atteste la clé du committeur. Le niveau bas risque exige maintenant aussi committer.login == "web-flow" : les commits de Dependabot sont committés et signés par GitHub, où l'auteur est le compte qui agit. Test de régression ajouté (commit attribué au bot, committeur humain vérifié : refusé). ADR-1126 mis à jour.


Generated by Claude Code

…itHub

A git author is a declared e-mail and a verified signature vouches for the
committer's key, so a contributor could sign a commit under Dependabot's name
on a Dependabot branch. The tier now also requires committer web-flow.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYsWnKSjpX4oNV19PCF
@claude

claude Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

PR #953 was updated after the trigger (5ec3aea -> df05c88). Push again or mention Claude to run on the latest version.

@claude

claude Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 3m 30s —— View job


Review of PR #953 (review 1 of 3)

Result: no Blockers, so the verdict is approve. The Codex P1 point is fixed: the web-flow committer check and its regression test are in place. The review comment lists three Notes that don't need action before merge: a possible commit rewritten by GitHub that I couldn't verify, renames that aren't checked, and update-type lines that are ignored instead of refused.

I didn't run pytest, ruff or the craftsmanship gate because they need permission in this job.

@claude

claude Bot commented Nov 9, 2026

Copy link
Copy Markdown

Review 1 of 3 (ADR-1119): PR #953, ADR-1126 low-risk tier

I reviewed df05c88 and 5ec3aea, using five reviewers: security, code quality, tests, docs and performance.

Blockers: none.

  • The Codex P1 point is fixed. _is_low_risk now requires committer.login == "web-flow" along with a dependabot[bot] author and a verified signature. test_a_bot_attributed_commit_signed_by_a_person_is_not covers the case.
  • The tier fails closed when there are no commits, no files, no update-type, an unknown update-type or a nested uv.lock path. Non-Dependabot PRs return before any extra API call.
  • Hold labels and titles are checked before the tier. The merge PUT is still pinned to the tested head.
  • Existing resolver tests still hold: test_ci_review_dictates_merge.py and test_ci_review_required.py.
  • Both constants carry # source:, and the dependabot.yml quote checks out. _is_low_risk is 33 lines.
  • The repo records CodeQL as an independent required check (ADR-0802), which is consistent with ADR-1126 §2.

Not done here: pytest, ruff and the craftsmanship gate need permission in this job, so I did not run them.

Notes, no action before merge

  1. Not verified: a commit GitHub rewrites itself might pass all three commit checks with a person's content. That covers "Update branch → rebase" and Contents/Git Data API commits with a custom author. Checking that the push actor is dependabot[bot] would close this, via the source run's actor or the PR timeline, as would requiring exactly one commit.
  2. The file allow-list reads only filename, not previous_filename, so a rename of .github/workflows/x.yml to uv.lock would pass. It is only reachable through commits that already pass the Dependabot/web-flow/verified check.
  3. update-type lines the regex does not match, and grouped entries with no update-type at all, are skipped instead of refused. Requiring one update-type per dependency-name would make this strict.

View job run

Verdict: approve

… and no rename

Review notes of #953: a second commit on the branch, a dependency named without
its update type, and a file renamed to a dependency file each refuse the tier.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
Claude-Session: https://claude.ai/code/session_018kyZYsWnKSjpX4oNV19PCF

cdeust commented Nov 9, 2026

Copy link
Copy Markdown
Owner Author

Notes du review 1 traitées dans 6fad8f6, parce qu'elles touchent le contournement de review : (1) le niveau exige exactement un commit Dependabot, un second commit sur la branche le refuse ; (2) un fichier renommé compte sous ses deux noms (previous_filename) ; (3) chaque dependency-name doit déclarer son update-type. Trois tests ajoutés, ADR-1126 aligné.

🤖 Generated with Claude Code


Generated by Claude Code

@claude

claude Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

Claude finished @cdeust's task in 2m 31s —— View job


Review 2 of 3 (ADR-1119): PR #953

Result: no Blockers, so the verdict is approve. 6fad8f6 refuses three cases, and each refusal fails closed: a second commit on the branch, a dependency named without its update-type, and a file renamed from or to a dependency file. Each new test fails only on its own condition.

The review lists three Notes that don't need action before merge:

  1. Not verified: the claim that the author of a web-flow commit "cannot be chosen" has no support in its cited source.
  2. The tier is not bound to the tested head. Adding commits[0]["sha"] == head would bind it.
  3. update-type and dependency-name are paired by count across the whole message, not entry by entry.

I didn't run pytest, ruff or the craftsmanship gate because they need permission in this job.

@claude

claude Bot commented Nov 9, 2026

Copy link
Copy Markdown

Review 2 of 3 (ADR-1119): PR #953, ADR-1126 low-risk tier

Review 1 (df05c88) had no Blockers. I reviewed the one commit pushed since: 6fad8f6. Five reviewers read it: security, code quality, tests, docs and performance.

Blockers: none.

  • Single commit. len(commits) != 1 refuses a second commit on the branch. The 250-commit cap of /commits can only shorten the list to 250, never to 1, so the check fails closed.
  • Typed updates. _declared_updates requires one update-type: for each - dependency-name:. A major update still can't hide, because every update-type must be in LOW_RISK_UPDATES.
  • Renames. A rename now counts under filename and previous_filename, and - {None} together with bool(files) still refuses an empty file list.
  • Tests. Traced by hand, each new test fails only on its own condition: second commit, untyped dependency, rename from .github/workflows/. The happy path still has one commit and merges with a single PUT.
  • Repo rules. _declared_updates is 19 lines and _is_low_risk 25. Both constants keep their # source:, and the two ADR-1126 copies agree.
  • Performance. A PR that isn't from Dependabot makes no extra API call.

Not done here: pytest, ruff and the craftsmanship gate need permission in this job, so I did not run them.

Notes, no action before merge

  1. Not verified: the _declared_updates docstring says the author of a web-flow commit "cannot be chosen", but the cited page doesn't say that. "Update branch → rebase" and Git Data API commits with a custom author may break it. Binding the tier to the push actor (PR timeline head_ref_force_pushed) would remove the assumption.
  2. /commits and /files show the branch as it is now, not the tested head. Adding require(commits[0]["sha"] == head) would bind the tier to the commit that gets merged.
  3. update-type and dependency-name are paired by count across the whole message, not entry by entry inside the updated-dependencies: YAML block.

Verdict: approve

@cdeust
cdeust merged commit 87dd2c3 into main Nov 9, 2026
18 checks passed
@cdeust
cdeust deleted the ci/risk-tier branch November 9, 2026 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants