Skip to content

release: v2.1.4

release: v2.1.4 #10

Workflow file for this run

# 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