Skip to content

refactor(#7798): add GitLab pipeline-variable override-role methods - #7813

Merged
ggallen merged 2 commits into
mainfrom
agent/7798-gitlab-pipeline-override-role
Sep 28, 2026
Merged

ggallen merged 2 commits into
mainfrom
agent/7798-gitlab-pipeline-override-role

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Summary

Add forge.Client methods to read and set GitLab's ci_pipeline_variables_minimum_override_role project setting (GitLab >= 17.1). This is the Wave 0 primitive that #7769 needs before it can tighten who may override CI_JOB_TOKEN and other pipeline variables.

This change does not wire the setting into the security gate or install-time provisioning; that remains #7769 / #7772.

Related Issue

#7798 (prerequisite for #7769; coordinates with #7767 / #7772)

Changes

  • New forge.Client methods: GetPipelineVariablesMinimumOverrideRole and SetPipelineVariablesMinimumOverrideRole.
  • Documented role constants: no_one_allowed, developer, maintainer, owner.
  • GitLab LiveClient GET/PUT on /api/v4/projects/:id with ci_pipeline_variables_minimum_override_role.
  • GitHub stubs return forge.ErrNotSupported.
  • FakeClient stores and round-trips the role value, including error injection and race coverage.

Testing

  • Unit tests for GitLab LiveClient GET (happy path, 404, 403, 5xx, decode error) and PUT (happy path, 404, 403, 5xx)
  • FakeClient round-trip, unset-project, and injected-error tests
  • GitHub unsupported-method stubs
  • go test -race on ./internal/forge/, ./internal/forge/github/, ./internal/forge/gitlab/
  • gofmt and go vet on changed packages
  • make lint — sandbox pre-commit could not fetch remote hook repos (HTTP 403); ran gofmt/vet/gitleaks and local file checks directly

Checklist

  • PR title follows Conventional Commits (correct type, ! for breaking changes)
  • Commits are signed off (DCO) — autonomous agent commits are exempt
  • I wrote this contribution myself and can explain all changes in it

Closes #7798

Post-script verification

  • Branch is not main/master (agent/7798-gitlab-pipeline-override-role)
  • Secret scan passed (gitleaks — 1e5e984ab1c70501f4759eca73680f05ddfd14b0..HEAD)
  • PR body secret scan passed (gitleaks — no-git)

@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner September 28, 2026 21:52
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Triggers review agent dispatch label Sep 28, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:54 PM UTC · Completed 10:11 PM UTC

Commit: 11842cf · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $5.44

@codecov

codecov Bot commented Sep 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Sep 28, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Risk Assessment: moderate (2/5)

Details

Additive forge primitive implementation with low metadata risk and tight issue alignment, balanced by active churn and regression history in core forge packages.

Previous run

Risk Assessment: moderate (2/5)

Details

Additive forge primitive implementation with low metadata risk and tight issue alignment, balanced by active churn and regression history in core forge packages.

@fullsend-ai-review

fullsend-ai-review Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Review

Findings

Low

  • [commit-title-tier-mismatch] PR title — The feat(#7798): ... prefix is inconsistent with COMMITS.md, which reserves feat for user-visible capabilities and lists "adding internal packages, helpers, or abstractions that don't change user-visible behavior" as refactor. This PR adds unwired forge.Client primitives (no CLI, config, or workflow wiring; not consumed by any caller outside internal/forge) for downstream security-gate work in ADR 0125: in-job security gate hardening (agent + poll scripts) #7769/GitLab service-account lifecycle + webhook fast-path via fresh-identity poller handoff (ADR 0125) #7772, with no user-visible behavior change. This finding also appeared in the two prior reviews of this PR and the title has not changed since.
    Remediation: Retitle to refactor(#7798): add GitLab pipeline-variable override-role methods per COMMITS.md's feat/refactor distinction, since GoReleaser uses PR titles to build release notes.

The prior review's unvalidated-input, api-contract, and nil-map-init findings are not observed in the current diff: forge.ValidatePipelineVarOverrideRole is now called from both the GitLab LiveClient.SetPipelineVariablesMinimumOverrideRole and FakeClient.SetPipelineVariablesMinimumOverrideRole before any request or storage, the interface doc on GetPipelineVariablesMinimumOverrideRole now documents the empty-string-on-absent-field behavior, and NewFakeClient now initializes PipelineVarOverrideRoles.

The forge.Client interface extension is additive only — all three implementers (FakeClient, GitHub LiveClient, GitLab LiveClient) are updated in this diff, each carries a compile-time interface assertion, and no existing method signatures changed. Cross-repo-contracts, correctness, security, docs-currency, and style-conventions review found no additional issues.

Previous run

Review

Findings

Low

  • [commit-title-tier-mismatch] PR title — The feat(#7798): ... prefix is inconsistent with COMMITS.md, which reserves feat for user-visible capabilities and lists "adding internal packages, helpers, or abstractions that don't change user-visible behavior" as refactor. This PR adds unwired forge.Client primitives (no CLI, config, or workflow wiring; not consumed by any caller outside internal/forge) for downstream security-gate work in ADR 0125: in-job security gate hardening (agent + poll scripts) #7769/GitLab service-account lifecycle + webhook fast-path via fresh-identity poller handoff (ADR 0125) #7772, with no user-visible behavior change. This finding also appeared in the prior review of this PR and the title has not changed since.
    Remediation: Retitle to refactor(#7798): add GitLab pipeline-variable override-role methods per COMMITS.md's feat/refactor distinction, since GoReleaser uses PR titles to build release notes.

The prior review's unvalidated-input, api-contract, and nil-map-init findings are not observed in the current diff: role validation, interface documentation, and map initialization were all added in this revision.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run (2)

Review

Findings

Low

  • [unvalidated-input] internal/forge/gitlab/repo.go:247 — SetPipelineVariablesMinimumOverrideRole forwards the caller-supplied role string to GitLab with no allowlist check against the four documented values (no_one_allowed, developer, maintainer, owner); FakeClient stores any string the same way. Not exploitable today — the primitive isn't wired into any security gate in this PR, and LiveClient.put() already surfaces a non-2xx GitLab response as an error — but the client silently accepts and records typos or unknown values, which could mask contract violations once ADR 0125: in-job security gate hardening (agent + poll scripts) #7769/GitLab service-account lifecycle + webhook fast-path via fresh-identity poller handoff (ADR 0125) #7772 build a security gate on this primitive.
    Remediation: Reject any role that is not one of the four PipelineVarOverride* constants before issuing PUT, via a shared helper used by both the GitLab LiveClient and FakeClient; return a non-nil error for empty/unknown values.

  • [api-contract] internal/forge/gitlab/repo.go:241 — GetPipelineVariablesMinimumOverrideRole returns ("", nil) when GitLab's response omits ci_pipeline_variables_minimum_override_role (e.g. older GitLab, or a tier/edition where the field is absent). Empty string is not one of the four documented roles, so callers cannot distinguish "field absent on this GitLab instance" from a successfully read role. Not a current fail-open — nothing consumes this primitive yet — but worth documenting before ADR 0125: in-job security gate hardening (agent + poll scripts) #7769/GitLab service-account lifecycle + webhook fast-path via fresh-identity poller handoff (ADR 0125) #7772 build a security gate on it.
    Remediation: Document the empty-string-on-absent-field behavior on the interface (or return a distinguishable sentinel/error) so the downstream security-gate work doesn't have to guess.

  • [nil-map-init] internal/forge/fake.go:15 — NewFakeClient() initializes sibling maps such as ProtectedBranches and PipelineSchedules but not the newly added PipelineVarOverrideRoles map. SetPipelineVariablesMinimumOverrideRole lazily initializes it, so today's tests are safe, but fake_test.go's established convention of seeding maps by direct assignment after NewFakeClient() (e.g. fc.ProtectedBranches["org/repo/main"] = true at fake_test.go:1694) would panic with a nil-map write if a future test does the same for PipelineVarOverrideRoles.
    Remediation: Add PipelineVarOverrideRoles: make(map[string]string), to the struct literal in NewFakeClient() in internal/forge/fake.go.

  • [commit-title-tier-mismatch] PR title — The feat(#7798): ... prefix is inconsistent with COMMITS.md, which reserves feat for user-visible functionality and explicitly lists "Adding internal packages, helpers, or abstractions that don't change user-visible behavior" as a refactor. The PR body itself states these methods are unwired primitives with no security-gate or provisioning effect yet.
    Remediation: Retitle to refactor(#7798): add GitLab pipeline-variable override-role methods per COMMITS.md's feat/refactor distinction, since GoReleaser uses PR titles to build release notes.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-coder

fullsend-ai-coder Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 10:13 PM UTC · Completed 10:22 PM UTC

Commit: 11842cf · View workflow run →

Runtime: claude · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $1.62

fullsend-ai-coder Bot added a commit that referenced this pull request Sep 28, 2026
Address review feedback on PR #7813:

- Reject any role passed to SetPipelineVariablesMinimumOverrideRole
  that isn't one of the four documented GitLab values, via a shared
  forge.ValidatePipelineVarOverrideRole helper used by both the GitLab
  LiveClient and FakeClient, so typos/unknown values are rejected
  before a PUT is issued or a value is stored.
- Initialize PipelineVarOverrideRoles in NewFakeClient() alongside its
  sibling maps, matching the direct-assignment seeding convention used
  elsewhere in fake_test.go.
- Document that GetPipelineVariablesMinimumOverrideRole returns
  ("", nil) when GitLab's response omits the field (older GitLab or an
  edition without it), since that's indistinguishable from an
  explicitly empty role.

Addresses #7813
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 1 (bot-triggered)

Addressed all four review findings on PR #7813: added a shared forge.ValidatePipelineVarOverrideRole helper enforcing the four documented GitLab roles, wired it into both the GitLab LiveClient and FakeClient Set methods, initialized the previously-missing PipelineVarOverrideRoles map in NewFakeClient(), documented the ambiguous empty-string-on-absent-field read behavior on the interface and LiveClient doc comments, and added regression tests for each. Also confirmed the PR title should be refactor(#7798) rather than feat(#7798) per COMMITS.md, but could not apply the retitle myself — the sandbox blocked the gh pr edit mutation by policy — so recommending a human/post-script apply it before merge. All tests and go vet pass on internal/forge/... (including github, gitlab, jira) with -race; gofmt is clean. pre-commit could not fetch remote hook repositories (same infra limitation noted in the original PR), so its applicable local checks (gofmt, go vet) were run directly instead.

Fixed (4):

  1. unvalidated-input: SetPipelineVariablesMinimumOverrideRole accepts any string (internal/forge/gitlab/repo.go): Added forge.ValidatePipelineVarOverrideRole, a shared helper that checks the role against the four documented constants (no_one_allowed, developer, maintainer, owner). GitLab LiveClient.SetPipelineVariablesMinimumOverrideRole now calls it before issuing the PUT, and FakeClient.SetPipelineVariablesMinimumOverrideRole calls the same helper before storing the value, so both implementations reject typos/unknown values identically. Added regression tests in gitlab_test.go (asserts no HTTP request is made for an invalid role) and fake_test.go.
  2. api-contract: GetPipelineVariablesMinimumOverrideRole returns ("", nil) when the field is absent (internal/forge/forge.go): Documented the ambiguity on the Client interface's Get/Set doc comments and on the GitLab LiveClient method: an absent ci_pipeline_variables_minimum_override_role field reads back as ("", nil), indistinguishable from an explicitly empty role, since GitLab never populates the field with an empty string. Also cross-referenced ValidatePipelineVarOverrideRole from the Set doc comment so callers know Set rejects empty/unknown values outright.
  3. nil-map-init: NewFakeClient() omits PipelineVarOverrideRoles (internal/forge/fake.go): Added PipelineVarOverrideRoles: make(map[string]string) to the struct literal in NewFakeClient(), matching sibling maps (ProtectedBranches, PipelineSchedules, etc.). Added a regression test asserting the map can be seeded by direct assignment right after NewFakeClient(), the convention used elsewhere in fake_test.go.
  4. commit-title-tier-mismatch: PR title uses feat(GitLab forge primitive: read/set project ci_pipeline_variables_minimum_override_role #7798) for an unwired internal primitive: Confirmed against COMMITS.md that this change (new forge.Client methods with no consumer wired up yet) matches the refactor guidance, not feat. Attempted gh pr edit 7813 --title "refactor(#7798): add GitLab pipeline-variable override-role methods" to retitle the PR directly, but the sandbox network policy denied the GraphQL mutation (403 policy_denied on POST /graphql) — PR metadata edits are outside this agent's permitted actions and are a post-script/human responsibility. Recommending the title above be applied before merge, since GoReleaser builds release notes from the PR title. The fix commit in this run uses a fix(#7798): prefix per COMMITS.md's guidance for review-feedback commits, since it corrects the missing validation/nil-map defects.

Tests: passed

CI inspections (12):

  1. CI / test (passing, success): Go build/test job succeeded on the PR head.
  2. CI / web (passing, success): Web build job succeeded.
  3. CI / test-sandbox-darwin (passing, success): Sandbox darwin job succeeded.
  4. CI / commit-lint (passing, success): Commit-lint job succeeded on the existing history.
  5. Functional Tests / functional-tests (passing, success): Functional test suite succeeded.
  6. Functional Tests / gate (passing, success): Gate check succeeded.
  7. E2E Tests / e2e (passing, success): E2E job succeeded.
  8. E2E Tests / gate (passing, success): Gate check succeeded.
  9. E2E Tests / behaviour (pending, in_progress): Still running at inspection time; no failure signal yet.
  10. Vouch Check / vouch-gate (passing, success): Vouch gate succeeded.
  11. DCO (passing, success): DCO check succeeded (autonomous agent commits are exempt per repo policy).
  12. codecov/patch (passing, success): Patch coverage check succeeded.
Decision points
  • Placed the role-validation logic in a single exported helper (forge.ValidatePipelineVarOverrideRole) rather than duplicating the same switch statement in the GitLab LiveClient and FakeClient. (alternatives: Duplicate an inline validation switch in both internal/forge/gitlab/repo.go and internal/forge/fake.go, Add a private validation function per package; rationale: The review finding explicitly asked for a shared helper used by both implementations so they can't drift; forge.go already owns the four role constants, making it the natural home for the validator.)

Next steps:

  • /fs-review — request a re-review of the changes
  • /fs-fix <your instruction> — run another fix pass with specific guidance
  • Push commits directly — review re-runs automatically on push
    Updated by fullsend fix agent

@fullsend-ai-review

fullsend-ai-review Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:24 PM UTC · Completed 10:36 PM UTC

Commit: 1da82fb · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $3.13

@fullsend-ai-review fullsend-ai-review Bot removed the risk/moderate PR risk: moderate label Sep 28, 2026
fullsend-ai-review[bot]

This comment was marked as outdated.

@ggallen

ggallen commented Sep 28, 2026

Copy link
Copy Markdown
Member

/fs-fix

Rebase. Resolve all conflicts. Fix all review issues. Reply to and resolve all threads.

@fullsend-ai-coder

fullsend-ai-coder Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 10:55 PM UTC · Completed 11:06 PM UTC

Commit: 1da82fb · View workflow run →

Runtime: claude · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $2.18

Add forge.Client methods to read and set GitLab's
ci_pipeline_variables_minimum_override_role project setting
(GitLab >= 17.1). This is the Wave 0 primitive #7769 needs
before it can tighten who may override CI_JOB_TOKEN and other
pipeline variables.

GitLab LiveClient GETs and PUTs /projects/:id. GitHub stubs
return ErrNotSupported. FakeClient round-trips the stored
role. 404 maps to ErrNotFound and 403 to ErrForbidden,
matching sibling project-settings methods.

Note: pre-commit could not fetch remote hook repos (HTTP 403).
gofmt, go vet, gitleaks, and local file checks were run
directly on the changed files.

Closes #7798
Address review feedback on PR #7813:

- Reject any role passed to SetPipelineVariablesMinimumOverrideRole
  that isn't one of the four documented GitLab values, via a shared
  forge.ValidatePipelineVarOverrideRole helper used by both the GitLab
  LiveClient and FakeClient, so typos/unknown values are rejected
  before a PUT is issued or a value is stored.
- Initialize PipelineVarOverrideRoles in NewFakeClient() alongside its
  sibling maps, matching the direct-assignment seeding convention used
  elsewhere in fake_test.go.
- Document that GetPipelineVariablesMinimumOverrideRole returns
  ("", nil) when GitLab's response omits the field (older GitLab or an
  edition without it), since that's indistinguishable from an
  explicitly empty role.

Addresses #7813
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 2 (human-triggered)

Rebased PR #7813 onto origin/main and resolved conflicts in 5 files where PR #7780's pipeline-trigger-token/webhook primitives collided with this PR's override-role primitives at the same interface/struct insertion points, keeping both sets of additions. Verified with build, vet, gofmt, the repo's interface-doc-sync lint, gitleaks, and go test -race across internal/forge/... (all pass). Of the review's 4 findings, 3 (unvalidated-input, api-contract, nil-map-init) were already fixed in the prior iteration and confirmed intact after the rebase; the 4th (PR title should be refactor(#7798) not feat(#7798)) could not be applied because gh pr edit is blocked by sandbox policy — recommending a human or post-script apply it. The human instruction to reply to and resolve review threads is outside this agent's permitted actions and is left to the post-script.

Fixed (5):

  1. Rebase onto main and resolve merge conflicts (internal/forge/forge.go): Rebased the branch (7 commits behind, mergeStateStatus=DIRTY/CONFLICTING) onto origin/main via git rebase origin/main. Resolved structural merge conflicts in internal/forge/fake.go, internal/forge/fake_test.go, internal/forge/forge.go, internal/forge/github/github.go, and internal/forge/github/github_test.go, all caused by PR feat(#7767): add GitLab trigger-token and webhook CRUD #7780 (pipeline-trigger-token and project-webhook primitives) landing on main alongside this PR's override-role primitives at the same insertion points in the Client interface, FakeClient struct, and GitHub stub methods. Combined both additions (kept both interface method blocks, both struct field blocks, both stub-method blocks); internal/forge/gitlab/gitlab_test.go and internal/forge/gitlab/repo.go auto-merged cleanly with no manual resolution needed. After the rebase, HEAD is 2 commits ahead of origin/main and 0 behind. Verified with go build ./internal/forge/..., go vet ./internal/forge/... ./internal/gitlabroles/..., gofmt -l (clean), ./hack/lint-interface-doc-sync (OK), gitleaks detect (no leaks), and go test -race -count=1 ./internal/forge/... (all packages pass) after resolving conflicts.
  2. unvalidated-input: SetPipelineVariablesMinimumOverrideRole accepted any string (internal/forge/gitlab/repo.go): Already fixed in the prior bot-triggered iteration (commit 1da82fb): forge.ValidatePipelineVarOverrideRole rejects any role not in the four documented constants, and is called from both GitLab LiveClient.SetPipelineVariablesMinimumOverrideRole and FakeClient.SetPipelineVariablesMinimumOverrideRole before a PUT is issued or a value stored. Verified this logic, its regression tests, and the shared helper all survived the rebase's conflict resolution intact (confirmed via diff against origin/main and passing tests). No further change needed; current review body confirms this finding is no longer observed.
  3. api-contract: GetPipelineVariablesMinimumOverrideRole returns ("", nil) on an absent field (internal/forge/forge.go): Already fixed in the prior iteration: the Client interface's Get/Set doc comments document that an absent ci_pipeline_variables_minimum_override_role field reads back as ("", nil), indistinguishable from an explicitly empty role. Verified this documentation survived the rebase (the GetPipelineVariablesMinimumOverrideRole/SetPipelineVariablesMinimumOverrideRole doc blocks merged cleanly with no conflict). No further change needed; current review body confirms this finding is no longer observed.
  4. nil-map-init: NewFakeClient() omitted PipelineVarOverrideRoles (internal/forge/fake.go): Already fixed in the prior iteration: PipelineVarOverrideRoles: make(map[string]string) was added to the struct literal in NewFakeClient(), matching sibling maps. This was the one file with a real rebase conflict (main had independently added PipelineTriggerTokens/ProjectHooks to the same struct literal and field block); resolved by keeping all three additions together. Verified the map is initialized post-rebase and covered by the existing direct-assignment regression test.
  5. commit-title-tier-mismatch: PR title uses feat(GitLab forge primitive: read/set project ci_pipeline_variables_minimum_override_role #7798) for an unwired internal primitive (PR title): Confirmed the finding is valid: this PR adds unwired internal forge.Client primitives (no CLI/config/workflow wiring, no caller outside internal/forge) per COMMITS.md's feat/refactor distinction, so the title should be refactor(GitLab forge primitive: read/set project ci_pipeline_variables_minimum_override_role #7798), not feat(GitLab forge primitive: read/set project ci_pipeline_variables_minimum_override_role #7798). Attempted gh pr edit 7813 --title "refactor(#7798): add GitLab pipeline-variable override-role methods" to apply the reviewer's exact remediation, but the sandbox network policy denied the mutation (403 policy_denied on POST /graphql), same as the prior iteration. PR title edits are a forge metadata mutation outside this agent's permitted actions. Recommending a human or the post-script apply the retitle above before merge, since GoReleaser builds release notes from PR titles.

Disagreed (1):

  1. Reply to and resolve all review threads: Posting replies and resolving PR review threads are forge mutations outside this agent's permitted actions (the fix agent cannot post comments on PRs/issues or otherwise mutate PR metadata beyond the code diff it commits). This is the post-script's responsibility once it publishes this run's commits and summary comment.

Tests: passed

CI inspections (10):

  1. test (passing, success): Go build/test job passed on pre-rebase head 1da82fb.
  2. web (passing, success): Web build job passed.
  3. test-sandbox-darwin (passing, success): Sandbox darwin job passed.
  4. commit-lint (passing, success): Commit-lint passed on existing commit history.
  5. functional-tests (passing, success): Functional test suite passed.
  6. e2e (passing, success): E2E job passed.
  7. behaviour (passing, success): Behaviour job passed.
  8. gate (passing, success): Functional-tests and e2e gate checks both passed.
  9. codecov/patch (passing, success): Patch coverage check passed.
  10. DCO (passing, success): DCO check passed (autonomous agent commits are exempt per repo policy).
Decision points
  • Preserved both sides' interface/struct/stub additions during conflict resolution instead of picking one side (alternatives: Take the 'ours' (main) version, dropping this PR's override-role additions, Take the 'theirs' (PR branch) version, dropping main's concurrent trigger-token/webhook additions; rationale: origin/main (via PR feat(#7767): add GitLab trigger-token and webhook CRUD #7780) and this PR add independent, non-overlapping forge.Client methods/fields that happened to land at the same file locations. Merging both preserves all functionality; dropping either side would silently delete a shipped feature.)

Next steps:

  • /fs-review — request a re-review of the changes
  • /fs-fix <your instruction> — run another fix pass with specific guidance
  • Push commits directly — review re-runs automatically on push
    Updated by fullsend fix agent

@fullsend-ai-coder
fullsend-ai-coder Bot force-pushed the agent/7798-gitlab-pipeline-override-role branch from 1da82fb to a89c97b Compare September 28, 2026 23:06
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:08 PM UTC · Completed 11:21 PM UTC

Commit: a89c97b · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $3.82

@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Sep 28, 2026
@fullsend-ai-review
fullsend-ai-review Bot dismissed stale reviews from themself September 28, 2026 23:21

Superseded by updated review

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Sep 28, 2026
@ggallen ggallen changed the title feat(#7798): add GitLab pipeline-variable override-role methods refactor(#7798): add GitLab pipeline-variable override-role methods Sep 28, 2026
@ggallen
ggallen added this pull request to the merge queue Sep 28, 2026
Merged via the queue into main with commit 3829be3 Sep 28, 2026
65 checks passed
@ggallen
ggallen deleted the agent/7798-gitlab-pipeline-override-role branch September 28, 2026 23:44
fullsend-ai-coder Bot added a commit that referenced this pull request Sep 29, 2026
…onverge

Uses the forge primitive from #7813, Get/SetPipelineVariablesMinimumOverrideRole,
to read and converge each enrolled GitLab repo's
ci_pipeline_variables_minimum_override_role toward "owner" at both fresh
install and converge/repair time, and report it as already-correct when
it is. Idempotent: an already-owner project is a no-op every time.

Active enforcement is gated behind
FULLSEND_GITLAB_PIPELINE_VAR_RESTRICTION=enforced and defaults to
report-only. Restricting the setting to owner also blocks the
Developer-level poller/dispatcher's own CreatePipeline call with
variables, internal/poll/dispatch.go, unless the poller identity is
separately raised to Owner. internal/repos/gitlab_pipeline_access.go and
gitlab_roles.go are built assuming a Developer-level poller throughout,
and ADR 0125 documents that credential-cost tradeoff as an open,
ship-gating decision, not a free hardening knob. Flipping the setting to
owner fleet-wide before that follow-up ships would break dispatch on
every enrolled repo, so this change wires and tests the primitive
without forcing that call.

Adds fresh-install, converge/repair, and already-correct coverage via
the fake forge client, plus GitHub/ErrNotSupported and injected-error
cases. Updates gitlab-role-credentials.md to point at the new wiring and
the still-open credential decision.

Addresses #7817

This branch was previously deployed

1 inactive deployment
dev — a89c97b0 Deployed Sep 28, 2026 by fullsend-ai-coder[bot] via behaviour #14366
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-merge All reviewers approved — ready to merge ready-for-review Triggers review agent dispatch risk/moderate PR risk: moderate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitLab forge primitive: read/set project ci_pipeline_variables_minimum_override_role

1 participant