Skip to content

Commit 19b0ce4

Browse files
committed
Sign CI version-bump commits via GraphQL createCommitOnBranch
Replace the direct `git push` to `main` with a Python call to the GraphQL createCommitOnBranch mutation. GitHub signs the resulting commit with its own key, satisfying the `main` branch's "require signed commits" rule. The `github-actions[bot]` actor still needs to be on the branch-protection bypass list for the "require PR" rule (repo settings, not codified here).
1 parent 1cd7e28 commit 19b0ce4

1 file changed

Lines changed: 66 additions & 6 deletions

File tree

.github/workflows/ci-stable.yml

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,73 @@ jobs:
104104
print(f"stable.toml -> {stable_version}")
105105
print(f"dev.toml -> {dev_version}")
106106
PY
107-
- name: Commit bumped versions back to main
107+
- name: Commit bumped versions back to main (signed via GitHub API)
108+
env:
109+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
110+
VERSION: ${{ steps.version.outputs.version }}
108111
run: |
109-
git config user.name "github-actions[bot]"
110-
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
111-
git add stable.toml dev.toml
112-
git commit -m "Bump version to v${{ steps.version.outputs.version }} [skip ci]"
113-
git push origin HEAD:main
112+
python - <<'PY'
113+
import base64
114+
import json
115+
import os
116+
import subprocess
117+
import urllib.request
118+
119+
head_oid = subprocess.check_output(["git", "rev-parse", "HEAD"], text=True).strip()
120+
repo = os.environ["GITHUB_REPOSITORY"]
121+
token = os.environ["GH_TOKEN"]
122+
version = os.environ["VERSION"]
123+
124+
def b64(path: str) -> str:
125+
with open(path, "rb") as fp:
126+
return base64.b64encode(fp.read()).decode("ascii")
127+
128+
mutation = """
129+
mutation($input: CreateCommitOnBranchInput!) {
130+
createCommitOnBranch(input: $input) {
131+
commit { oid url }
132+
}
133+
}
134+
"""
135+
136+
payload = {
137+
"query": mutation,
138+
"variables": {
139+
"input": {
140+
"branch": {
141+
"repositoryNameWithOwner": repo,
142+
"branchName": "main",
143+
},
144+
"message": {
145+
"headline": f"Bump version to v{version} [skip ci]",
146+
},
147+
"expectedHeadOid": head_oid,
148+
"fileChanges": {
149+
"additions": [
150+
{"path": "stable.toml", "contents": b64("stable.toml")},
151+
{"path": "dev.toml", "contents": b64("dev.toml")},
152+
]
153+
},
154+
}
155+
},
156+
}
157+
158+
request = urllib.request.Request(
159+
"https://api.github.com/graphql",
160+
data=json.dumps(payload).encode("utf-8"),
161+
headers={
162+
"Authorization": f"Bearer {token}",
163+
"Accept": "application/vnd.github+json",
164+
"Content-Type": "application/json",
165+
},
166+
method="POST",
167+
)
168+
with urllib.request.urlopen(request) as resp:
169+
body = json.loads(resp.read())
170+
if body.get("errors"):
171+
raise SystemExit(f"GraphQL error: {body['errors']}")
172+
print(body["data"]["createCommitOnBranch"]["commit"])
173+
PY
114174
- name: Use stable.toml as pyproject.toml
115175
run: cp stable.toml pyproject.toml
116176
- name: Build sdist and wheel

0 commit comments

Comments
 (0)