Skip to content

Commit 019c2dc

Browse files
Merge remote-tracking branch 'origin/main' into stlc/promote-next
2 parents 677f579 + 4cf851e commit 019c2dc

226 files changed

Lines changed: 33795 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ARG VARIANT="3.9"
2+
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
3+
4+
USER vscode
5+
6+
RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.44.0" RYE_INSTALL_OPTION="--yes" bash
7+
ENV PATH=/home/vscode/.rye/shims:$PATH
8+
9+
RUN echo "[[ -d .venv ]] && source .venv/bin/activate || export PATH=\$PATH" >> /home/vscode/.bashrc

.devcontainer/devcontainer.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
2+
// README at: https://github.com/devcontainers/templates/tree/main/src/debian
3+
{
4+
"name": "Debian",
5+
"build": {
6+
"dockerfile": "Dockerfile",
7+
"context": ".."
8+
},
9+
10+
"postStartCommand": "rye sync --all-features",
11+
12+
"customizations": {
13+
"vscode": {
14+
"extensions": [
15+
"ms-python.python"
16+
],
17+
"settings": {
18+
"terminal.integrated.shell.linux": "/bin/bash",
19+
"python.pythonPath": ".venv/bin/python",
20+
"python.defaultInterpreterPath": ".venv/bin/python",
21+
"python.typeChecking": "basic",
22+
"terminal.integrated.env.linux": {
23+
"PATH": "/home/vscode/.rye/shims:${env:PATH}"
24+
}
25+
}
26+
}
27+
},
28+
"features": {
29+
"ghcr.io/devcontainers/features/node:1": {}
30+
}
31+
32+
// Features to add to the dev container. More info: https://containers.dev/features.
33+
// "features": {},
34+
35+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
36+
// "forwardPorts": [],
37+
38+
// Configure tool-specific properties.
39+
// "customizations": {},
40+
41+
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
42+
// "remoteUser": "root"
43+
}

.github/workflows/ci.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: CI
2+
on:
3+
push:
4+
branches:
5+
- '**'
6+
- '!integrated/**'
7+
- '!stl-preview-head/**'
8+
- '!stl-preview-base/**'
9+
- '!generated'
10+
- '!codegen/**'
11+
- 'codegen/stl/**'
12+
pull_request:
13+
branches-ignore:
14+
- 'stl-preview-head/**'
15+
- 'stl-preview-base/**'
16+
17+
jobs:
18+
lint:
19+
timeout-minutes: 10
20+
name: lint
21+
runs-on: ubuntu-latest
22+
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
23+
steps:
24+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25+
26+
- name: Install Rye
27+
run: |
28+
curl -sSf https://rye.astral.sh/get | bash
29+
echo "$HOME/.rye/shims" >> $GITHUB_PATH
30+
env:
31+
RYE_VERSION: '0.44.0'
32+
RYE_INSTALL_OPTION: '--yes'
33+
34+
- name: Install dependencies
35+
run: rye sync --all-features
36+
37+
- name: Run lints
38+
run: ./scripts/lint
39+
40+
build:
41+
if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
42+
timeout-minutes: 10
43+
name: build
44+
permissions:
45+
contents: read
46+
id-token: write
47+
runs-on: ubuntu-latest
48+
steps:
49+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
50+
51+
- name: Install Rye
52+
run: |
53+
curl -sSf https://rye.astral.sh/get | bash
54+
echo "$HOME/.rye/shims" >> $GITHUB_PATH
55+
env:
56+
RYE_VERSION: '0.44.0'
57+
RYE_INSTALL_OPTION: '--yes'
58+
59+
- name: Install dependencies
60+
run: rye sync --all-features
61+
62+
- name: Run build
63+
run: rye build

.github/workflows/publish-pypi.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# This workflow is triggered when a GitHub release is created.
2+
# It can also be run manually to re-publish to PyPI in case it failed for some reason.
3+
# You can run this workflow by navigating to https://www.github.com/kernel/hypeman-python/actions/workflows/publish-pypi.yml
4+
name: Publish PyPI
5+
on:
6+
workflow_dispatch:
7+
8+
release:
9+
types: [published]
10+
11+
jobs:
12+
publish:
13+
name: publish
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
19+
- name: Install Rye
20+
run: |
21+
curl -sSf https://rye.astral.sh/get | bash
22+
echo "$HOME/.rye/shims" >> $GITHUB_PATH
23+
env:
24+
RYE_VERSION: '0.44.0'
25+
RYE_INSTALL_OPTION: '--yes'
26+
27+
- name: Publish to PyPI
28+
run: |
29+
bash ./bin/publish-pypi
30+
env:
31+
PYPI_TOKEN: ${{ secrets.HYPEMAN_PYPI_TOKEN || secrets.PYPI_TOKEN }}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Release Doctor
2+
on:
3+
pull_request:
4+
branches:
5+
- main
6+
workflow_dispatch:
7+
8+
jobs:
9+
release_doctor:
10+
name: release doctor
11+
runs-on: ubuntu-latest
12+
if: github.repository == 'kernel/hypeman-python' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')
13+
14+
steps:
15+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
16+
17+
- name: Check release environment
18+
run: |
19+
bash ./bin/check-release-environment
20+
env:
21+
RELEASE_PLEASE_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }}
22+
PYPI_TOKEN: ${{ secrets.HYPEMAN_PYPI_TOKEN || secrets.PYPI_TOKEN }}

.github/workflows/stlc-promote.yml

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: Promote SDK changes
2+
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`.
7+
on:
8+
push:
9+
branches: [main]
10+
workflow_dispatch: {}
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
promote:
17+
if: github.repository == 'kernel/hypeman-python-staging'
18+
runs-on: ${{ vars.STLC_RUNNER || 'ubuntu-latest' }}
19+
concurrency:
20+
group: stlc-promote
21+
cancel-in-progress: true
22+
steps:
23+
- name: Check out staging
24+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
25+
with:
26+
fetch-depth: 0
27+
persist-credentials: false
28+
29+
- name: Mint production token
30+
id: production-token
31+
uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1
32+
with:
33+
app-id: ${{ secrets.ADMIN_APP_ID }}
34+
private-key: ${{ secrets.ADMIN_APP_PRIVATE_KEY }}
35+
owner: kernel
36+
repositories: hypeman-python
37+
permission-contents: write
38+
permission-pull-requests: write
39+
permission-workflows: write
40+
41+
- name: Fetch production branches
42+
id: production
43+
env:
44+
GH_TOKEN: ${{ steps.production-token.outputs.token }}
45+
PRODUCTION_REPO: kernel/hypeman-python
46+
run: |
47+
set -euo pipefail
48+
git remote add production \
49+
"https://x-access-token:${GH_TOKEN}@github.com/${PRODUCTION_REPO}.git"
50+
if git ls-remote --exit-code --heads production main >/dev/null 2>&1; then
51+
git fetch production main
52+
echo "has_main=true" >> "$GITHUB_OUTPUT"
53+
else
54+
echo "has_main=false" >> "$GITHUB_OUTPUT"
55+
fi
56+
if git ls-remote --exit-code --heads production next >/dev/null 2>&1; then
57+
git fetch production next
58+
echo "has_next=true" >> "$GITHUB_OUTPUT"
59+
else
60+
echo "has_next=false" >> "$GITHUB_OUTPUT"
61+
fi
62+
63+
- name: Prepare the next release branch
64+
env:
65+
APP_SLUG: ${{ steps.production-token.outputs.app-slug }}
66+
GH_TOKEN: ${{ steps.production-token.outputs.token }}
67+
HAS_MAIN: ${{ steps.production.outputs.has_main }}
68+
HAS_NEXT: ${{ steps.production.outputs.has_next }}
69+
PRODUCTION_REPO: kernel/hypeman-python
70+
run: |
71+
set -euo pipefail
72+
bot_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)
73+
git config user.name "${APP_SLUG}[bot]"
74+
git config user.email "${bot_id}+${APP_SLUG}[bot]@users.noreply.github.com"
75+
76+
open_conflict_pr() {
77+
source_ref=$1
78+
source_name=$2
79+
advance_next=$3
80+
conflict_branch=stlc/promotion-conflict
81+
82+
git merge --abort
83+
existing=$(gh pr list --repo "$PRODUCTION_REPO" --base next \
84+
--head "$conflict_branch" --state open --json url --jq '.[0].url // ""')
85+
if [ -n "$existing" ]; then
86+
echo "::error title=SDK promotion blocked::Resolve the existing recovery PR: $existing"
87+
exit 1
88+
fi
89+
90+
if [ "$advance_next" = "true" ]; then
91+
git push production HEAD:refs/heads/next
92+
fi
93+
git push production "$source_ref:refs/heads/$conflict_branch" --force
94+
95+
body=$(mktemp)
96+
printf '%s\n' \
97+
'## SDK promotion conflict' \
98+
'' \
99+
"The automated promotion could not merge $source_name into the pending next release." \
100+
'' \
101+
'Resolve the conflicts on this branch, validate the SDK, mark this PR ready, and merge it with a merge commit.' \
102+
'' \
103+
'After merging, rerun the staging Promote SDK changes workflow to include any newer generated changes.' \
104+
> "$body"
105+
recovery_url=$(gh pr create --repo "$PRODUCTION_REPO" --draft \
106+
--base next --head "$conflict_branch" \
107+
--title 'chore: resolve SDK promotion conflict' --body-file "$body")
108+
echo "::error title=SDK promotion conflict::Resolve the recovery PR: $recovery_url"
109+
exit 1
110+
}
111+
112+
if [ "$HAS_MAIN" != "true" ]; then
113+
# The Python production repository started empty. Seed a minimal
114+
# default branch so release-please can open the first next -> main
115+
# release PR while preserving staging as a parent of that release.
116+
git checkout --orphan stlc/bootstrap-main
117+
git rm -rf .
118+
git checkout origin/main -- \
119+
.github/workflows/release-please.yml \
120+
.release-please-manifest.json \
121+
release-please-config.json
122+
git commit -m 'chore: initialize SDK release history'
123+
git push production HEAD:refs/heads/main
124+
git fetch production main
125+
fi
126+
127+
if [ "$HAS_NEXT" = "true" ]; then
128+
git checkout -B stlc/promote-next production/next
129+
else
130+
git checkout -B stlc/promote-next production/main
131+
fi
132+
133+
if ! git merge-base --is-ancestor production/main HEAD; then
134+
if ! git merge --no-edit production/main; then
135+
open_conflict_pr production/main 'production main' false
136+
fi
137+
fi
138+
if ! git merge-base --is-ancestor origin/main HEAD; then
139+
merge_args=(--no-edit)
140+
if ! git merge-base production/main origin/main >/dev/null 2>&1; then
141+
merge_args+=(--allow-unrelated-histories)
142+
fi
143+
if ! git merge "${merge_args[@]}" origin/main; then
144+
open_conflict_pr origin/main 'validated staging changes' true
145+
fi
146+
fi
147+
148+
if [ "$HAS_NEXT" = "true" ]; then
149+
git merge-base --is-ancestor production/next HEAD
150+
fi
151+
152+
- name: Update the pending release
153+
env:
154+
GH_TOKEN: ${{ steps.production-token.outputs.token }}
155+
run: |
156+
set -euo pipefail
157+
git push production HEAD:refs/heads/next
158+
echo "Updated production next; the versioned release PR will be opened or refreshed."

0 commit comments

Comments
 (0)