Skip to content

Commit d980cbe

Browse files
committed
ci: use one SDK release PR
1 parent 6321d5b commit d980cbe

3 files changed

Lines changed: 110 additions & 38 deletions

File tree

.github/workflows/release-please.yml

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
name: Release Please
2+
3+
# `next` accumulates validated SDK changes in one versioned PR to `main`.
4+
# Merging that PR creates the GitHub release; the package publishing workflow
5+
# runs from the release event.
26
on:
37
push:
48
branches:
9+
- next
510
- main
611

712
permissions:
813
contents: read
914

15+
concurrency:
16+
group: release-please
17+
cancel-in-progress: false
18+
1019
jobs:
1120
release-please:
1221
if: github.repository == 'kernel/kernel-python-sdk'
@@ -26,7 +35,68 @@ jobs:
2635
permission-pull-requests: write
2736
permission-workflows: write
2837

29-
- uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1
30-
id: release
38+
- name: Set up Node
39+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
40+
with:
41+
node-version: '18.20.2'
42+
43+
- name: Set up pnpm
44+
uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4
3145
with:
32-
token: ${{ steps.release-token.outputs.token }}
46+
version: '9.11.0'
47+
run_install: false
48+
49+
- name: Build pinned release tooling
50+
id: tooling
51+
env:
52+
RELEASE_PLEASE_DIR: ${{ runner.temp }}/release-please
53+
RELEASE_PLEASE_SHA: a116e1e520e0f87824acf46a2e79c91d41e819d7
54+
run: |
55+
set -euo pipefail
56+
rm -rf "$RELEASE_PLEASE_DIR"
57+
git init "$RELEASE_PLEASE_DIR"
58+
git -C "$RELEASE_PLEASE_DIR" remote add origin https://github.com/stainless-api/release-please.git
59+
git -C "$RELEASE_PLEASE_DIR" fetch --depth=1 origin "$RELEASE_PLEASE_SHA"
60+
git -C "$RELEASE_PLEASE_DIR" checkout --detach FETCH_HEAD
61+
pnpm --dir "$RELEASE_PLEASE_DIR" install --frozen-lockfile
62+
pnpm --dir "$RELEASE_PLEASE_DIR" build
63+
echo "cli=$RELEASE_PLEASE_DIR/build/src/bin/release-please.js" >> "$GITHUB_OUTPUT"
64+
65+
- name: Open or update the release PR
66+
if: github.ref_name == 'next'
67+
env:
68+
GH_TOKEN: ${{ steps.release-token.outputs.token }}
69+
RELEASE_PLEASE: ${{ steps.tooling.outputs.cli }}
70+
run: |
71+
set -euo pipefail
72+
node "$RELEASE_PLEASE" release-pr \
73+
--repo-url "$GITHUB_REPOSITORY" \
74+
--token "$GH_TOKEN" \
75+
--target-branch main \
76+
--changes-branch next
77+
78+
- name: Remove the legacy promotion PR
79+
if: github.ref_name == 'next'
80+
env:
81+
GH_TOKEN: ${{ steps.release-token.outputs.token }}
82+
run: |
83+
set -euo pipefail
84+
legacy=$(gh pr list --repo "$GITHUB_REPOSITORY" --head stainless/release \
85+
--state open --json number --jq '.[].number')
86+
for pr in $legacy; do
87+
gh pr close "$pr" --repo "$GITHUB_REPOSITORY" \
88+
--comment "Superseded by the versioned release PR from next to main."
89+
done
90+
gh api -X DELETE "repos/$GITHUB_REPOSITORY/git/refs/heads/stainless/release" >/dev/null 2>&1 || true
91+
92+
- name: Create the GitHub release
93+
if: github.ref_name == 'main'
94+
env:
95+
GH_TOKEN: ${{ steps.release-token.outputs.token }}
96+
RELEASE_PLEASE: ${{ steps.tooling.outputs.cli }}
97+
run: |
98+
set -euo pipefail
99+
node "$RELEASE_PLEASE" github-release \
100+
--repo-url "$GITHUB_REPOSITORY" \
101+
--token "$GH_TOKEN" \
102+
--target-branch main

.github/workflows/stlc-promote.yml

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
name: Promote SDKs
1+
name: Promote SDK changes
22

3-
# Production requires pull requests, so staging is promoted through a merge-
4-
# commit PR. Never squash or rebase this cross-repo PR: preserving the incoming
5-
# commits keeps production and staging on one ancestry chain.
3+
# Staging is the generator's integration history. Production `next` is the
4+
# developer-facing queue for the next release. This workflow combines the
5+
# latest released state with validated staging changes, then advances `next`.
6+
# Release automation maintains the single versioned PR from `next` to `main`.
67
on:
78
push:
89
branches: [main]
@@ -35,49 +36,49 @@ jobs:
3536
repositories: kernel-python-sdk
3637
permission-contents: write
3738
permission-workflows: write
38-
permission-pull-requests: write
3939

40-
- name: Fetch production main
40+
- name: Fetch production branches
41+
id: production
4142
env:
4243
GH_TOKEN: ${{ steps.production-token.outputs.token }}
4344
PRODUCTION_REPO: kernel/kernel-python-sdk
4445
run: |
45-
git remote add production "https://x-access-token:${GH_TOKEN}@github.com/${PRODUCTION_REPO}.git"
46+
set -euo pipefail
47+
git remote add production \
48+
"https://x-access-token:${GH_TOKEN}@github.com/${PRODUCTION_REPO}.git"
4649
git fetch production main
47-
48-
- name: Check whether production already has staging's content
49-
id: diff
50-
run: |
51-
MERGED=$(git merge-tree --write-tree production/main origin/main) || MERGED=conflict
52-
PRODUCTION_TREE=$(git rev-parse 'production/main^{tree}')
53-
if [ "$MERGED" = "$PRODUCTION_TREE" ]; then
54-
echo "Production already contains staging's content. Nothing to promote."
55-
echo "synced=true" >> "$GITHUB_OUTPUT"
50+
if git ls-remote --exit-code --heads production next >/dev/null 2>&1; then
51+
git fetch production next
52+
echo "has_next=true" >> "$GITHUB_OUTPUT"
5653
else
57-
echo "synced=false" >> "$GITHUB_OUTPUT"
54+
echo "has_next=false" >> "$GITHUB_OUTPUT"
5855
fi
5956
60-
- name: Push the production release branch
61-
if: steps.diff.outputs.synced == 'false'
57+
- name: Prepare the next release branch
6258
env:
59+
APP_SLUG: ${{ steps.production-token.outputs.app-slug }}
6360
GH_TOKEN: ${{ steps.production-token.outputs.token }}
64-
PRODUCTION_REPO: kernel/kernel-python-sdk
65-
run: git push production origin/main:refs/heads/stainless/release --force
61+
HAS_NEXT: ${{ steps.production.outputs.has_next }}
62+
run: |
63+
set -euo pipefail
64+
bot_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)
65+
git config user.name "${APP_SLUG}[bot]"
66+
git config user.email "${bot_id}+${APP_SLUG}[bot]@users.noreply.github.com"
67+
68+
git checkout -B stlc/promote-next origin/main
69+
if ! git merge-base --is-ancestor production/main HEAD; then
70+
git merge --no-edit production/main
71+
fi
6672
67-
- name: Open or update the promote PR
68-
if: steps.diff.outputs.synced == 'false'
73+
if [ "$HAS_NEXT" = "true" ] && ! git merge-base --is-ancestor production/next HEAD; then
74+
echo "::error title=Promotion blocked::production next has commits that are not present in staging or production main."
75+
exit 1
76+
fi
77+
78+
- name: Update the pending release
6979
env:
7080
GH_TOKEN: ${{ steps.production-token.outputs.token }}
71-
PRODUCTION_REPO: kernel/kernel-python-sdk
7281
run: |
73-
body=$(mktemp)
74-
git log --oneline production/main..origin/main > "$body"
75-
existing=$(gh pr list --repo "$PRODUCTION_REPO" --head stainless/release --state open --json number --jq 'if length == 0 then "" else .[0].number end')
76-
if [ -z "$existing" ]; then
77-
gh pr create --repo "$PRODUCTION_REPO" --base main --head stainless/release --title "Release SDK updates" --body-file "$body"
78-
else
79-
gh pr edit "$existing" --repo "$PRODUCTION_REPO" --title "Release SDK updates" --body-file "$body"
80-
fi
81-
if ! gh pr merge stainless/release --repo "$PRODUCTION_REPO" --merge --auto; then
82-
echo "::warning title=Manual promotion required::Merge the promote PR with a merge commit."
83-
fi
82+
set -euo pipefail
83+
git push production HEAD:refs/heads/next
84+
echo "Updated production next; the versioned release PR will be opened or refreshed."

release-please-config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"bump-minor-pre-major": true,
1111
"bump-patch-for-minor-pre-major": false,
1212
"pull-request-header": "Automated Release PR",
13+
"pull-request-footer": "Merge this pull request with a merge commit. Merging creates the GitHub release and publishes the package.",
1314
"pull-request-title-pattern": "release: ${version}",
1415
"changelog-sections": [
1516
{

0 commit comments

Comments
 (0)