name: Release on: push: branches: [main] paths: - 'src/**' - 'src-tauri/**' - 'package.json' - 'vite.config.ts' - 'index.html' jobs: test: name: Run Tests if: "!contains(github.event.head_commit.message, '[skip ci]')" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - name: Install npm deps run: npm ci - name: Frontend tests run: npx vitest run - name: Install uv run: | curl -LsSf https://astral.sh/uv/install.sh | sh echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Python tests run: | uv venv .testvenv VIRTUAL_ENV=.testvenv uv pip install pytest httpx pytest-asyncio anyio fastapi pydantic pyyaml uvicorn requests .testvenv/bin/python -m pytest backend/tests/ client/tests/ -v --tb=short bump-version: name: Bump version and tag needs: test runs-on: ubuntu-latest outputs: new_version: ${{ steps.bump.outputs.new_version }} tag: ${{ steps.bump.outputs.tag }} 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 id: bump run: | CURRENT=$(grep '"version"' package.json | head -1 | sed 's/.*"version": *"\([^"]*\)".*/\1/') echo "Current version: ${CURRENT}" 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}" sed -i "s/\"version\": \"${CURRENT}\"/\"version\": \"${NEW_VERSION}\"/" package.json sed -i "s/\"version\": \"${CURRENT}\"/\"version\": \"${NEW_VERSION}\"/" src-tauri/tauri.conf.json sed -i "s/^version = \"${CURRENT}\"/version = \"${NEW_VERSION}\"/" src-tauri/Cargo.toml sed -i "s/__version__ = \"${CURRENT}\"/__version__ = \"${NEW_VERSION}\"/" version.py sed -i "s/__version_info__ = .*/__version_info__ = (${MAJOR}, ${MINOR}, ${NEW_PATCH})/" version.py echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT echo "tag=v${NEW_VERSION}" >> $GITHUB_OUTPUT - name: Commit and tag env: BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} run: | NEW_VERSION="${{ steps.bump.outputs.new_version }}" git add package.json src-tauri/tauri.conf.json src-tauri/Cargo.toml version.py git commit -m "chore: bump version to ${NEW_VERSION} [skip ci]" git tag "v${NEW_VERSION}" REMOTE_URL=$(git remote get-url origin | sed "s|://|://gitea-actions:${BUILD_TOKEN}@|") git pull --rebase "${REMOTE_URL}" main || true 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="${{ steps.bump.outputs.tag }}" RELEASE_NAME="Local Transcription ${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}" - name: Trigger per-OS app builds env: BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} run: | REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" TAG="${{ steps.bump.outputs.tag }}" for workflow in build-app-linux.yml build-app-windows.yml build-app-macos.yml; do echo "Dispatching ${workflow} for ${TAG}..." HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ -H "Authorization: token ${BUILD_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"ref\": \"main\", \"inputs\": {\"tag\": \"${TAG}\"}}" \ "${REPO_API}/actions/workflows/${workflow}/dispatches") echo " -> HTTP ${HTTP_CODE}" done - name: Clean up old app releases env: BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} run: | REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" KEEP=3 PROTECT_TAG="v1.4.0" echo "Cleaning up old app releases (keeping latest ${KEEP} + ${PROTECT_TAG})..." # Get all app releases (v* tags, not sidecar-v*) RELEASES=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \ "${REPO_API}/releases?limit=50" | jq -c '[.[] | select(.tag_name | startswith("v")) | select(.tag_name | startswith("sidecar") | not)]') TOTAL=$(echo "$RELEASES" | jq 'length') echo "Found ${TOTAL} app releases" if [ "$TOTAL" -le "$KEEP" ]; then echo "Nothing to clean up" exit 0 fi # Skip the newest KEEP releases, delete the rest (except protected) echo "$RELEASES" | jq -c ".[$KEEP:][]" | while read -r release; do ID=$(echo "$release" | jq -r '.id') TAG=$(echo "$release" | jq -r '.tag_name') if [ "$TAG" = "$PROTECT_TAG" ]; then echo " Protecting ${TAG}" continue fi echo " Deleting release ${TAG} (ID: ${ID})..." curl -s -X DELETE -H "Authorization: token ${BUILD_TOKEN}" \ "${REPO_API}/releases/${ID}" # Also delete the tag curl -s -X DELETE -H "Authorization: token ${BUILD_TOKEN}" \ "${REPO_API}/tags/${TAG}" done echo "Cleanup complete"