name: release description: Prepare a Traefik release (patch, minor RC1, minor RC2+, major RC) — generates changelog, bumps versions, commits, pushes, opens PR user-invocable: true
Release skill
Invocation: /release <new-tag>
Examples:
/release v2.11.51— patch release/release v3.8.0-rc.1— minor RC1 (from master)/release v3.8.0-rc.2— minor RC2+ (from v3.8 branch)/release v4.0.0-rc.1— major RC1 (from master)
Step 1 — Parse tag and detect release type
From NEW_TAG, extract:
MAJOR,MINOR,PATCH,RC_NUM(0 if not an RC)IS_RC: true if tag contains-rc.IS_RC1: true ifRC_NUM == 1
Release types and their properties:
| Type | Example | Branch | Prev tag detection |
|------|---------|--------|-------------------|
| Patch | v2.11.51 | v{major}.{minor} | last v{major}.{minor}.* tag |
| RC1 | v3.8.0-rc.1 | master | last v{major}.{minor-1}.0-rc.* or ea.* tag |
| RC2+ | v3.8.0-rc.2 | v{major}.{minor} | v{major}.{minor}.0-rc.{RC_NUM-1} |
Set BRANCH and RELEASE_BRANCH=prepare-release-${NEW_TAG}.
Detect PREV_TAG:
- Patch:
git tag --sort=-version:refname | grep "^v${MAJOR}\.${MINOR}\." | grep -v "^${NEW_TAG}$" | grep -v "\-rc\." | head -1 - RC1:
git tag --sort=-version:refname | grep -E "^v${MAJOR}\.$(( MINOR - 1 ))\.0-(rc|ea)\." | head -1 - RC2+: construct directly as
v${MAJOR}.${MINOR}.0-rc.$(( RC_NUM - 1 ))
If PREV_TAG is empty: ask the user "Could not auto-detect previous tag. What is the previous tag?"
Step 2 — Pre-flight checks (fail fast, clear messages)
Run these checks in order:
- Current branch:
git branch --show-currentmust equalBRANCH. If not:Error: must be on branch ${BRANCH}, currently on <current>. - Branch does not exist:
git branch --list ${RELEASE_BRANCH}must be empty. If not:Error: branch ${RELEASE_BRANCH} already exists. - Up to date: run
git fetch upstreamthengit rev-list HEAD..upstream/${BRANCH} --count. If count > 0:Error: branch is N commits behind upstream/${BRANCH}. Run: git pull upstream ${BRANCH} - CODENAME: read
.github/workflows/release.yaml, extract value afterCODENAME:. If missing: ask "What is the current release codename? (check .github/workflows/release.yaml)" - GITHUB_TOKEN: use
$GITHUB_TOKENif set, else rungh auth token. Export for use in git-cliff. - Fork remote: run
git remote -vandgh api user --jq .loginto find the remote whose push URL contains the GitHub username. If ambiguous: ask "Which remote is your fork?"
Show summary and ask "Proceed? (y to continue)":
Release type: <Patch | Minor RC1 | Minor RC2+ | Major RC1>
New tag: ${NEW_TAG}
Prev tag: ${PREV_TAG}
Branch: ${BRANCH} → ${RELEASE_BRANCH}
Codename: ${CODENAME}
Step 3 — Create release branch
git checkout -b ${RELEASE_BRANCH}
Step 4 — [RC1 only] Bump version in documentation
Detect old minor version: OLD_MINOR=v${MAJOR}.$(( MINOR - 1 )), NEW_MINOR=v${MAJOR}.${MINOR}.
Replace all occurrences of ${OLD_MINOR} with ${NEW_MINOR} in all git-tracked files under docs/, excluding docs/dist/:
git ls-files docs/ | grep -v '^docs/dist/' | xargs sed -i '' "s/${OLD_MINOR}/${NEW_MINOR}/g"
Also update cmd/traefik/traefik.go (contains a doc URL with the version).
Show the list of changed files. Pause 1a — ask: "Review the version bump changes in your editor. (y to commit)"
Commit:
git add $(git ls-files docs/ | grep -v '^docs/dist/') cmd/traefik/traefik.go
git commit -m "Bump documentation references from ${OLD_MINOR} to ${NEW_MINOR}"
Step 5 — [RC1 only] Update CODENAME
Ask the user: "What is the new codename for ${NEW_MINOR}?"
Update the CODENAME: line in .github/workflows/release.yaml:
- Find the line matching
CODENAME:and replace its value with the new codename.
Pause 1b — ask: "CODENAME updated to <new_codename> in release.yaml. (y to commit)"
git add .github/workflows/release.yaml
git commit -m "Update release codename to <new_codename>"
Step 6 — Generate changelog
GITHUB_TOKEN=${GITHUB_TOKEN} git cliff --config script/release/cliff.toml --tag ${NEW_TAG} ${PREV_TAG}..${BRANCH}
Step 7 — Process changelog output
Apply to the raw git-cliff output:
- Sort entries within each section alphabetically:
- Entries with
**[area]**tag: sort by the tag text inside**[...]** - Entries without a tag: sort by full line text, place after tagged entries
- Entries with
- Remove blank lines between entries within a section (blank lines between sections are preserved)
Prepend the processed result to the top of CHANGELOG.md.
Show the added lines (first ~30 lines of the new block).
Pause 2 — ask: "CHANGELOG.md updated. Review in your editor, adjust if needed. (y to commit)"
git add CHANGELOG.md
git commit -m "Prepare release ${NEW_TAG}"
Step 8 — Push
Pause 3 — ask: "Ready to push branch ${RELEASE_BRANCH} to ${FORK_REMOTE}. (y to push)"
git push ${FORK_REMOTE} ${RELEASE_BRANCH}
Step 9 — Open pull request
Pause 4 — ask: "Ready to open PR against traefik/traefik:${BRANCH}. (y to open PR)"
gh pr create \
--repo traefik/traefik \
--base ${BRANCH} \
--head ${GITHUB_USER}:${RELEASE_BRANCH} \
--title "Prepare release ${NEW_TAG}" \
--label "area/documentation" \
--label "size/S" \
--body "$(cat <<'PRBODY'
### What does this PR do?
Prepare release ${NEW_TAG}.
aka `${CODENAME}`
### Motivation
To create a new release.
### More
- [ ] Added/updated tests
- [x] Added/updated documentation
PRBODY
)"
Print the PR URL.
Reference: script/release/README.md
For manual procedure when this skill is unavailable, see script/release/README.md.
Expert Next.js App Router
Developpement
Un skill qui transforme Claude en expert Next.js App Router.
Générateur de README
Developpement
Crée des README.md professionnels et complets pour vos projets.
Rédacteur de Documentation API
Developpement
Génère de la documentation API complète au format OpenAPI/Swagger.