Spaces:
Paused
Paused
| name: Bump version + release | |
| on: | |
| push: | |
| branches: [master] | |
| paths-ignore: | |
| - "packages/electron/package.json" | |
| - "*.md" | |
| workflow_dispatch: | |
| concurrency: | |
| group: bump-version | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| actions: write | |
| jobs: | |
| bump: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for new commits since last tag | |
| id: check | |
| run: | | |
| LAST_TAG=$(git tag --sort=-v:refname | grep '^v' | head -1 || echo "") | |
| if [ -z "$LAST_TAG" ]; then | |
| echo "No previous tag, skipping" | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Count non-merge, non-chore commits since last tag | |
| NEW_COMMITS=$(git log "${LAST_TAG}..HEAD" --no-merges \ | |
| --pretty=format:"%s" | grep -cvE "^(chore|docs|ci)" || true) | |
| if [ "$NEW_COMMITS" -eq 0 ]; then | |
| echo "No meaningful commits since $LAST_TAG, skipping" | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "Found $NEW_COMMITS new commit(s) since $LAST_TAG" | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| echo "last_tag=$LAST_TAG" >> "$GITHUB_OUTPUT" | |
| - name: Bump version + tag | |
| id: bump | |
| if: steps.check.outputs.skip != 'true' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| LAST_TAG="${{ steps.check.outputs.last_tag }}" | |
| CURRENT="${LAST_TAG#v}" | |
| IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" | |
| NEW_PATCH=$((PATCH + 1)) | |
| NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}" | |
| NEW_TAG="v${NEW_VERSION}" | |
| # Check tag doesn't already exist | |
| if git rev-parse "$NEW_TAG" >/dev/null 2>&1; then | |
| echo "Tag $NEW_TAG already exists, skipping" | |
| exit 0 | |
| fi | |
| # Bump both root and electron package versions | |
| node -e " | |
| const fs = require('fs'); | |
| for (const p of ['package.json', 'packages/electron/package.json']) { | |
| const pkg = JSON.parse(fs.readFileSync(p, 'utf-8')); | |
| pkg.version = '${NEW_VERSION}'; | |
| fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\n'); | |
| } | |
| " | |
| git add package.json packages/electron/package.json | |
| git commit -m "chore: bump version to ${NEW_VERSION} [skip ci]" | |
| git tag -a "$NEW_TAG" -m "Release ${NEW_TAG}" | |
| # Retry push with rebase on conflict (other workflows may push concurrently) | |
| for i in 1 2 3; do | |
| if git push origin master --follow-tags; then | |
| echo "Bumped to $NEW_VERSION, tagged $NEW_TAG" | |
| echo "new_tag=$NEW_TAG" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "Push failed (attempt $i/3), rebasing and retrying..." | |
| git tag -d "$NEW_TAG" | |
| git pull --rebase origin master | |
| git tag -a "$NEW_TAG" -m "Release ${NEW_TAG}" | |
| sleep 2 | |
| done | |
| echo "::error::Push failed after 3 attempts" | |
| exit 1 | |
| - name: Trigger release workflow | |
| if: steps.bump.outputs.new_tag | |
| run: | | |
| echo "Dispatching release for $NEW_TAG" | |
| gh workflow run release.yml -f tag="$NEW_TAG" | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| NEW_TAG: ${{ steps.bump.outputs.new_tag }} | |