Add allow-workflows field for GitHub App workflows:write permission on safe-outputs#25817
Add allow-workflows field for GitHub App workflows:write permission on safe-outputs#25817
allow-workflows field for GitHub App workflows:write permission on safe-outputs#25817Conversation
…sion on safe-outputs (#25776) Agent-Logs-Url: https://github.com/github/gh-aw/sessions/68aaa733-6049-46fd-9e04-278b12b3a09b Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds an explicit allow-workflows opt-in for safe-outputs PR handlers so the compiler can request the GitHub App-only workflows: write permission when users intend to modify files under .github/workflows/.
Changes:
- Introduces
allow-workflows: booloncreate-pull-requestandpush-to-pull-request-branchsafe-outputs configs and threads it through parsing + docs + schema. - Updates safe-outputs permission computation to add
workflows: writewhenallow-workflows: true(and the handler isn’t staged). - Adds compile-time validation + unit tests + an ADR documenting the explicit opt-in decision.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/safe_outputs_validation.go | Adds allow-workflows validation requiring a configured GitHub App. |
| pkg/workflow/safe_outputs_permissions.go | Adds workflows: write to computed permissions when allow-workflows is enabled. |
| pkg/workflow/safe_outputs_allow_workflows_test.go | New tests covering permissions, parsing, validation, and compile-time failure. |
| pkg/workflow/push_to_pull_request_branch.go | Adds AllowWorkflows field and parses allow-workflows from config. |
| pkg/workflow/create_pull_request.go | Adds AllowWorkflows field to config struct. |
| pkg/workflow/compiler.go | Wires the new safe-outputs validation into the compile pipeline. |
| pkg/parser/schemas/main_workflow_schema.json | Extends JSON schema for both handlers with allow-workflows. |
| docs/src/content/docs/reference/safe-outputs-pull-requests.md | Documents the new allow-workflows behavior and rationale. |
| docs/src/content/docs/reference/frontmatter-full.md | Regenerates frontmatter reference including allow-workflows. |
| docs/adr/0002-explicit-opt-in-allow-workflows-permission.md | Adds ADR documenting the explicit opt-in design. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 10/10 changed files
- Comments generated: 3
| return fmt.Errorf( | ||
| "safe-outputs.%s.allow-workflows: requires a GitHub App to be configured.\n"+ | ||
| "The workflows permission is a GitHub App-only permission and cannot be granted via GITHUB_TOKEN.\n\n"+ | ||
| "Add a GitHub App configuration to safe-outputs:\n\n"+ | ||
| "safe-outputs:\n"+ | ||
| " github-app:\n"+ | ||
| " app-id: ${{ vars.APP_ID }}\n"+ | ||
| " private-key: ${{ secrets.APP_PRIVATE_KEY }}\n"+ | ||
| " %s:\n"+ | ||
| " allow-workflows: true", | ||
| handlers[0], handlers[0], |
There was a problem hiding this comment.
The validation error message only interpolates the first handler found (handlers[0]) into both the config path and the example snippet. If both create-pull-request and push-to-pull-request-branch set allow-workflows: true, the error will misleadingly point to only one handler. Consider including all handler names in the error (e.g., join the list for the message, and/or emit one line per handler path) so users can quickly find every offending config block.
| return fmt.Errorf( | |
| "safe-outputs.%s.allow-workflows: requires a GitHub App to be configured.\n"+ | |
| "The workflows permission is a GitHub App-only permission and cannot be granted via GITHUB_TOKEN.\n\n"+ | |
| "Add a GitHub App configuration to safe-outputs:\n\n"+ | |
| "safe-outputs:\n"+ | |
| " github-app:\n"+ | |
| " app-id: ${{ vars.APP_ID }}\n"+ | |
| " private-key: ${{ secrets.APP_PRIVATE_KEY }}\n"+ | |
| " %s:\n"+ | |
| " allow-workflows: true", | |
| handlers[0], handlers[0], | |
| handlerPaths := make([]string, 0, len(handlers)) | |
| handlerExamples := make([]string, 0, len(handlers)) | |
| for _, handler := range handlers { | |
| handlerPaths = append(handlerPaths, fmt.Sprintf("safe-outputs.%s.allow-workflows", handler)) | |
| handlerExamples = append(handlerExamples, fmt.Sprintf(" %s:\n allow-workflows: true", handler)) | |
| } | |
| return fmt.Errorf( | |
| "%s: requires a GitHub App to be configured.\n"+ | |
| "The workflows permission is a GitHub App-only permission and cannot be granted via GITHUB_TOKEN.\n\n"+ | |
| "Add a GitHub App configuration to safe-outputs:\n\n"+ | |
| "safe-outputs:\n"+ | |
| " github-app:\n"+ | |
| " app-id: ${{ vars.APP_ID }}\n"+ | |
| " private-key: ${{ secrets.APP_PRIVATE_KEY }}\n"+ | |
| "%s", | |
| strings.Join(handlerPaths, "\n"), | |
| strings.Join(handlerExamples, "\n"), |
| // Validate safe-outputs allow-workflows requires GitHub App | ||
| log.Printf("Validating safe-outputs allow-workflows") | ||
| if err := validateSafeOutputsAllowWorkflows(workflowData.SafeOutputs); err != nil { | ||
| return formatCompilerError(markdownPath, "error", err.Error(), err) | ||
| } |
There was a problem hiding this comment.
This new validation is inserted after the network firewall validations, splitting the safe-outputs validation block (target/max/allowed-domains) into two separate sections. For maintainability and discoverability, consider keeping all safe-outputs validations together (e.g., moving this check up near the other safe-outputs validations).
| # ADR-0002: Explicit Opt-In for GitHub App workflows:write Permission via allow-workflows Field | ||
|
|
||
| **Date**: 2026-04-11 | ||
| **Status**: Draft | ||
| **Deciders**: pelikhan, Copilot | ||
|
|
There was a problem hiding this comment.
This ADR is numbered 0002, but docs/adr/0002-allow-secrets-in-step-env-bindings-under-strict-mode.md already exists. Having two ADR-0002 documents will cause ambiguity and broken references. Please renumber this new ADR (and its title/header) to the next available number (e.g., ADR-0003) to keep the sequence unique.
✅ Design Decision Gate — ADR VerifiedThe implementation in this PR aligns with the stated Architecture Decision Record. ADR reviewed: ADR-0002: Explicit Opt-In for GitHub App workflows:write Permission via allow-workflows Field Verification SummaryAll normative requirements from the ADR are satisfied by the code changes:
|
There was a problem hiding this comment.
Implementation verified: code aligns with the linked Architecture Decision Record (ADR-0002). All MUST/MUST NOT normative requirements are satisfied. See the inline comment for the full verification matrix and two minor follow-up items (ADR numbering conflict + status update).
🧪 Test Quality Sentinel ReportTest Quality Score: 80/100✅ Excellent test quality
Test Classification DetailsAll 6 test functions
Flagged Tests — Minor Observations
|
There was a problem hiding this comment.
✅ Test Quality Sentinel: 80/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 6 tests verify observable behavioral contracts with proper build tags, no mock libraries, and descriptive assertion messages. Minor suggestions posted in the review comment.
Add three new glossary entries and update one existing entry based on changes from the past 7 days: - Add 'Allow Workflows (allow-workflows:)' — opt-in field for workflow file changes via GitHub App token (PR #25776/#25817) - Add 'Allowed Events (allowed-events:)' — review event type filter for submit-pull-request-review (PR #25484) - Add 'Effective Tokens' — weighted token count for cost estimation, referenced across audit, cost-management, and footers docs - Update 'Integrity Filtering' to mention trusted-users field (PR #25545 documented all integrity-filtering inputs) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Applies the changes from #25776 to current HEAD.
When
allowed-filestargets.github/workflows/paths, pushing requiresworkflows:write— a GitHub App-only permission the compiler never inferred. Users resorted to fragilesedinjection post-compile.Changes
allow-workflows: booloncreate-pull-requestandpush-to-pull-request-branchconfigsComputePermissionsForSafeOutputsaddsworkflows: writewhenallow-workflows: true(respects staged mode — no-op when staged)validateSafeOutputsAllowWorkflowserrors whenallow-workflows: truewithout a configured GitHub App (app-id+private-key)allowed-filespatterns for auditability)safe-outputs-pull-requests.mdandfrontmatter-full.mdUsage