Add auto-increment version and release workflow
All checks were successful
Release / Bump version and tag (push) Successful in 3s

- New release.yml: bumps patch version, commits with skip-ci marker, tags, creates Gitea release
- Build workflows now trigger on v* tags only (not branch push)
- Simplified upload steps: use tag directly, retry loop for release lookup
- Fix macOS: install jq if missing
- Sync python/pyproject.toml version to 0.2.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude
2026-03-21 11:51:11 -07:00
parent b7a00af2e0
commit 1ed34e0bbb
5 changed files with 132 additions and 62 deletions

View File

@@ -2,9 +2,7 @@ name: Build Linux
on: on:
push: push:
branches: [main] tags: ["v*"]
pull_request:
branches: [main]
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.11"
@@ -65,35 +63,33 @@ jobs:
# ── Release ── # ── Release ──
- name: Upload to release - name: Upload to release
if: github.ref == 'refs/heads/main'
env: env:
BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }}
run: | run: |
sudo apt-get install -y jq sudo apt-get install -y jq
REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
# Check if the current commit has a version tag TAG="${GITHUB_REF_NAME}"
VERSION_TAG=$(git tag --points-at HEAD | grep '^v' | head -1) RELEASE_NAME="Voice to Notes ${TAG}"
if [ -n "${VERSION_TAG}" ]; then
TAG="${VERSION_TAG}"
RELEASE_NAME="Voice to Notes ${TAG}"
PRERELEASE=false
else
TAG="latest"
RELEASE_NAME="Voice to Notes (Latest Build)"
PRERELEASE=true
fi
echo "Release tag: ${TAG}" echo "Release tag: ${TAG}"
RELEASE_ID=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \ # Wait for release to be created by the release workflow
"${REPO_API}/releases/tags/${TAG}" | jq -r '.id // empty') for i in 1 2 3 4 5; do
RELEASE_ID=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \
"${REPO_API}/releases/tags/${TAG}" | jq -r '.id // empty')
if [ -n "${RELEASE_ID}" ] && [ "${RELEASE_ID}" != "null" ]; then
break
fi
echo "Release not found yet, waiting 10s... (attempt $i)"
sleep 10
done
if [ -z "${RELEASE_ID}" ]; then # Fallback: create release if it still doesn't exist
if [ -z "${RELEASE_ID}" ] || [ "${RELEASE_ID}" = "null" ]; then
RELEASE_ID=$(curl -s -X POST \ RELEASE_ID=$(curl -s -X POST \
-H "Authorization: token ${BUILD_TOKEN}" \ -H "Authorization: token ${BUILD_TOKEN}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "{\"tag_name\": \"${TAG}\", \"name\": \"${RELEASE_NAME}\", \"body\": \"Automated build.\", \"draft\": false, \"prerelease\": ${PRERELEASE}}" \ -d "{\"tag_name\": \"${TAG}\", \"name\": \"${RELEASE_NAME}\", \"body\": \"Automated build.\", \"draft\": false, \"prerelease\": false}" \
"${REPO_API}/releases" | jq -r '.id') "${REPO_API}/releases" | jq -r '.id')
fi fi

View File

@@ -2,9 +2,7 @@ name: Build macOS
on: on:
push: push:
branches: [main] tags: ["v*"]
pull_request:
branches: [main]
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.11"
@@ -64,34 +62,35 @@ jobs:
# ── Release ── # ── Release ──
- name: Upload to release - name: Upload to release
if: github.ref == 'refs/heads/main'
env: env:
BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }}
run: | run: |
# Ensure jq is available
which jq || brew install jq
REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
# Check if the current commit has a version tag TAG="${GITHUB_REF_NAME}"
VERSION_TAG=$(git tag --points-at HEAD | grep '^v' | head -1) RELEASE_NAME="Voice to Notes ${TAG}"
if [ -n "${VERSION_TAG}" ]; then
TAG="${VERSION_TAG}"
RELEASE_NAME="Voice to Notes ${TAG}"
PRERELEASE=false
else
TAG="latest"
RELEASE_NAME="Voice to Notes (Latest Build)"
PRERELEASE=true
fi
echo "Release tag: ${TAG}" echo "Release tag: ${TAG}"
RELEASE_ID=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \ # Wait for release to be created by the release workflow
"${REPO_API}/releases/tags/${TAG}" | jq -r '.id // empty') for i in 1 2 3 4 5; do
RELEASE_ID=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \
"${REPO_API}/releases/tags/${TAG}" | jq -r '.id // empty')
if [ -n "${RELEASE_ID}" ] && [ "${RELEASE_ID}" != "null" ]; then
break
fi
echo "Release not found yet, waiting 10s... (attempt $i)"
sleep 10
done
if [ -z "${RELEASE_ID}" ]; then # Fallback: create release if it still doesn't exist
if [ -z "${RELEASE_ID}" ] || [ "${RELEASE_ID}" = "null" ]; then
RELEASE_ID=$(curl -s -X POST \ RELEASE_ID=$(curl -s -X POST \
-H "Authorization: token ${BUILD_TOKEN}" \ -H "Authorization: token ${BUILD_TOKEN}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "{\"tag_name\": \"${TAG}\", \"name\": \"${RELEASE_NAME}\", \"body\": \"Automated build.\", \"draft\": false, \"prerelease\": ${PRERELEASE}}" \ -d "{\"tag_name\": \"${TAG}\", \"name\": \"${RELEASE_NAME}\", \"body\": \"Automated build.\", \"draft\": false, \"prerelease\": false}" \
"${REPO_API}/releases" | jq -r '.id') "${REPO_API}/releases" | jq -r '.id')
fi fi

View File

@@ -2,9 +2,7 @@ name: Build Windows
on: on:
push: push:
branches: [main] tags: ["v*"]
pull_request:
branches: [main]
env: env:
PYTHON_VERSION: "3.11" PYTHON_VERSION: "3.11"
@@ -74,7 +72,6 @@ jobs:
# ── Release ── # ── Release ──
- name: Upload to release - name: Upload to release
if: github.ref == 'refs/heads/main'
shell: powershell shell: powershell
env: env:
BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }}
@@ -82,30 +79,31 @@ jobs:
$REPO_API = "${{ github.server_url }}/api/v1/repos/${{ github.repository }}" $REPO_API = "${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
$Headers = @{ "Authorization" = "token $env:BUILD_TOKEN" } $Headers = @{ "Authorization" = "token $env:BUILD_TOKEN" }
# Check if the current commit has a version tag $TAG = "${{ github.ref_name }}"
$VERSION_TAG = (git tag --points-at HEAD | Select-String '^v').Line $RELEASE_NAME = "Voice to Notes ${TAG}"
if ($VERSION_TAG) {
$TAG = $VERSION_TAG
$RELEASE_NAME = "Voice to Notes ${TAG}"
$PRERELEASE = $false
} else {
$TAG = "latest"
$RELEASE_NAME = "Voice to Notes (Latest Build)"
$PRERELEASE = $true
}
Write-Host "Release tag: ${TAG}" Write-Host "Release tag: ${TAG}"
try { # Wait for release to be created by the release workflow
$release = Invoke-RestMethod -Uri "${REPO_API}/releases/tags/${TAG}" -Headers $Headers -ErrorAction Stop $RELEASE_ID = $null
$RELEASE_ID = $release.id for ($i = 1; $i -le 5; $i++) {
} catch { try {
$release = Invoke-RestMethod -Uri "${REPO_API}/releases/tags/${TAG}" -Headers $Headers -ErrorAction Stop
$RELEASE_ID = $release.id
break
} catch {
Write-Host "Release not found yet, waiting 10s... (attempt $i)"
Start-Sleep -Seconds 10
}
}
# Fallback: create release if it still doesn't exist
if (-not $RELEASE_ID) {
$body = @{ $body = @{
tag_name = $TAG tag_name = $TAG
name = $RELEASE_NAME name = $RELEASE_NAME
body = "Automated build." body = "Automated build."
draft = $false draft = $false
prerelease = $PRERELEASE prerelease = $false
} | ConvertTo-Json } | ConvertTo-Json
$release = Invoke-RestMethod -Uri "${REPO_API}/releases" -Method Post -Headers $Headers -ContentType "application/json" -Body $body $release = Invoke-RestMethod -Uri "${REPO_API}/releases" -Method Post -Headers $Headers -ContentType "application/json" -Body $body
$RELEASE_ID = $release.id $RELEASE_ID = $release.id

View File

@@ -0,0 +1,77 @@
name: Release
on:
push:
branches: [main]
jobs:
bump-version:
name: Bump version and tag
# Skip if this is a version-bump commit (avoid infinite loop)
if: "!contains(github.event.head_commit.message, '[skip ci]')"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure git
run: |
git config user.name "Gitea Actions"
git config user.email "actions@gitea.local"
- name: Bump patch version
run: |
# Read current version from package.json
CURRENT=$(grep '"version"' package.json | head -1 | sed 's/.*"version": *"\([^"]*\)".*/\1/')
echo "Current version: ${CURRENT}"
# Increment patch number
MAJOR=$(echo "${CURRENT}" | cut -d. -f1)
MINOR=$(echo "${CURRENT}" | cut -d. -f2)
PATCH=$(echo "${CURRENT}" | cut -d. -f3)
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}"
echo "New version: ${NEW_VERSION}"
# Update package.json
sed -i "s/\"version\": \"${CURRENT}\"/\"version\": \"${NEW_VERSION}\"/" package.json
# Update src-tauri/tauri.conf.json
sed -i "s/\"version\": \"${CURRENT}\"/\"version\": \"${NEW_VERSION}\"/" src-tauri/tauri.conf.json
# Update src-tauri/Cargo.toml (match version = "x.y.z" in [package] section)
sed -i "s/^version = \"${CURRENT}\"/version = \"${NEW_VERSION}\"/" src-tauri/Cargo.toml
# Update python/pyproject.toml
sed -i "s/^version = \".*\"/version = \"${NEW_VERSION}\"/" python/pyproject.toml
echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_ENV
- name: Commit and tag
env:
BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }}
run: |
git add package.json src-tauri/tauri.conf.json src-tauri/Cargo.toml python/pyproject.toml
git commit -m "chore: bump version to ${NEW_VERSION} [skip ci]"
git tag "v${NEW_VERSION}"
# Push using token for authentication
REMOTE_URL=$(git remote get-url origin | sed "s|://|://gitea-actions:${BUILD_TOKEN}@|")
git push "${REMOTE_URL}" HEAD:main
git push "${REMOTE_URL}" "v${NEW_VERSION}"
- name: Create Gitea release
env:
BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }}
run: |
REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
TAG="v${NEW_VERSION}"
RELEASE_NAME="Voice to Notes ${TAG}"
curl -s -X POST \
-H "Authorization: token ${BUILD_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"tag_name\": \"${TAG}\", \"name\": \"${RELEASE_NAME}\", \"body\": \"Automated build.\", \"draft\": false, \"prerelease\": false}" \
"${REPO_API}/releases"
echo "Created release: ${RELEASE_NAME}"

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "voice-to-notes" name = "voice-to-notes"
version = "0.1.0" version = "0.2.0"
description = "Python sidecar for Voice to Notes — transcription, diarization, and AI services" description = "Python sidecar for Voice to Notes — transcription, diarization, and AI services"
requires-python = ">=3.11" requires-python = ">=3.11"
license = "MIT" license = "MIT"