-
Notifications
You must be signed in to change notification settings - Fork 0
chore: add release automation and /release skill #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # Release | ||
|
|
||
| Prepare a release PR for initium. This command handles version bumping, changelog updates, and PR creation. The release is published automatically when the PR merges (CI detects the version bump and creates the tag, which triggers the release workflow). | ||
|
|
||
| ## Determine the next version number | ||
|
|
||
| Follow semantic versioning (MAJOR.MINOR.PATCH): | ||
|
|
||
| 1. Read `CHANGELOG.md` under `## [Unreleased]` to see what has changed since the last release. | ||
| 2. Read recent commits since the last tag: `git log $(git describe --tags --abbrev=0)..HEAD --oneline` | ||
| 3. Determine the version bump: | ||
| - **PATCH** (x.y.Z): Only bug fixes, documentation, or internal changes with no user-facing behavior change. | ||
| - **MINOR** (x.Y.0): New features, new CLI flags, new configuration options, or backward-compatible enhancements. | ||
| - **MAJOR** (X.0.0): Breaking changes — removed features, changed defaults, incompatible schema/config changes, or renamed CLI flags. | ||
| 4. Read the current version from `Cargo.toml` and compute the next version. | ||
|
|
||
| ## Confirmation phase | ||
|
|
||
| Before making any changes, present to the user: | ||
| - The **current version** and the **proposed next version** with reasoning. | ||
| - A **summary of changes** that will go into the release (from Unreleased changelog + commit log). | ||
| - Ask: "Proceed with version X.Y.Z?" and wait for confirmation. | ||
| - If the user suggests a different version, use that instead. | ||
|
|
||
| ## Execute the release | ||
|
|
||
| Once confirmed: | ||
|
|
||
| 1. Fetch origin and create a branch: `release/vX.Y.Z` from `origin/main`. | ||
| 2. Bump version in `Cargo.toml` (the `version = "..."` field under `[package]`). | ||
| 3. Run `cargo check` to update `Cargo.lock`. | ||
| 4. Update `CHANGELOG.md`: | ||
| - Move everything under `## [Unreleased]` into a new `## [X.Y.Z] - YYYY-MM-DD` section (use today's date). | ||
| - Leave `## [Unreleased]` empty (with just the heading). | ||
| 5. Run `cargo test` to verify nothing is broken. | ||
| 6. Run `cargo clippy -- -D warnings` and `cargo fmt -- --check`. | ||
| 7. Commit: `release: vX.Y.Z` | ||
| 8. Push the branch and create a PR with title `release: vX.Y.Z`. | ||
| 9. The PR body should include the changelog entries for this version. | ||
|
|
||
| When the PR merges, the auto-tag workflow detects the version bump in `Cargo.toml` and creates the `vX.Y.Z` tag, which triggers the release workflow (Docker build + crates.io publish). | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,40 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Auto Tag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| push: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: [main] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| paths: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Cargo.toml | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fetch-depth: 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Check for version bump | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CURRENT=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PREVIOUS=$(git show HEAD~1:Cargo.toml | grep '^version' | head -1 | sed 's/.*"\(.*\)"/\1/') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+20
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fetch-depth: 2 | |
| - name: Check for version bump | |
| id: version | |
| run: | | |
| CURRENT=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') | |
| PREVIOUS=$(git show HEAD~1:Cargo.toml | grep '^version' | head -1 | sed 's/.*"\(.*\)"/\1/') | |
| fetch-depth: 0 | |
| - name: Check for version bump | |
| id: version | |
| run: | | |
| CURRENT=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') | |
| PREVIOUS=$(git show ${{ github.event.before }}:Cargo.toml | grep '^version' | head -1 | sed 's/.*"\(.*\)"/\1/') |
Copilot
AI
Mar 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tag existence check uses git rev-parse "$TAG", which only checks locally fetched tags. In a shallow checkout this may not include existing remote tags, causing git push to fail when the tag already exists on origin. Prefer checking the remote (git ls-remote --tags origin "refs/tags/$TAG") or fetching tags before the check, and handle a push rejection gracefully.
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists, skipping" | |
| exit 0 | |
| fi | |
| git tag "$TAG" | |
| git push origin "$TAG" | |
| # Check if the tag already exists on the remote | |
| if git ls-remote --tags origin "refs/tags/$TAG" | grep -q .; then | |
| echo "Tag $TAG already exists on origin, skipping" | |
| exit 0 | |
| fi | |
| # Also check if the tag exists locally | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists locally, skipping" | |
| exit 0 | |
| fi | |
| git tag "$TAG" | |
| # Push the tag; if it fails, re-check the remote to handle concurrent creation | |
| if ! git push origin "$TAG"; then | |
| if git ls-remote --tags origin "refs/tags/$TAG" | grep -q .; then | |
| echo "Tag $TAG was created concurrently on origin, skipping" | |
| exit 0 | |
| fi | |
| echo "Failed to push tag $TAG" | |
| exit 1 | |
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This step says
cargo checkwill updateCargo.lock, butcargo checktypically won't change the lockfile unless dependency resolution changes; bumping the package version alone won't do that. If the goal is just validation, reword to reflect that; if the goal is to ensure a lockfile exists/updates, use the appropriate Cargo command (e.g., generating/updating the lockfile) instead.