Enterprise blocker: create-pull-request safe output fails with org-level required_signatures ruleset
Problem
When an organisation enforces a required_signatures ruleset (common in enterprise environments), the create-pull-request safe output fails because git am + git push produces unsigned commits. The push is rejected with:
! [remote rejected] branch -> branch (push declined due to repository rule violations)
error: failed to push some refs
This blocks any workflow using create-pull-request in organisations with signed commit requirements.
Analysis
Root cause is in actions/setup/js/create_pull_request.cjs:
- Line 694:
git am --3way ${patchFilePath} — creates a local unsigned commit
- Line 742:
git push origin ${branchName} — pushes the unsigned commit, rejected by ruleset
The same issue affects push_to_pull_request_branch.cjs.
Other safe outputs (create-issue, dispatch-workflow, add-comment, etc.) work correctly because they use the GitHub API, which signs operations automatically.
GitHub Apps DO sign commits when using the API — the createCommitOnBranch GraphQL mutation produces verified commits. The problem is specifically the git CLI path.
Related Issues
Workaround
Add the GitHub App as a bypass actor on the org's required_signatures ruleset, which undermines the purpose of the ruleset.
Implementation Plan
Replace the git am + git push pipeline with the GraphQL createCommitOnBranch mutation:
-
Parse the patch to extract file changes (additions, deletions, modifications)
- Already partially done — patch content is validated and parsed for file counts in
enforcePullRequestLimits()
- Need to extract per-file diffs into
FileAddition and FileDeletion objects
-
Create branch via API (POST /repos/{owner}/{repo}/git/refs)
- Create the branch ref pointing at the base branch HEAD
- Replaces
git checkout -b ${branchName}
-
Commit via GraphQL (createCommitOnBranch mutation)
mutation($input: CreateCommitOnBranchInput!) {
createCommitOnBranch(input: $input) {
commit { oid, url }
}
}
- Input: branch, expectedHeadOid, message, fileChanges (additions + deletions)
- GitHub signs the commit automatically
- The App token already has
contents: write permission
-
Create PR via API (already done — line 1079 uses GraphQL)
-
Update push_to_pull_request_branch.cjs with the same approach
-
Handle edge cases:
- Binary files (base64 encode for
FileAddition)
- File renames (deletion + addition)
- Large patches — GraphQL has a payload size limit; may need chunked commits
- Empty commits (
allow_empty config option)
-
Add tests in create_pull_request.test.cjs:
- Test patch-to-FileChanges conversion
- Test GraphQL commit creation
- Test with file additions, deletions, and modifications
- Test binary file handling
-
Retain git am + git push as fallback for GHES environments where GraphQL createCommitOnBranch may not be available (check API version)
Impact
This is a significant blocker for enterprise adoption. Organisations with signed commit requirements (which is increasingly standard for compliance) cannot use any workflow that creates PRs via safe outputs.
Enterprise blocker:
create-pull-requestsafe output fails with org-levelrequired_signaturesrulesetProblem
When an organisation enforces a
required_signaturesruleset (common in enterprise environments), thecreate-pull-requestsafe output fails becausegit am+git pushproduces unsigned commits. The push is rejected with:This blocks any workflow using
create-pull-requestin organisations with signed commit requirements.Analysis
Root cause is in
actions/setup/js/create_pull_request.cjs:git am --3way ${patchFilePath}— creates a local unsigned commitgit push origin ${branchName}— pushes the unsigned commit, rejected by rulesetThe same issue affects
push_to_pull_request_branch.cjs.Other safe outputs (
create-issue,dispatch-workflow,add-comment, etc.) work correctly because they use the GitHub API, which signs operations automatically.GitHub Apps DO sign commits when using the API — the
createCommitOnBranchGraphQL mutation produces verified commits. The problem is specifically thegitCLI path.Related Issues
gitare unverified; switch to GraphQL for commits #18565 — "Commits viagitare unverified; switch to GraphQL for commits"Workaround
Add the GitHub App as a bypass actor on the org's
required_signaturesruleset, which undermines the purpose of the ruleset.Implementation Plan
Replace the
git am+git pushpipeline with the GraphQLcreateCommitOnBranchmutation:Parse the patch to extract file changes (additions, deletions, modifications)
enforcePullRequestLimits()FileAdditionandFileDeletionobjectsCreate branch via API (
POST /repos/{owner}/{repo}/git/refs)git checkout -b ${branchName}Commit via GraphQL (
createCommitOnBranchmutation)contents: writepermissionCreate PR via API (already done — line 1079 uses GraphQL)
Update
push_to_pull_request_branch.cjswith the same approachHandle edge cases:
FileAddition)allow_emptyconfig option)Add tests in
create_pull_request.test.cjs:Retain
git am+git pushas fallback for GHES environments where GraphQLcreateCommitOnBranchmay not be available (check API version)Impact
This is a significant blocker for enterprise adoption. Organisations with signed commit requirements (which is increasingly standard for compliance) cannot use any workflow that creates PRs via safe outputs.