Skip to content

Commit 39bb1b0

Browse files
authored
Merge pull request #125 from swgoh-utils/ci/release-pr-without-gh-pr-create
ci(release): stage the release PR instead of opening it, and move to comlink 4.4.2
2 parents fa0e550 + 3e76873 commit 39bb1b0

4 files changed

Lines changed: 61 additions & 45 deletions

File tree

.github/workflows/integration.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ jobs:
2121
services:
2222
# Pinned deliberately: on `latest`, an upstream Comlink release lands in CI with no
2323
# commit of ours, so a red suite carries no information about the change under test.
24-
# Bump this tag on purpose. 4.4.1 is the current release and matches what `latest`
25-
# resolved to when this was pinned.
24+
# Bump this tag on purpose, and keep both services on the same tag.
25+
# 4.4.2 fixes the /data fetch that 4.4.0 and 4.4.1 could not complete.
2626
comlink:
2727
image: ghcr.io/swgoh-utils/swgoh-comlink:4.4.2
2828
env:
@@ -31,7 +31,7 @@ jobs:
3131
- 3000:3000
3232

3333
comlink-hmac:
34-
image: ghcr.io/swgoh-utils/swgoh-comlink:4.4.1
34+
image: ghcr.io/swgoh-utils/swgoh-comlink:4.4.2
3535
env:
3636
APP_NAME: comlink-python-hmac-integration-tests
3737
ACCESS_KEY: ${{ secrets.COMLINK_ACCESS_KEY }}

.github/workflows/prepare-release.yml

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
name: prepare release
22

33
# Manually dispatched from `develop`. Computes the next version from Conventional
4-
# Commits, regenerates CHANGELOG.md, and opens a PR into `main`. The PR carries the
5-
# full develop payload plus the changelog commit, so merging it promotes develop ->
4+
# Commits, regenerates CHANGELOG.md, and pushes a `release/<tag>` branch carrying the
5+
# full develop payload plus the changelog commit. Merging that branch promotes develop ->
66
# main with the changelog already in place — BEFORE the release workflow cuts the tag.
7+
#
8+
# This workflow deliberately does NOT open the pull request. Opening it here would make
9+
# the PR authored by github-actions[bot], and a bot-authored PR does not trigger the
10+
# `pull_request` workflows (CI, Integration Tests, Commit Lint) that gate `main` — the
11+
# release would arrive unverified. Instead the release PR text is written to a file on
12+
# the release branch and a prefilled "create PR" link is put in the job summary, so a
13+
# maintainer opens it in two clicks and the checks run as normal.
714

815
on:
916
workflow_dispatch:
@@ -16,11 +23,10 @@ on:
1623

1724
permissions:
1825
contents: write
19-
pull-requests: write
2026

2127
jobs:
2228
prepare:
23-
name: Regenerate changelog and open release PR
29+
name: Regenerate changelog and stage the release branch
2430
runs-on: ubuntu-latest
2531
if: github.ref == 'refs/heads/develop'
2632
steps:
@@ -53,22 +59,62 @@ jobs:
5359
- name: Regenerate CHANGELOG.md
5460
run: uv run git-changelog --bump '${{ inputs.bump }}'
5561

56-
- name: Open release PR
57-
env:
58-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
62+
- name: Write the release PR text
63+
id: pr_text
64+
run: |
65+
set -euo pipefail
66+
tag="${{ steps.version.outputs.tag }}"
67+
body_file=".github/release-pr/${tag}.md"
68+
mkdir -p "$(dirname "${body_file}")"
69+
70+
# Pull just this version's section out of the freshly regenerated changelog:
71+
# start at its anchor, stop at the next one.
72+
notes="$(awk -v t="${tag}" \
73+
'BEGIN{p="^<a name=\""t"\"></a>$"} $0 ~ p {f=1} f && /^<a name=/ && ++n>1 {exit} f' \
74+
CHANGELOG.md)"
75+
76+
{
77+
printf 'Automated release prep for **%s**. CHANGELOG.md regenerated via git-changelog.\n\n' "${tag}"
78+
printf 'Merging promotes `develop` -> `main` with the changelog already in place.\n'
79+
printf 'Afterwards, run the **release** workflow on `main` to build, publish, and tag %s.\n\n' "${tag}"
80+
printf -- '---\n\n'
81+
printf '%s\n' "${notes}"
82+
} > "${body_file}"
83+
84+
echo "body_file=${body_file}" >> "$GITHUB_OUTPUT"
85+
86+
- name: Push the release branch
5987
run: |
6088
set -euo pipefail
6189
tag="${{ steps.version.outputs.tag }}"
6290
branch="release/${tag}"
6391
git config user.name "github-actions[bot]"
6492
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
6593
git switch -c "${branch}"
66-
git add CHANGELOG.md
94+
git add CHANGELOG.md "${{ steps.pr_text.outputs.body_file }}"
6795
# `chore` keeps this bookkeeping commit out of the rendered sections;
6896
# `docs` would list every release's regeneration in the next release.
6997
git commit -m "chore(changelog): update for ${tag}"
7098
git push --force-with-lease origin "${branch}"
71-
gh pr create \
72-
--base main --head "${branch}" \
73-
--title "chore(release): ${tag}" \
74-
--body "Automated release prep for **${tag}**. Regenerated CHANGELOG.md via git-changelog. Merging promotes develop -> main; then run the release workflow on main to build, publish, and tag ${tag}."
99+
100+
- name: Summarise how to open the release PR
101+
run: |
102+
set -euo pipefail
103+
tag="${{ steps.version.outputs.tag }}"
104+
branch="release/${tag}"
105+
body_file="${{ steps.pr_text.outputs.body_file }}"
106+
title="chore(release): ${tag}"
107+
# Only the title is prefilled via the URL: bodies routinely exceed what a query
108+
# string can carry, so the body is copied from the file on the branch instead.
109+
encoded_title="$(jq -rn --arg t "${title}" '$t|@uri')"
110+
url="${{ github.server_url }}/${{ github.repository }}/compare/main...${branch}?expand=1&title=${encoded_title}"
111+
112+
{
113+
printf '## %s is staged\n\n' "${tag}"
114+
printf 'Branch `%s` is pushed. Open the PR manually — a bot-authored PR would not run the `pull_request` checks that gate `main`.\n\n' "${branch}"
115+
printf '### [→ Open the release PR](%s)\n\n' "${url}"
116+
printf 'Base `main`, head `%s`, title:\n\n```\n%s\n```\n\n' "${branch}" "${title}"
117+
printf 'The body below is also committed to `%s` on that branch — copy it in:\n\n' "${body_file}"
118+
printf -- '---\n\n'
119+
cat "${body_file}"
120+
} >> "$GITHUB_STEP_SUMMARY"

tests/integration/test_async_client.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,11 @@
33
import pytest
44

55
from swgoh_comlink import SwgohComlinkAsync
6-
from swgoh_comlink.exceptions import SwgohComlinkException
76

87
from .conftest import COMLINK_URL, TEST_ALLYCODE
98

109
pytestmark = [pytest.mark.integration, pytest.mark.asyncio]
1110

12-
# A cold service container in CI cannot complete a /data fetch from the upstream game
13-
# servers: every form of the request fails with HTTP 400 and the body "Did not receive a
14-
# response code back from the server, even after a retry." The trailing hint about the
15-
# parameter being invalid is boilerplate — request_segment, a Segment aggregate, and a
16-
# single collection value all fail identically, on both 4.4.0 and 4.4.1, while every
17-
# other endpoint works. Nothing in this library can fix that, so the /data tests are
18-
# expected to fail there. Non-strict on purpose: they pass against a warm instance, and
19-
# an XPASS is the signal that upstream has recovered and this marker can come off.
20-
data_endpoint_unavailable = pytest.mark.xfail(
21-
raises=SwgohComlinkException,
22-
reason="upstream /data fetch fails on a cold CI service container",
23-
)
24-
2511

2612
async def test_get_enums(async_comlink):
2713
"""GET /enums returns game enum definitions."""
@@ -93,7 +79,6 @@ async def test_get_guilds_by_name(async_comlink):
9379
assert len(result["guild"]) > 0
9480

9581

96-
@data_endpoint_unavailable
9782
async def test_get_game_data_filtered(async_comlink):
9883
"""POST /data with a single items collection populates that collection and no other.
9984

tests/integration/test_sync_client.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,11 @@
33
import pytest
44

55
from swgoh_comlink import SwgohComlink
6-
from swgoh_comlink.exceptions import SwgohComlinkException
76

87
from .conftest import COMLINK_URL, TEST_ALLYCODE
98

109
pytestmark = pytest.mark.integration
1110

12-
# A cold service container in CI cannot complete a /data fetch from the upstream game
13-
# servers: every form of the request fails with HTTP 400 and the body "Did not receive a
14-
# response code back from the server, even after a retry." The trailing hint about the
15-
# parameter being invalid is boilerplate — request_segment, a Segment aggregate, and a
16-
# single collection value all fail identically, on both 4.4.0 and 4.4.1, while every
17-
# other endpoint works. Nothing in this library can fix that, so the /data tests are
18-
# expected to fail there. Non-strict on purpose: they pass against a warm instance, and
19-
# an XPASS is the signal that upstream has recovered and this marker can come off.
20-
data_endpoint_unavailable = pytest.mark.xfail(
21-
raises=SwgohComlinkException,
22-
reason="upstream /data fetch fails on a cold CI service container",
23-
)
24-
2511

2612
def test_get_enums(comlink):
2713
"""GET /enums returns game enum definitions."""
@@ -93,7 +79,6 @@ def test_get_guilds_by_name(comlink):
9379
assert len(result["guild"]) > 0
9480

9581

96-
@data_endpoint_unavailable
9782
def test_get_game_data_filtered(comlink):
9883
"""POST /data with a single items collection populates that collection and no other.
9984

0 commit comments

Comments
 (0)