name: Release Trigger on: workflow_dispatch: inputs: version: description: 'Version to release (e.g., 0.1.11). Leave empty to auto-increment patch version.' required: false type: string jobs: bump-version: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - name: Checkout repository uses: actions/checkout@v6 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - name: Configure Git run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - name: Determine version id: version env: INPUT_VERSION: ${{ github.event.inputs.version }} run: | if [[ -n "$INPUT_VERSION" ]]; then # Manual version specified - strip optional v prefix VERSION="${INPUT_VERSION#v}" # Validate strict semver format to prevent injection if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "Error: Invalid version format '$VERSION'. Must be X.Y.Z (e.g. 1.2.3 or v1.2.3)" exit 1 fi echo "version=$VERSION" >> $GITHUB_OUTPUT echo "tag=v$VERSION" >> $GITHUB_OUTPUT echo "Using manual version: $VERSION" else # Auto-increment patch version LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") echo "Latest tag: $LATEST_TAG" # Extract version number and increment VERSION=$(echo $LATEST_TAG | sed 's/v//') IFS='.' read -ra VERSION_PARTS <<< "$VERSION" MAJOR=${VERSION_PARTS[0]:-0} MINOR=${VERSION_PARTS[1]:-0} PATCH=${VERSION_PARTS[2]:-0} # Increment patch version PATCH=$((PATCH + 1)) NEW_VERSION="$MAJOR.$MINOR.$PATCH" echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT echo "tag=v$NEW_VERSION" >> $GITHUB_OUTPUT echo "Auto-incremented version: $NEW_VERSION" fi - name: Check if tag already exists run: | if git rev-parse "${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then echo "Error: Tag ${{ steps.version.outputs.tag }} already exists!" exit 1 fi - name: Create release branch run: | BRANCH="chore/release-${{ steps.version.outputs.tag }}" git checkout -b "$BRANCH" echo "branch=$BRANCH" >> $GITHUB_ENV - name: Update pyproject.toml run: | sed -i "s/version = \".*\"/version = \"${{ steps.version.outputs.version }}\"/" pyproject.toml echo "Updated pyproject.toml to version ${{ steps.version.outputs.version }}" - name: Update CHANGELOG.md run: | if [ -f "CHANGELOG.md" ]; then DATE=$(date +%Y-%m-%d) # Get the previous tag to compare commits PREVIOUS_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") echo "Generating changelog from commits..." if [[ -n "$PREVIOUS_TAG" ]]; then echo "Changes since $PREVIOUS_TAG" COMMITS=$(git log --oneline "$PREVIOUS_TAG"..HEAD --no-merges --pretty=format:"- %s" 2>/dev/null || echo "- Initial release") else echo "No previous tag found - this is the first release" COMMITS="- Initial release" fi # Create new changelog entry { head -n 8 CHANGELOG.md echo "" echo "## [${{ steps.version.outputs.version }}] - $DATE" echo "" echo "### Changed" echo "" echo "$COMMITS" echo "" tail -n +9 CHANGELOG.md } > CHANGELOG.md.tmp mv CHANGELOG.md.tmp CHANGELOG.md echo "✅ Updated CHANGELOG.md with commits since $PREVIOUS_TAG" else echo "No CHANGELOG.md found" fi - name: Commit version bump run: | if [ -f "CHANGELOG.md" ]; then git add pyproject.toml CHANGELOG.md else git add pyproject.toml fi if git diff --cached --quiet; then echo "No changes to commit" else git commit -m "chore: bump version to ${{ steps.version.outputs.version }}" echo "Changes committed" fi - name: Create and push tag run: | git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}" git push origin "${{ env.branch }}" git push origin "${{ steps.version.outputs.tag }}" echo "Branch ${{ env.branch }} and tag ${{ steps.version.outputs.tag }} pushed" - name: Open pull request env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh pr create \ --base main \ --head "${{ env.branch }}" \ --title "chore: bump version to ${{ steps.version.outputs.version }}" \ --body "Automated version bump to ${{ steps.version.outputs.version }}. This PR was created by the Release Trigger workflow. The git tag \`${{ steps.version.outputs.tag }}\` has already been pushed and the release artifacts are being built. Merge this PR to record the version bump and changelog update on \`main\`." - name: Summary run: | echo "✅ Version bumped to ${{ steps.version.outputs.version }}" echo "✅ Tag ${{ steps.version.outputs.tag }} created and pushed" echo "✅ PR opened to merge version bump into main" echo "🚀 Release workflow is building artifacts from the tag"