-
Notifications
You must be signed in to change notification settings - Fork 307
Description
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
- Commits via
gitare unverified; switch to GraphQL for commits #18565 — "Commits viagitare unverified; switch to GraphQL for commits" - Replace format-patch/git-am pipeline with tree diff + GraphQL commit API #18900 — "Replace format-patch/git-am pipeline with tree diff + GraphQL commit API"
- Commits made by AI do not have signature #20322 — "Commits made by AI do not have signature"
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
FileAdditionandFileDeletionobjects
- Already partially done — patch content is validated and parsed for file counts in
-
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 (
createCommitOnBranchmutation)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: writepermission
-
Create PR via API (already done — line 1079 uses GraphQL)
- No changes needed here
-
Update
push_to_pull_request_branch.cjswith 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_emptyconfig option)
- Binary files (base64 encode for
-
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 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.