Repository navigation
133 lines (124 loc) · 5.83 KB
/
Copy pathprepare-python-release.yml
File metadata and controls
133 lines (124 loc) · 5.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Opens the PR that stamps today's CalVer date (e.g. 2026.8.1) onto each Python
# server that changed since its last version bump (#4472). Dispatched by a
# maintainer when preparing a release; the logic, and why Python stays on
# CalVer, is in `scripts/prepare-python-release.mjs`.
#
# It is the Python counterpart of the changesets "Version Packages" PR: the
# version changes in a reviewed PR on the develop branch, and nothing is
# published until a maintainer publishes a GitHub Release (`release.yml`).
#
# The PR targets the branch the workflow was dispatched on, which is `v2/main`
# in the normal flow. It is one of a release's preparation PRs, so it follows
# the same rules as any other PR here: its body opens with `Closes #N` for the
# milestone's release issue (the `issue` input), its branch is named for that
# issue, and it is labeled `v2`. The link is only a cross-reference on
# `v2/main`; the release issue stays open until the Release is published.
#
# It pushes the branch with the workflow token, and a push made with that
# token starts no workflow, so the PR would get no TypeScript or Python CI
# (#5110); a close and reopen fires only `pull_request`, which those workflows
# do not run on. So it dispatches both on the branch once the PR is open:
# `workflow_dispatch` is the one event the workflow token can start.
name: Prepare Python Release
on:
workflow_dispatch:
inputs:
issue:
description: "The release issue this PR belongs to (its number, e.g. 4930)"
required: true
type: string
jobs:
prepare:
timeout-minutes: 10
if: github.repository_owner == 'modelcontextprotocol'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
# To dispatch the TypeScript and Python workflows on the PR's branch.
actions: write
steps:
# The ref this was dispatched on becomes the PR's base, and every PR
# targets `v2/main`. A run from `main` would open a version PR straight
# against the release branch, around the milestone merge.
- name: Refuse a dispatch from any branch but v2/main
run: |
if [ "$GITHUB_REF" != "refs/heads/v2/main" ]; then
echo "::error::Dispatch this workflow on v2/main, not $GITHUB_REF."
exit 1
fi
# Full history: the script finds each package's last version bump with
# `git log`, and a shallow clone would make every package look new.
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24
# The script runs `uv lock` in each package it stamps.
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Stamp CalVer versions
run: node scripts/prepare-python-release.mjs > "$RUNNER_TEMP/stamped.txt"
- name: Check for changes
id: changes
run: |
if git diff --quiet; then
echo "No Python package needs a version stamp"
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Create pull request
if: steps.changes.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BASE: ${{ github.ref_name }}
ISSUE: ${{ inputs.issue }}
run: |
# The input is free text; only a bare issue number may reach the
# branch name and the PR body.
case "$ISSUE" in
'' | *[!0-9]*) echo "issue must be a number, got: '$ISSUE'" >&2; exit 1 ;;
esac
DATE=$(date -u +%Y.%-m.%-d)
BRANCH="v2/chore/$ISSUE-python-calver-$DATE"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -b "$BRANCH"
git add -u
git commit -m "chore: stamp Python CalVer versions for $DATE"
git push --force origin "$BRANCH"
{
echo "Closes #$ISSUE"
echo
echo "Stamps today's CalVer date onto the Python packages that changed since their last version bump:"
echo
sed 's/^/- /' "$RUNNER_TEMP/stamped.txt"
echo
echo "Generated by the **Prepare Python Release** workflow. Nothing is published until a maintainer publishes a GitHub Release."
echo
echo "> [!NOTE]"
echo "> A push made with the workflow token starts no CI, so the workflow dispatched the TypeScript and Python workflows on this branch. Their results show on this PR as the \`TypeScript (dispatched)\` and \`Python (dispatched)\` statuses. To run them again: \`gh workflow run python.yml --ref $BRANCH\` (and \`typescript.yml\`)."
} > "$RUNNER_TEMP/pr-body.md"
# A second run on the same day force-updates the branch, and may
# stamp a different set of packages; the open PR's body is rewritten
# to match what the branch now holds.
EXISTING=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number // empty')
if [ -n "$EXISTING" ]; then
gh pr edit "$EXISTING" --body-file "$RUNNER_TEMP/pr-body.md"
echo "PR #$EXISTING for $BRANCH was already open; its branch and body were updated"
else
gh pr create \
--base "$BASE" \
--head "$BRANCH" \
--label v2 \
--title "chore: stamp Python CalVer versions for $DATE" \
--body-file "$RUNNER_TEMP/pr-body.md"
fi
# The push above starts no workflow (see the header), so CI is
# dispatched on the branch explicitly, after a first run and a rerun
# alike.
for workflow in typescript.yml python.yml; do
gh workflow run "$workflow" --ref "$BRANCH"
done