|
65 | 65 | runs-on: ubuntu-latest |
66 | 66 | permissions: |
67 | 67 | contents: write |
68 | | - pull-requests: write |
69 | 68 | steps: |
70 | 69 | - uses: actions/checkout@v4 |
71 | 70 | with: |
@@ -105,133 +104,17 @@ jobs: |
105 | 104 | print(f"stable.toml -> {stable_version}") |
106 | 105 | print(f"dev.toml -> {dev_version}") |
107 | 106 | PY |
108 | | - - name: Push signed bump commit to a release branch |
| 107 | + - name: Commit and push bumped versions back to main |
109 | 108 | id: bump_commit |
110 | 109 | env: |
111 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
112 | 110 | VERSION: ${{ steps.version.outputs.version }} |
113 | 111 | run: | |
114 | | - python - <<'PY' |
115 | | - import base64 |
116 | | - import json |
117 | | - import os |
118 | | - import subprocess |
119 | | - import urllib.error |
120 | | - import urllib.request |
121 | | -
|
122 | | - head_oid = subprocess.check_output(["git", "rev-parse", "HEAD"], text=True).strip() |
123 | | - repo = os.environ["GITHUB_REPOSITORY"] |
124 | | - token = os.environ["GH_TOKEN"] |
125 | | - version = os.environ["VERSION"] |
126 | | - branch = f"release/bump-v{version}" |
127 | | -
|
128 | | - def api(path, method="GET", body=None): |
129 | | - req = urllib.request.Request( |
130 | | - f"https://api.github.com/{path}", |
131 | | - data=(json.dumps(body).encode("utf-8") if body is not None else None), |
132 | | - headers={ |
133 | | - "Authorization": f"Bearer {token}", |
134 | | - "Accept": "application/vnd.github+json", |
135 | | - "Content-Type": "application/json", |
136 | | - }, |
137 | | - method=method, |
138 | | - ) |
139 | | - with urllib.request.urlopen(req) as resp: |
140 | | - raw = resp.read() |
141 | | - return json.loads(raw) if raw else None |
142 | | -
|
143 | | - # Delete any pre-existing release branch (from a prior partial run) |
144 | | - # so the bump always starts from main's HEAD. Avoids STALE_DATA from |
145 | | - # createCommitOnBranch and prevents stacking multiple bump commits. |
146 | | - # Any open PR on the stale branch gets auto-closed when the branch |
147 | | - # is deleted, which is fine — we always open a fresh PR below. |
148 | | - try: |
149 | | - api(f"repos/{repo}/git/refs/heads/{branch}", method="DELETE") |
150 | | - print(f"deleted stale branch: {branch}") |
151 | | - except urllib.error.HTTPError as error: |
152 | | - if error.code not in (404, 422): # ref doesn't exist; nothing to clean |
153 | | - raise |
154 | | -
|
155 | | - api( |
156 | | - f"repos/{repo}/git/refs", |
157 | | - method="POST", |
158 | | - body={"ref": f"refs/heads/{branch}", "sha": head_oid}, |
159 | | - ) |
160 | | - expected_oid = head_oid |
161 | | -
|
162 | | - def b64(path: str) -> str: |
163 | | - with open(path, "rb") as fp: |
164 | | - return base64.b64encode(fp.read()).decode("ascii") |
165 | | -
|
166 | | - mutation = """ |
167 | | - mutation($input: CreateCommitOnBranchInput!) { |
168 | | - createCommitOnBranch(input: $input) { |
169 | | - commit { oid url } |
170 | | - } |
171 | | - } |
172 | | - """ |
173 | | -
|
174 | | - payload = { |
175 | | - "query": mutation, |
176 | | - "variables": { |
177 | | - "input": { |
178 | | - "branch": { |
179 | | - "repositoryNameWithOwner": repo, |
180 | | - "branchName": branch, |
181 | | - }, |
182 | | - "message": { |
183 | | - "headline": f"Bump version to v{version} [skip ci]", |
184 | | - }, |
185 | | - "expectedHeadOid": expected_oid, |
186 | | - "fileChanges": { |
187 | | - "additions": [ |
188 | | - {"path": "stable.toml", "contents": b64("stable.toml")}, |
189 | | - {"path": "dev.toml", "contents": b64("dev.toml")}, |
190 | | - ] |
191 | | - }, |
192 | | - } |
193 | | - }, |
194 | | - } |
195 | | -
|
196 | | - request = urllib.request.Request( |
197 | | - "https://api.github.com/graphql", |
198 | | - data=json.dumps(payload).encode("utf-8"), |
199 | | - headers={ |
200 | | - "Authorization": f"Bearer {token}", |
201 | | - "Accept": "application/vnd.github+json", |
202 | | - "Content-Type": "application/json", |
203 | | - }, |
204 | | - method="POST", |
205 | | - ) |
206 | | - with urllib.request.urlopen(request) as resp: |
207 | | - body = json.loads(resp.read()) |
208 | | - if body.get("errors"): |
209 | | - raise SystemExit(f"GraphQL error: {body['errors']}") |
210 | | - commit = body["data"]["createCommitOnBranch"]["commit"] |
211 | | - print(f"bump commit: {commit['oid']} -> {commit['url']}") |
212 | | -
|
213 | | - with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fp: |
214 | | - fp.write(f"branch={branch}\n") |
215 | | - fp.write(f"oid={commit['oid']}\n") |
216 | | - PY |
217 | | - - name: Open PR for the version bump |
218 | | - env: |
219 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
220 | | - VERSION: ${{ steps.version.outputs.version }} |
221 | | - BRANCH: ${{ steps.bump_commit.outputs.branch }} |
222 | | - run: | |
223 | | - gh pr create \ |
224 | | - --base main \ |
225 | | - --head "$BRANCH" \ |
226 | | - --title "Bump version to v${VERSION} [skip ci]" \ |
227 | | - --body "Automated patch bump emitted by the stable publish workflow. [skip ci]" |
228 | | - - name: Try to auto-merge the bump PR |
229 | | - env: |
230 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
231 | | - BRANCH: ${{ steps.bump_commit.outputs.branch }} |
232 | | - run: | |
233 | | - gh pr merge "$BRANCH" --squash --auto --delete-branch \ |
234 | | - || echo "auto-merge unavailable; PR left open for manual merge" |
| 112 | + git config user.name "github-actions[bot]" |
| 113 | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" |
| 114 | + git add stable.toml dev.toml |
| 115 | + git commit -m "Bump version to v${VERSION} [skip ci]" |
| 116 | + git push origin HEAD:main |
| 117 | + echo "oid=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" |
235 | 118 | - name: Use stable.toml as pyproject.toml |
236 | 119 | run: cp stable.toml pyproject.toml |
237 | 120 | - name: Build sdist and wheel |
|
0 commit comments