Skip to content

Commit 9529bea

Browse files
authored
Merge pull request #141 from kernel/stainless/release
Release SDK updates
2 parents 140bfdd + 53eb143 commit 9529bea

2 files changed

Lines changed: 190 additions & 0 deletions

File tree

.github/workflows/stlc-promote.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Promote SDKs
2+
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.
6+
on:
7+
push:
8+
branches: [main]
9+
workflow_dispatch: {}
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
promote:
16+
if: github.repository == 'kernel/kernel-python-sdk-staging'
17+
runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }}
18+
concurrency:
19+
group: stlc-promote
20+
cancel-in-progress: true
21+
steps:
22+
- name: Check out staging
23+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
24+
with:
25+
fetch-depth: 0
26+
persist-credentials: false
27+
28+
- name: Mint production token
29+
id: production-token
30+
uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
31+
with:
32+
app-id: ${{ secrets.ADMIN_APP_ID }}
33+
private-key: ${{ secrets.ADMIN_APP_PRIVATE_KEY }}
34+
owner: kernel
35+
repositories: kernel-python-sdk
36+
permission-contents: write
37+
permission-workflows: write
38+
permission-pull-requests: write
39+
40+
- name: Fetch production main
41+
env:
42+
GH_TOKEN: ${{ steps.production-token.outputs.token }}
43+
PRODUCTION_REPO: kernel/kernel-python-sdk
44+
run: |
45+
git remote add production "https://x-access-token:${GH_TOKEN}@github.com/${PRODUCTION_REPO}.git"
46+
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"
56+
else
57+
echo "synced=false" >> "$GITHUB_OUTPUT"
58+
fi
59+
60+
- name: Push the production release branch
61+
if: steps.diff.outputs.synced == 'false'
62+
env:
63+
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
66+
67+
- name: Open or update the promote PR
68+
if: steps.diff.outputs.synced == 'false'
69+
env:
70+
GH_TOKEN: ${{ steps.production-token.outputs.token }}
71+
PRODUCTION_REPO: kernel/kernel-python-sdk
72+
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

.github/workflows/stlc-sync.yml

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
name: Sync SDK repos
2+
3+
# Keeps production and staging on one fast-forward-only history. Optional
4+
# dispatch tokens make the polling loop eager; the scheduled back-sync is the
5+
# safety backstop when those secrets are absent.
6+
on:
7+
schedule:
8+
- cron: '7,37 * * * *'
9+
workflow_dispatch: {}
10+
repository_dispatch:
11+
types: [prod-released]
12+
release:
13+
types: [published]
14+
push:
15+
branches: [main]
16+
17+
jobs:
18+
back-sync:
19+
if: >-
20+
github.repository == 'kernel/kernel-python-sdk-staging' &&
21+
(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch')
22+
runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }}
23+
permissions:
24+
contents: write
25+
concurrency:
26+
group: stlc-back-sync
27+
cancel-in-progress: true
28+
steps:
29+
- name: Check out staging
30+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Fetch production main
35+
run: |
36+
git remote add production "https://github.com/kernel/kernel-python-sdk.git"
37+
git -c "http.https://github.com/.extraheader=" fetch production main
38+
39+
- name: Check whether production has content staging lacks
40+
id: diff
41+
run: |
42+
MERGED=$(git merge-tree --write-tree origin/main production/main) || MERGED=conflict
43+
STAGING_TREE=$(git rev-parse 'origin/main^{tree}')
44+
if [ "$MERGED" = "$STAGING_TREE" ]; then
45+
echo "Staging already has production's content. Nothing to pull back."
46+
echo "behind=false" >> "$GITHUB_OUTPUT"
47+
else
48+
echo "behind=true" >> "$GITHUB_OUTPUT"
49+
fi
50+
51+
- name: Sync production to staging
52+
if: steps.diff.outputs.behind == 'true'
53+
run: |
54+
if ! git merge-base --is-ancestor origin/main production/main; then
55+
echo "::error title=Back-sync blocked::staging main is not an ancestor of production/main."
56+
exit 1
57+
fi
58+
git push origin production/main:refs/heads/main
59+
60+
notify-back-sync:
61+
if: >-
62+
github.repository == 'kernel/kernel-python-sdk' &&
63+
(github.event_name == 'release' || github.event_name == 'workflow_dispatch')
64+
runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }}
65+
permissions:
66+
contents: read
67+
steps:
68+
- name: Dispatch back-sync to staging
69+
env:
70+
DISPATCH_TOKEN: ${{ secrets.STAGING_DISPATCH_TOKEN }}
71+
REF_NAME: ${{ github.ref_name }}
72+
run: |
73+
set -euo pipefail
74+
if [ -z "${DISPATCH_TOKEN:-}" ]; then
75+
echo "::notice::STAGING_DISPATCH_TOKEN not configured; the scheduled back-sync remains active."
76+
exit 0
77+
fi
78+
payload=$(jq -n --arg ref "$REF_NAME" '{event_type:"prod-released",client_payload:{ref:$ref}}')
79+
curl --fail-with-body -sS -X POST -H "Authorization: Bearer $DISPATCH_TOKEN" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" "https://api.github.com/repos/kernel/kernel-python-sdk-staging/dispatches" -d "$payload"
80+
81+
seal-dispatch:
82+
if: github.repository == 'kernel/kernel-python-sdk-staging' && github.event_name == 'push'
83+
runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }}
84+
permissions:
85+
contents: read
86+
concurrency:
87+
group: seal-dispatch-${{ github.ref }}
88+
cancel-in-progress: false
89+
steps:
90+
- name: Dispatch tracking sync
91+
env:
92+
DISPATCH_TOKEN: ${{ secrets.CONFIG_DISPATCH_TOKEN }}
93+
HEAD_MSG: ${{ github.event.head_commit.message }}
94+
HEAD_AUTHOR_NAME: ${{ github.event.head_commit.author.name }}
95+
SHA: ${{ github.sha }}
96+
run: |
97+
set -euo pipefail
98+
if printf '%s' "$HEAD_MSG" | grep -q 'Stainless-Generated-From' || [ "$HEAD_AUTHOR_NAME" = "stlc-bot" ]; then
99+
echo "Generated commit; skipping tracking dispatch."
100+
exit 0
101+
fi
102+
if [ -z "${DISPATCH_TOKEN:-}" ]; then
103+
echo "::notice::CONFIG_DISPATCH_TOKEN not configured; the config repo's scheduled sync remains active."
104+
exit 0
105+
fi
106+
payload=$(jq -n --arg sha "$SHA" --arg repo "${{ github.repository }}" '{event_type:"seal-custom-code",client_payload:{target:"all",sha:$sha,repo:$repo}}')
107+
curl --fail-with-body -sS -X POST -H "Authorization: Bearer $DISPATCH_TOKEN" -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" "https://api.github.com/repos/kernel/kernel/dispatches" -d "$payload"

0 commit comments

Comments
 (0)