Problem
Safe-output pull request workflows often need caller-specific policy choices in reusable workflow_call workflows. Today several PR safe-output policy fields are compile-time-only because they are validated as static enums or static strings.
High-value examples include:
safe-outputs:
push-to-pull-request-branch:
protected-files: ${{ inputs.protected-files-policy }}
patch-format: ${{ inputs.patch-format }}
Without expression support, reusable workflow authors need separate workflow files for otherwise-identical workflows that differ only in protected-file policy or patch transport format.
Related context: #23724 confirmed appetite for runtime parameterization of frontmatter fields where safe. Earlier follow-ups covered timeout/version fields, but not safe-output PR policy fields.
Desired Behavior
Allow expression strings for enum-like PR policy fields while preserving existing literal validation:
on:
workflow_call:
inputs:
protected-files-policy:
type: string
default: fallback-to-issue
patch-format:
type: string
default: am
---
safe-outputs:
push-to-pull-request-branch:
protected-files: ${{ inputs.protected-files-policy }}
patch-format: ${{ inputs.patch-format }}
Literal values must still work and should continue to receive compile-time enum validation:
safe-outputs:
push-to-pull-request-branch:
protected-files: fallback-to-issue
patch-format: am
Proposed Scope
Start with enum-like policy fields that do not change the generated job permission model:
safe-outputs.push-to-pull-request-branch.protected-files
safe-outputs.push-to-pull-request-branch.patch-format
safe-outputs.create-pull-request.protected-files
safe-outputs.create-pull-request.patch-format
- Any shared validation helper used by both handlers, such as
validateStringEnumField, so the behavior stays consistent.
If object-form protected-files cannot reasonably support expressions for nested policy, it is acceptable to start with expression support for the string policy form only.
Implementation Plan
-
Schema updates
- Update the relevant
protected-files and patch-format schema definitions to accept either the current enum literals or a GitHub Actions expression string.
- Keep object-form
protected-files behavior unchanged unless nested expression support is straightforward.
-
Parser and validation updates
- Update enum validation helpers so literal strings are validated against the existing allowlist, while expression strings are accepted and passed through.
- Preserve clear errors for invalid literal strings.
- Ensure both create-PR and push-to-PR-branch paths use the same helper behavior.
-
Compilation/runtime behavior
- Ensure the expression string is emitted into the generated handler config in a runtime-evaluable way.
- Confirm JavaScript safe-output handlers evaluate the resolved runtime value against the same policy enum before applying it.
- Fail closed at runtime if the resolved value is not one of the allowed policies/formats.
-
Tests
- Add schema/parser tests for literal valid values, literal invalid values, and expression values.
- Add compiler tests showing expressions appear in the safe-output handler config.
- Add JS runtime tests for invalid resolved values to ensure fail-closed behavior.
-
Documentation
- Update PR safe-output docs with reusable-workflow examples.
- Document the allowed runtime-resolved values for each field.
Acceptance Criteria
Problem
Safe-output pull request workflows often need caller-specific policy choices in reusable
workflow_callworkflows. Today several PR safe-output policy fields are compile-time-only because they are validated as static enums or static strings.High-value examples include:
Without expression support, reusable workflow authors need separate workflow files for otherwise-identical workflows that differ only in protected-file policy or patch transport format.
Related context: #23724 confirmed appetite for runtime parameterization of frontmatter fields where safe. Earlier follow-ups covered timeout/version fields, but not safe-output PR policy fields.
Desired Behavior
Allow expression strings for enum-like PR policy fields while preserving existing literal validation:
Literal values must still work and should continue to receive compile-time enum validation:
Proposed Scope
Start with enum-like policy fields that do not change the generated job permission model:
safe-outputs.push-to-pull-request-branch.protected-filessafe-outputs.push-to-pull-request-branch.patch-formatsafe-outputs.create-pull-request.protected-filessafe-outputs.create-pull-request.patch-formatvalidateStringEnumField, so the behavior stays consistent.If object-form
protected-filescannot reasonably support expressions for nestedpolicy, it is acceptable to start with expression support for the string policy form only.Implementation Plan
Schema updates
protected-filesandpatch-formatschema definitions to accept either the current enum literals or a GitHub Actions expression string.protected-filesbehavior unchanged unless nested expression support is straightforward.Parser and validation updates
Compilation/runtime behavior
Tests
Documentation
Acceptance Criteria
protected-filesandpatch-formatliteral values remain backward compatible.