mirror of
https://github.com/github/spec-kit.git
synced 2026-03-17 19:03:08 +00:00
* fix: split release process to sync pyproject.toml version with git tags (#1721) - Split release workflow into two: release-trigger.yml and release.yml - release-trigger.yml: Updates pyproject.toml, generates changelog from commits, creates tag - release.yml: Triggered by tag push, builds artifacts, creates GitHub release - Ensures git tags point to commits with correct version in pyproject.toml - Auto-generates changelog from commit messages since last tag - Supports manual version input or auto-increment patch version - Added simulate-release.sh for local testing without pushing - Added comprehensive RELEASE-PROCESS.md documentation - Updated pyproject.toml to v0.1.10 to sync with latest release This fixes the version mismatch issue where tags pointed to commits with outdated pyproject.toml versions, preventing confusion when installing from source. * Update .github/workflows/RELEASE-PROCESS.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update .github/workflows/scripts/simulate-release.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update .github/workflows/release.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update .github/workflows/release-trigger.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: harden release-trigger against shell injection and fix stale docs - Pass workflow_dispatch version input via env: instead of direct interpolation into shell script, preventing potential injection attacks - Validate version input against strict semver regex before use - Fix RELEASE-PROCESS.md Option 2 still referencing [Unreleased] section handling that no longer exists in the workflow --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
185 lines
5.7 KiB
Markdown
185 lines
5.7 KiB
Markdown
# Release Process
|
||
|
||
This document describes the automated release process for Spec Kit.
|
||
|
||
## Overview
|
||
|
||
The release process is split into two workflows to ensure version consistency:
|
||
|
||
1. **Release Trigger Workflow** (`release-trigger.yml`) - Manages versioning and triggers release
|
||
2. **Release Workflow** (`release.yml`) - Builds and publishes artifacts
|
||
|
||
This separation ensures that git tags always point to commits with the correct version in `pyproject.toml`.
|
||
|
||
## Before Creating a Release
|
||
|
||
**Important**: Write clear, descriptive commit messages!
|
||
|
||
### How CHANGELOG.md Works
|
||
|
||
The CHANGELOG is **automatically generated** from your git commit messages:
|
||
|
||
1. **During Development**: Write clear, descriptive commit messages:
|
||
```bash
|
||
git commit -m "feat: Add new authentication feature"
|
||
git commit -m "fix: Resolve timeout issue in API client (#123)"
|
||
git commit -m "docs: Update installation instructions"
|
||
```
|
||
|
||
2. **When Releasing**: The release trigger workflow automatically:
|
||
- Finds all commits since the last release tag
|
||
- Formats them as changelog entries
|
||
- Inserts them into CHANGELOG.md
|
||
- Commits the updated changelog before creating the new tag
|
||
|
||
### Commit Message Best Practices
|
||
|
||
Good commit messages make good changelogs:
|
||
- **Be descriptive**: "Add user authentication" not "Update files"
|
||
- **Reference issues/PRs**: Include `(#123)` for automated linking
|
||
- **Use conventional commits** (optional): `feat:`, `fix:`, `docs:`, `chore:`
|
||
- **Keep it concise**: One line is ideal, details go in commit body
|
||
|
||
**Example commits that become good changelog entries:**
|
||
```
|
||
fix: prepend YAML frontmatter to Cursor .mdc files (#1699)
|
||
feat: add generic agent support with customizable command directories (#1639)
|
||
docs: document dual-catalog system for extensions (#1689)
|
||
```
|
||
|
||
## Creating a Release
|
||
|
||
### Option 1: Auto-Increment (Recommended for patches)
|
||
|
||
1. Go to **Actions** → **Release Trigger**
|
||
2. Click **Run workflow**
|
||
3. Leave the version field **empty**
|
||
4. Click **Run workflow**
|
||
|
||
The workflow will:
|
||
- Auto-increment the patch version (e.g., `0.1.10` → `0.1.11`)
|
||
- Update `pyproject.toml`
|
||
- Update `CHANGELOG.md` by adding a new section for the release based on commits since the last tag
|
||
- Commit changes
|
||
- Create and push git tag
|
||
- Trigger the release workflow automatically
|
||
|
||
### Option 2: Manual Version (For major/minor bumps)
|
||
|
||
1. Go to **Actions** → **Release Trigger**
|
||
2. Click **Run workflow**
|
||
3. Enter the desired version (e.g., `0.2.0` or `v0.2.0`)
|
||
4. Click **Run workflow**
|
||
|
||
The workflow will:
|
||
- Use your specified version
|
||
- Update `pyproject.toml`
|
||
- Update `CHANGELOG.md` by adding a new section for the release based on commits since the last tag
|
||
- Commit changes
|
||
- Create and push git tag
|
||
- Trigger the release workflow automatically
|
||
|
||
## What Happens Next
|
||
|
||
Once the release trigger workflow completes:
|
||
|
||
1. The git tag is pushed to GitHub
|
||
2. The **Release Workflow** is automatically triggered
|
||
3. Release artifacts are built for all supported agents
|
||
4. A GitHub Release is created with all assets
|
||
5. Release notes are generated from PR titles
|
||
|
||
## Workflow Details
|
||
|
||
### Release Trigger Workflow
|
||
|
||
**File**: `.github/workflows/release-trigger.yml`
|
||
|
||
**Trigger**: Manual (`workflow_dispatch`)
|
||
|
||
**Permissions Required**: `contents: write`
|
||
|
||
**Steps**:
|
||
1. Checkout repository
|
||
2. Determine version (manual or auto-increment)
|
||
3. Check if tag already exists (prevents duplicates)
|
||
4. Update `pyproject.toml`
|
||
5. Update `CHANGELOG.md`
|
||
6. Commit changes
|
||
7. Create and push tag
|
||
|
||
### Release Workflow
|
||
|
||
**File**: `.github/workflows/release.yml`
|
||
|
||
**Trigger**: Tag push (`v*`)
|
||
|
||
**Permissions Required**: `contents: write`
|
||
|
||
**Steps**:
|
||
1. Checkout repository at tag
|
||
2. Extract version from tag name
|
||
3. Check if release already exists
|
||
4. Build release package variants (all agents × shell/powershell)
|
||
5. Generate release notes from commits
|
||
6. Create GitHub Release with all assets
|
||
|
||
## Version Constraints
|
||
|
||
- Tags must follow format: `v{MAJOR}.{MINOR}.{PATCH}`
|
||
- Example valid versions: `v0.1.11`, `v0.2.0`, `v1.0.0`
|
||
- Auto-increment only bumps patch version
|
||
- Cannot create duplicate tags (workflow will fail)
|
||
|
||
## Benefits of This Approach
|
||
|
||
✅ **Version Consistency**: Git tags point to commits with matching `pyproject.toml` version
|
||
|
||
✅ **Single Source of Truth**: Version set once, used everywhere
|
||
|
||
✅ **Prevents Drift**: No more manual version synchronization needed
|
||
|
||
✅ **Clean Separation**: Versioning logic separate from artifact building
|
||
|
||
✅ **Flexibility**: Supports both auto-increment and manual versioning
|
||
|
||
## Troubleshooting
|
||
|
||
### No Commits Since Last Release
|
||
|
||
If you run the release trigger workflow when there are no new commits since the last tag:
|
||
- The workflow will still succeed
|
||
- The CHANGELOG will show "- Initial release" if it's the first release
|
||
- Or it will be empty if there are no commits
|
||
- Consider adding meaningful commits before releasing
|
||
|
||
**Best Practice**: Use descriptive commit messages - they become your changelog!
|
||
|
||
### Tag Already Exists
|
||
|
||
If you see "Error: Tag vX.Y.Z already exists!", you need to:
|
||
- Choose a different version number, or
|
||
- Delete the existing tag if it was created in error
|
||
|
||
### Release Workflow Didn't Trigger
|
||
|
||
Check that:
|
||
- The release trigger workflow completed successfully
|
||
- The tag was pushed (check repository tags)
|
||
- The release workflow is enabled in Actions settings
|
||
|
||
### Version Mismatch
|
||
|
||
If `pyproject.toml` doesn't match the latest tag:
|
||
- Run the release trigger workflow to sync versions
|
||
- Or manually update `pyproject.toml` and push changes before running the release trigger
|
||
|
||
## Legacy Behavior (Pre-v0.1.10)
|
||
|
||
Before this change, the release workflow:
|
||
- Created tags automatically on main branch pushes
|
||
- Updated `pyproject.toml` AFTER creating the tag
|
||
- Resulted in tags pointing to commits with outdated versions
|
||
|
||
This has been fixed in v0.1.10+.
|