Release #74
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
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| inputs: | |
| dry-run: | |
| description: "Skip release creation and npm publish (build + verify only)" | |
| type: boolean | |
| default: true | |
| permissions: {} | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| build: | |
| name: Build (${{ matrix.platform }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: darwin-arm64 | |
| os: macos-15 | |
| binary: claude-view | |
| artifact: claude-view-darwin-arm64.tar.gz | |
| - platform: darwin-x64 | |
| os: macos-15-intel | |
| binary: claude-view | |
| artifact: claude-view-darwin-x64.tar.gz | |
| - platform: linux-x64 | |
| os: ubuntu-24.04 | |
| binary: claude-view | |
| artifact: claude-view-linux-x64.tar.gz | |
| # Windows build deferred | |
| # - platform: win32-x64 | |
| # os: windows-latest | |
| # binary: claude-view.exe | |
| # artifact: claude-view-win32-x64.zip | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@4be9e76fd7c4901c61fb841f559994984270fce7 # stable | |
| - name: Install Linux build dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y pkg-config libssl-dev | |
| - name: Rust cache | |
| uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: "24" | |
| - name: Verify version matches tag | |
| if: github.ref_type == 'tag' | |
| shell: bash | |
| run: | | |
| TAG_VERSION="${GITHUB_REF_NAME#v}" | |
| PKG_VERSION=$(node -p "require('./npx-cli/package.json').version") | |
| CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/') | |
| if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then | |
| echo "::error::Tag version ($TAG_VERSION) != npx-cli/package.json version ($PKG_VERSION)" | |
| exit 1 | |
| fi | |
| if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then | |
| echo "::error::Tag version ($TAG_VERSION) != Cargo.toml version ($CARGO_VERSION)" | |
| exit 1 | |
| fi | |
| PLUGIN_VERSION=$(node -p "require('./packages/plugin/.claude-plugin/plugin.json').version") | |
| if [ "$TAG_VERSION" != "$PLUGIN_VERSION" ]; then | |
| echo "::error::Tag version ($TAG_VERSION) != plugin.json version ($PLUGIN_VERSION)" | |
| exit 1 | |
| fi | |
| echo "Version verified: $TAG_VERSION (npm + cargo + plugin)" | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 | |
| - name: Install frontend dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Build frontend | |
| run: cd apps/web && bun run build | |
| env: | |
| NODE_OPTIONS: "--max-old-space-size=4096" | |
| VITE_SUPABASE_URL: ${{ vars.VITE_SUPABASE_URL }} | |
| VITE_SUPABASE_PUBLISHABLE_KEY: ${{ vars.VITE_SUPABASE_PUBLISHABLE_KEY }} | |
| - name: Build sidecar | |
| run: | | |
| cd sidecar | |
| npm install | |
| npm run build | |
| - name: Build Rust binary (dist profile) | |
| run: cargo build --profile dist -p claude-view-server --no-default-features --features dist | |
| env: | |
| SUPABASE_URL: ${{ vars.SUPABASE_URL }} | |
| RELAY_URL: wss://claude-view-relay.fly.dev/ws | |
| SHARE_WORKER_URL: https://api-share.claudeview.ai | |
| SHARE_VIEWER_URL: https://share.claudeview.ai | |
| POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} | |
| - name: Stage sidecar | |
| run: | | |
| mkdir -p staging/sidecar | |
| cp -r sidecar/dist staging/sidecar/ | |
| - name: Package (unix) | |
| if: runner.os != 'Windows' | |
| run: | | |
| mkdir -p staging | |
| cp target/dist/${{ matrix.binary }} staging/ | |
| cp -r apps/web/dist staging/ | |
| tar -czf ${{ matrix.artifact }} -C staging . | |
| - name: Package (windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path staging | |
| Copy-Item "target\dist\${{ matrix.binary }}" -Destination staging\ | |
| Copy-Item -Recurse apps\web\dist staging\dist | |
| Compress-Archive -Path staging\* -DestinationPath ${{ matrix.artifact }} | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: ${{ matrix.artifact }} | |
| path: ${{ matrix.artifact }} | |
| retention-days: 1 | |
| verify: | |
| name: Verify artifacts | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Contract — all expected tarballs exist and are reasonable size | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| expected=(claude-view-darwin-arm64 claude-view-darwin-x64 claude-view-linux-x64) | |
| fail=0 | |
| for p in "${expected[@]}"; do | |
| f="artifacts/${p}.tar.gz" | |
| if [[ ! -f "$f" ]]; then | |
| echo "::error file=${f}::Missing artifact" | |
| fail=1 | |
| continue | |
| fi | |
| size=$(stat -c%s "$f") | |
| if [[ $size -lt 1000000 ]]; then | |
| echo "::error file=${f}::Artifact only $size bytes — build silently failed" | |
| fail=1 | |
| else | |
| echo "OK: ${f} ($size bytes)" | |
| fi | |
| done | |
| [[ $fail -eq 0 ]] || exit 1 | |
| - name: Contract — tarball internal structure matches npx-cli expectations | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| fail=0 | |
| for tarball in artifacts/claude-view-*.tar.gz; do | |
| tmp=$(mktemp -d) | |
| tar -xzf "$tarball" -C "$tmp" | |
| name=$(basename "$tarball") | |
| if ! test -f "$tmp/claude-view"; then | |
| echo "::error::${name}: missing binary 'claude-view'" | |
| fail=1 | |
| elif ! test -x "$tmp/claude-view"; then | |
| echo "::error::${name}: binary 'claude-view' not executable" | |
| fail=1 | |
| fi | |
| if ! test -d "$tmp/dist"; then | |
| echo "::error::${name}: missing frontend 'dist/' directory" | |
| fail=1 | |
| fi | |
| if ! test -d "$tmp/sidecar/dist"; then | |
| echo "::error::${name}: missing 'sidecar/dist/' directory" | |
| fail=1 | |
| fi | |
| rm -rf "$tmp" | |
| done | |
| [[ $fail -eq 0 ]] || exit 1 | |
| - name: Contract — linux-x64 binary runs and reports correct version | |
| shell: bash | |
| env: | |
| REF_TYPE: ${{ github.ref_type }} | |
| REF_NAME: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| tmp=$(mktemp -d) | |
| tar -xzf artifacts/claude-view-linux-x64.tar.gz -C "$tmp" | |
| actual=$("$tmp/claude-view" --version 2>&1 | head -1 | awk '{print $NF}') | |
| echo "Binary reports version: $actual" | |
| if [[ "$REF_TYPE" == "tag" ]]; then | |
| expected="${REF_NAME#v}" | |
| if [[ "$actual" != "$expected" ]]; then | |
| echo "::error::Binary version '$actual' != tag '$expected'" | |
| exit 1 | |
| fi | |
| echo "OK: binary version matches tag ($expected)" | |
| else | |
| echo "Not a tag push — skipping tag-vs-binary comparison" | |
| fi | |
| release: | |
| name: Create Release | |
| needs: verify | |
| if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.dry-run == false) }} | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Generate checksums | |
| run: | | |
| cd artifacts | |
| sha256sum claude-view-*.tar.gz > checksums.txt | |
| cat checksums.txt | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 | |
| with: | |
| generate_release_notes: true | |
| files: artifacts/* | |
| publish-npm: | |
| name: Publish to npm | |
| needs: release | |
| if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.dry-run == false) }} | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 | |
| with: | |
| node-version: "24" | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2 | |
| - name: Publish claude-view | |
| run: npm publish --access public || echo "Already published, skipping" | |
| working-directory: npx-cli | |
| - name: Build plugin | |
| run: cd packages/plugin && bun install && bun run build | |
| - name: Publish @claude-view/plugin | |
| run: npm publish --access public || echo "Already published, skipping" | |
| working-directory: packages/plugin |