Feat/add gitlab mr approval controls - #423
Merged
Merged
Conversation
Joseph94m
force-pushed
the
feat/add-gitlab-mr-approval-controls
branch
from
August 20, 2026 07:18
d96ac25 to
f33e099
Compare
Joseph94m
marked this pull request as ready for review
August 20, 2026 07:52
Joseph94m
requested review from
Totara-thib,
coconux3 and
thomasboni
as code owners
August 20, 2026 07:52
Joseph94m
force-pushed
the
feat/add-gitlab-mr-approval-controls
branch
from
August 20, 2026 10:56
f33e099 to
f85cb93
Compare
Joseph94m
force-pushed
the
feat/add-gitlab-mr-approval-controls
branch
2 times, most recently
from
August 20, 2026 11:32
90ac8ab to
0688320
Compare
Joseph94m
force-pushed
the
feat/add-gitlab-mr-approval-controls
branch
from
August 20, 2026 11:46
0688320 to
8b7a80a
Compare
Joseph94m
force-pushed
the
feat/add-gitlab-mr-approval-controls
branch
from
August 20, 2026 12:01
8b7a80a to
02c5edf
Compare
Contributor
|
@Joseph94m Reviewed + tested e2e. Also checked legacy fidelity line-by-line against the backend2 controls. All of this by Claude. I've verified its results. Blocker
Nits
|
Joseph94m
force-pushed
the
feat/add-gitlab-mr-approval-controls
branch
from
August 21, 2026 15:34
ab36c42 to
f15f4b2
Compare
Collaborator
Author
|
@thomasboni should be good ! |
thomasboni
previously approved these changes
Aug 24, 2026
Adds two GitLab controls over merge-request approval rules: - ISSUE-502 flags an approval rule that covers all protected branches yet requires fewer approvals than the configured minimum. Identity is keyed on the stable approval-rule ID, not the renameable rule name, so renaming a rule does not re-key its finding. - ISSUE-504 flags a project where no approval rule applies to all protected branches, including the zero-rules case. Both abstain when the approvals listing could not be read (MRApprovalRulesKnown=false) and report not-evaluable rather than a false pass: GitLab Free 200-empties the approvals API instead of returning 403, so an empty listing cannot be read as compliant. The renderers carry a Premium/Ultimate caveat for the ambiguous zero-rules case, and an unreadable listing shows the caveat in the terminal instead of a bare green check. Refs #412
Joseph94m
force-pushed
the
feat/add-gitlab-mr-approval-controls
branch
from
August 25, 2026 08:33
c0f8326 to
389cd3f
Compare
Joseph94m
added a commit
that referenced
this pull request
Aug 25, 2026
StatusFor had no case for mergeRequestSettingsMustBeCompliant, so when the project settings could not be read the control reported a green pass on data it never saw, while its sibling ISSUE-503 correctly reported error on the same run. Add the matching guard, ahead of the CI-file checks: this control reads Settings > Merge requests, not the pipeline, so a repo with no .gitlab-ci.yml must not turn a genuine evaluation into an error either. The shipped default broke the "a setting left unset is not checked" contract that #415/#416 specify. A config inheriting plumber:default can override a value but cannot remove a key, so shipping the eight ISSUE-506 expectations and the ISSUE-503 surface populated forced every one of those opinions on anyone who merely enabled the control. They now ship commented out, so enabling a control enforces only what the operator uncomments. The MR comment dropped findings for every MR control: writeIssueDetails walks a hand-written list, and a control missing from it renders as failed in the table with no detail lines beneath. Four MR controls were absent (two from this branch, two from #423) plus externalRefsMustNotCollide, which predates both. That regression has now shipped three times, so the list moved to package scope and TestMRCommentOrderCoversEveryGitLabControl ties it to GitLabControls, the same source the table is built from. Terminal caveats for the two settings controls, matching the #423 pattern, so an unreadable payload stops printing an unqualified check. A test pins each caveat to StatusFor so the two surfaces cannot drift apart. Tests for the two gaps the review bot found in this branch's own code: the buildMRSettings projection (eight field copies, previously unexercised because every ISSUE-506 test hand-built the IR value) and the ISSUE-506 legacy JSON dispatch (an unrouted control silently loses its whole block). Not addressed here: an unreadable control still lands under Passed Controls and still counts toward the score, because neither the renderer's bucketing nor ComputeCompliance consults StatusFor. That predates this branch and hits the #422 and #423 controls identically, so it needs its own change. Refs #415, #416 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Closes #413
Closes #414
Test on https://gitlab.com/getplumber/examples/go-test-with-hash @thomasboni