From 2d3c5a184b6b1c448f77c594792897e79846706b Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Tue, 16 Jun 2026 16:12:52 +1000 Subject: [PATCH] Add Tracks release skill The release workflow here is specific to this Swift Package: release branches carry the version change, and GitHub Releases create the release tags consumed by Swift Package Manager. --- Generated with the help of Codex, https://openai.com/codex Co-Authored-By: Codex GPT-5 --- .claude/skills/release-tracks/SKILL.md | 92 +++++++++++++++++++ .../skills/release-tracks/agents/openai.yaml | 4 + AGENTS.md | 6 +- 3 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 .claude/skills/release-tracks/SKILL.md create mode 100644 .claude/skills/release-tracks/agents/openai.yaml diff --git a/.claude/skills/release-tracks/SKILL.md b/.claude/skills/release-tracks/SKILL.md new file mode 100644 index 00000000..30062a7c --- /dev/null +++ b/.claude/skills/release-tracks/SKILL.md @@ -0,0 +1,92 @@ +--- +name: release-tracks +description: Prepare, verify, and publish releases for Automattic Tracks Apple, the Automattic-Tracks-iOS Swift Package. Use when asked to cut a Tracks release, prepare a release branch or release PR, update the Tracks changelog for a version, create the GitHub Release that creates the release tag, or verify the Tracks release process. +--- + +# Release Tracks + +Use this only for `Automattic/Automattic-Tracks-iOS`. +Read `AGENTS.md`, `CHANGELOG.md`, `.buildkite/pipeline.yml`, and current GitHub state before acting. +If those conflict with this skill, follow the repository files and current GitHub state. + +Tracks is distributed as a Swift Package. +There is no separate publish command, `fastlane` release lane, podspec, or version file in `Package.swift`. +The release is the GitHub Release and the Git tag it creates. + +## Release Contract + +- Default branch: `trunk`. +- Release branch: `release/`. +- Version source: `CHANGELOG.md`. +- Tag format: bare semantic version, for example `4.3.0`; do not prefix with `v`. +- Release tag target: the merged release commit on `trunk`, not the pre-merge release branch commit. +- Tag creation: create a GitHub Release and let GitHub create the tag. + Do not push the tag manually unless the maintainer explicitly changes the release process. + +## Workflow + +1. Confirm the release target. + Identify the requested version and whether it is major, minor, or patch. + Check the current latest tag with `git tag --sort=-v:refname | head` after fetching tags. + Check open PRs against `trunk` with `gh pr list --base trunk --state open --json number,title,url,isDraft,reviewDecision,mergeStateStatus,statusCheckRollup`. + Call out non-draft PRs that look ready to merge before the release, especially approved PRs with passing checks, and ask whether the release should wait for them. + +2. Create the release branch from current `origin/trunk`. + Use `release/`, for example `release/4.3.0`. + Do not use an author-prefixed branch for the actual release branch. + +3. Update `CHANGELOG.md`. + Follow the instructions in the changelog comment. + Remove empty sections for the release, rename `## Unreleased` to `## `, and add a fresh `## Unreleased` section above it with the existing template. + Keep release notes factual and based on already-merged changes. + +4. Verify locally before opening the release PR. + Use the repository wrappers: + + ```bash + bundle exec fastlane ios test clean:true + bundle exec fastlane mac test clean:true + make lint + ``` + + If the system `bundle` cannot find the locked Bundler, run Bundler through the Ruby version from `.ruby-version`. + With the current `.ruby-version`, `mise exec ruby@3.2.2 -- ruby -S bundle install` bootstraps the repo and installs gems into `./vendor/bundle`. + Keep the `mise` Ruby version aligned with `.ruby-version` if it changes. + Do not change `Gemfile.lock` or use the global SwiftLint binary to work around local environment issues. + +5. Open the release PR. + Title it `Release `. + The PR only needs the changelog change unless the repository gained an explicit version file. + Do not update `Package.swift` for the release version. + Monitor Buildkite and GitHub checks until they pass. + +6. After the PR merges, create the GitHub Release. + Use the changelog section for that version as the release notes. + Set the tag and release title to the bare version, for example `4.3.0`. + Target `trunk` so GitHub creates the tag on the merge commit. + `gh release create --target trunk --title --notes-file ` is acceptable when the notes file contains only the released changelog section. + +7. Verify the published release. + Fetch tags and confirm the tag points at `origin/trunk`: + + ```bash + git fetch origin --tags + git rev-parse + git rev-parse origin/trunk + ``` + + Confirm the GitHub Release exists and shows the intended notes. + +## CI Notes + +At the time this skill was written, `.buildkite/pipeline.yml` contains iOS tests, macOS tests, and SwiftLint only. +It does not define tag-specific release or publish behavior. +Re-check the file before each release; if tag-specific Buildkite behavior appears later, follow the repository config before creating the GitHub Release. + +## Guardrails + +- Do not create a tag before the release PR is merged. +- Do not tag the release branch commit after the PR has merged. +- Do not invent release notes from commit titles when `CHANGELOG.md` already has the release notes. +- Do not skip ready-PR discovery before cutting the release branch. +- Do not run SwiftLint with a global `swiftlint`; use `make lint`. diff --git a/.claude/skills/release-tracks/agents/openai.yaml b/.claude/skills/release-tracks/agents/openai.yaml new file mode 100644 index 00000000..b552ef80 --- /dev/null +++ b/.claude/skills/release-tracks/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Tracks Release" + short_description: "Release Tracks Swift Package versions" + default_prompt: "Use $release-tracks to prepare the next Tracks release." diff --git a/AGENTS.md b/AGENTS.md index 5ed26717..7b5b288a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -83,6 +83,10 @@ Do not use the global `swiftlint` binary — it may be a different version. - PRs should update `CHANGELOG.md` when warranted. See PR template @.github/PULL_REQUEST.md. See PR template @.github/PULL_REQUEST_TEMPLATE.md . - `CHANGELOG.md` follows [Keep a Changelog](https://keepachangelog.com/). +### Releases + +Use @.claude/skills/release-tracks/SKILL.md when preparing or publishing a Tracks release. + ### Tests Two test targets in `Package.swift`: @@ -123,7 +127,7 @@ In the long run, we wish to remove Core Data in favor of a leaner persistence la ## Common pitfalls -- **Fastlane test scheme**: tests run via the `TracksDemo` / `TracksDemo Mac` Xcode schemes, not the SPM package directly. +- **fastlane test scheme**: tests run via the `TracksDemo` / `TracksDemo Mac` Xcode schemes, not the SPM package directly. The demo project at `TracksDemo/TracksDemo.xcodeproj` must stay buildable. - **Spaces in directory names**: several source directories have spaces (`Event Logging`, `Event Logging (Swift)`, `Encrypted Logs`, `Remote Logging`). Be careful with shell commands and path handling.