release: v2.1.4 #10
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Build CLI + desktop app installers, then create a GitHub Release. | |
| # | |
| # Triggered by: git push origin main --tags (after running `make release`) | |
| # | |
| # What it does: | |
| # 1. Bundles CLI as a single .mjs file | |
| # 2. Builds desktop app for macOS (dmg) | |
| # 3. Extracts changelog for this version | |
| # 4. Creates a GitHub Release with all artifacts + changelog | |
| # 5. Updates manifest.json with the final git hash | |
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write | |
| jobs: | |
| # ── CLI (single .mjs file, platform-independent) ───────────────── | |
| # ink/yoga-layout use top-level await (ESM-only) which is incompatible | |
| # with Node.js SEA (CJS-only). We ship a single .mjs bundle instead. | |
| # The install script creates a wrapper that invokes it with node. | |
| cli: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 9 | |
| - name: Install dependencies | |
| run: pnpm install --ignore-scripts | |
| - name: Build TypeScript | |
| run: | | |
| pnpm --filter @anton/protocol build | |
| pnpm --filter @anton/cli build | |
| - name: Get CLI version | |
| id: cli_version | |
| run: echo "version=$(node -e "console.log(JSON.parse(require('fs').readFileSync('packages/cli/package.json','utf8')).version)")" >> "$GITHUB_OUTPUT" | |
| - name: Bundle CLI with esbuild | |
| run: | | |
| # Stub out react-devtools-core (ink imports it but it's optional/dev-only) | |
| mkdir -p .stubs | |
| echo "export default {};" > .stubs/react-devtools-core.mjs | |
| CLI_EXTERNALS=$(node scripts/esbuild.config.js cli-externals) | |
| npx esbuild packages/cli/dist/index.js \ | |
| --bundle \ | |
| --platform=node \ | |
| --target=node22 \ | |
| --format=esm \ | |
| --outfile=anton-cli.mjs \ | |
| $CLI_EXTERNALS \ | |
| --alias:react-devtools-core=./.stubs/react-devtools-core.mjs \ | |
| --define:__CLI_VERSION__=\"${{ steps.cli_version.outputs.version }}\" \ | |
| --banner:js="import{createRequire}from'module';const require=createRequire(import.meta.url);" | |
| chmod +x anton-cli.mjs | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: anton-cli | |
| path: anton-cli.mjs | |
| # ── Sidecar (Go binary, cross-compiled for Linux) ──────────────── | |
| sidecar: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.25' | |
| cache-dependency-path: sidecar/go.sum | |
| - name: Extract version from tag | |
| id: version | |
| run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" | |
| - name: Cross-compile sidecar | |
| working-directory: sidecar | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| LDFLAGS="-s -w -X main.version=${VERSION}" | |
| GOOS=linux GOARCH=arm64 go build -ldflags "$LDFLAGS" -o ../anton-sidecar-linux-arm64 . | |
| GOOS=linux GOARCH=amd64 go build -ldflags "$LDFLAGS" -o ../anton-sidecar-linux-amd64 . | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sidecar-binaries | |
| path: | | |
| anton-sidecar-linux-arm64 | |
| anton-sidecar-linux-amd64 | |
| # ── Detect desktop changes (tag events don't support path filters) ─ | |
| desktop-changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| changed: ${{ steps.check.outputs.changed }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check if desktop-related files changed since last tag | |
| id: check | |
| run: | | |
| # Find the previous tag (the one before the current push) | |
| PREV_TAG=$(git tag --sort=-v:refname | grep '^v' | sed -n '2p') | |
| if [ -z "$PREV_TAG" ]; then | |
| echo "No previous tag found — building desktop" | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "Comparing $PREV_TAG..HEAD" | |
| # Paths that should trigger a desktop rebuild | |
| DESKTOP_PATHS="packages/desktop/ packages/protocol/" | |
| CHANGED=$(git diff --name-only "$PREV_TAG"..HEAD -- $DESKTOP_PATHS) | |
| if [ -n "$CHANGED" ]; then | |
| echo "Desktop-related files changed:" | |
| echo "$CHANGED" | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No desktop-related files changed — skipping build" | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| # ── Desktop app (macOS) ───────────────────────────────────────── | |
| desktop: | |
| needs: [desktop-changes] | |
| if: needs.desktop-changes.outputs.changed == 'true' | |
| strategy: | |
| matrix: | |
| include: | |
| - os: macos-latest | |
| target: macos | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 9 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Build protocol (desktop dependency) | |
| run: pnpm --filter @anton/protocol build | |
| - name: Build desktop app | |
| uses: tauri-apps/tauri-action@v0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} | |
| with: | |
| projectPath: packages/desktop | |
| tauriScript: pnpm tauri | |
| - name: Upload desktop artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: desktop-${{ matrix.target }} | |
| path: | | |
| packages/desktop/src-tauri/target/release/bundle/**/*.dmg | |
| packages/desktop/src-tauri/target/release/bundle/**/*.app.tar.gz | |
| packages/desktop/src-tauri/target/release/bundle/**/*.app.tar.gz.sig | |
| packages/desktop/src-tauri/target/release/bundle/**/*.msi | |
| packages/desktop/src-tauri/target/release/bundle/**/*.msi.sig | |
| packages/desktop/src-tauri/target/release/bundle/**/*.AppImage | |
| packages/desktop/src-tauri/target/release/bundle/**/*.AppImage.sig | |
| packages/desktop/src-tauri/target/release/bundle/**/*.deb | |
| # ── Create GitHub Release ──────────────────────────────────────── | |
| release: | |
| needs: [cli, sidecar, desktop] | |
| if: always() && needs.cli.result == 'success' && needs.sidecar.result == 'success' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Extract version from tag | |
| id: version | |
| run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" | |
| - name: Extract changelog | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| node -e " | |
| const fs = require('fs'); | |
| const changelog = fs.readFileSync('CHANGELOG.md', 'utf8'); | |
| const regex = new RegExp('## \\\\[' + '${VERSION}'.replace(/\\./g, '\\\\.') + '\\\\][\\\\s\\\\S]*?(?=\\n---)', 'm'); | |
| const match = changelog.match(regex); | |
| fs.writeFileSync('release-notes.md', match ? match[0] : 'Release v${VERSION}'); | |
| " | |
| - name: Collect all release assets | |
| run: | | |
| mkdir -p release-assets | |
| # CLI | |
| cp artifacts/anton-cli/anton-cli.mjs release-assets/ 2>/dev/null || true | |
| # Sidecar binaries | |
| cp artifacts/sidecar-binaries/anton-sidecar-linux-* release-assets/ 2>/dev/null || true | |
| # Desktop installers (only present when desktop files changed) | |
| if ls artifacts/desktop-* 1>/dev/null 2>&1; then | |
| find artifacts/desktop-* -type f \( \ | |
| -name "*.dmg" -o -name "*.msi" -o -name "*.AppImage" -o -name "*.deb" \ | |
| -o -name "*.app.tar.gz" -o -name "*.app.tar.gz.sig" \ | |
| -o -name "*.msi.sig" -o -name "*.AppImage.sig" \ | |
| \) -exec cp {} release-assets/ \; | |
| find artifacts/desktop-* -name "latest.json" -exec cp {} release-assets/ \; 2>/dev/null || true | |
| fi | |
| echo "Release assets:" | |
| ls -lh release-assets/ | |
| - name: Create GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release create "${{ github.ref_name }}" \ | |
| --title "v${{ steps.version.outputs.version }}" \ | |
| --notes-file release-notes.md \ | |
| release-assets/* | |
| - name: Update manifest with git hash | |
| run: | | |
| GIT_HASH=$(git rev-parse --short HEAD) | |
| node -e " | |
| const fs = require('fs'); | |
| const manifest = JSON.parse(fs.readFileSync('manifest.json', 'utf8')); | |
| manifest.gitHash = '${GIT_HASH}'; | |
| fs.writeFileSync('manifest.json', JSON.stringify(manifest, null, 2) + '\n'); | |
| " | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add manifest.json | |
| git commit -m "ci: update manifest.json with git hash for v${{ steps.version.outputs.version }}" | |
| git push origin HEAD:main |