fix: propagate callback permissions into top-level workflow permissions - #191
Merged
Merged
Conversation
Per-callback permissions declared in the manifest (such as id-token: write for OIDC) were parsed into CallbackInfo but never emitted. A reusable-workflow caller job cannot set job-level permissions, so the calling workflow's top-level permissions must grant the union of base scopes and every scope any invoked callback requires. Without id-token: write at the caller top level, GitHub rejects the callee with 'requesting id-token: write, but is only allowed id-token: none'. Collect the union of callback permissions across the dependency graph and emit it on top of each generator's base scopes, with callback-only scopes appended in sorted order for deterministic output. Applied to orchestrate, promote, hotfix, and rollback generators. The no-callback-permissions path is byte identical to prior output. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
…dent Use a lexicographic comparison so the union and base promotion pick the same deterministic value when callbacks set a scope to different values, removing the latent dependency on map iteration order. write still wins over read wins over none, matching the monotonic permission order. Signed-off-by: Joshua Temple <joshua.temple@stablekernel.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.
Problem
Per-callback workflow
permissionsdeclared in a manifest (such asid-token: writefor OIDC) were parsed intoCallbackInfo.Permissionsbut never emitted into any generated workflow. A reusable-workflow caller job legally cannot set job-levelpermissions, so the calling workflow's top-levelpermissionsblock must grant everything any invoked callback requires. With the top-level block hardcoded, a callee needing a scope the caller lacks fails: GitHub rejects it withrequesting id-token: write, but is only allowed id-token: none.Fix
Compute the union of callback
permissionsacross the dependency graph and emit it on top of each generator's existing base scopes. Base scopes keep their historical order for byte-identical output when no callback declares permissions; callback-only scopes are appended in sorted order so generation stays deterministic. A scope required aswriteby any callback is promoted towrite.Applied to the generators that invoke reusable-workflow callbacks: orchestrate, promote, hotfix, and rollback. Standalone generators (external-update, merge-queue, pr-preview, validate-check) invoke no reusable callbacks and are unchanged.
Verification
internal/generate/callback_permissions_test.go: union includesid-token: writeplus base scopes; deterministic sorted order across multiple scopes; no-callback output byte-identical; promote and rollback covered.determinism_test.goconfig extended with callbacks carryingpermissionsmaps so the determinism guarantee covers the new map-ordered emission.e2e/scenarios/orchestrate/callback-permissions-oidc.yamlasserts a callback withid-token: writeproduces the top-level union and that no job-level permissions block is emitted on the caller job.go build ./... && go test ./... && golangci-lint run ./...green; e2e module builds and vets clean.