name: Release on: push: tags: - "v*" permissions: contents: write jobs: build: name: Build (${{ matrix.binary }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - os: ubuntu-latest target: bun-linux-x64 binary: hai-linux-x64 - os: macos-latest target: bun-darwin-arm64 binary: hai-darwin-arm64 - os: macos-13 target: bun-darwin-x64 binary: hai-darwin-x64 - os: windows-latest target: bun-windows-x64 binary: hai-windows-x64.exe steps: - name: Checkout uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "22" cache: pnpm - name: Install Bun uses: oven-sh/setup-bun@v2 - name: Extract version from tag run: | VERSION="${GITHUB_REF#refs/tags/v}" echo "RELEASE_VERSION=${VERSION}" >> $GITHUB_ENV echo "Releasing version: ${VERSION}" - name: Verify tag matches package version run: | PKG_VERSION=$(node -p "require('./packages/cli/package.json').version") if [ "$RELEASE_VERSION" != "$PKG_VERSION" ]; then echo "ERROR: Tag version ($RELEASE_VERSION) does not match packages/cli/package.json version ($PKG_VERSION)" exit 1 fi echo "Version check passed: $RELEASE_VERSION" - name: Install dependencies run: pnpm install - name: Build run: pnpm build - name: Build standalone binary run: pnpm --filter hai build:exe -- --target ${{ matrix.target }} - name: Rename binary with platform and arch run: | PLATFORM=$(uname -s | tr '[:upper:]' '[:lower:]') ARCH=$(uname -m) case "$ARCH" in x86_64) ARCH="x64" ;; aarch64) ARCH="arm64" ;; esac cp packages/cli/dist/hai packages/cli/dist/hai-${PLATFORM}-${ARCH} # Code signing steps — activate when cross-platform matrix is in place (HAI-079) - name: Sign macOS binaries if: runner.os == 'macOS' env: APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} run: | for binary in packages/cli/dist/hai-darwin-*; do [ -f "$binary" ] && bash scripts/sign-macos.sh "$binary" done - name: Sign Windows binaries if: runner.os == 'Windows' env: WINDOWS_CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }} WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} run: | Get-ChildItem packages/cli/dist/hai-windows-*.exe | ForEach-Object { & .\scripts\sign-windows.ps1 $_.FullName } shell: pwsh - name: Generate checksum (Linux) if: runner.os == 'Linux' run: | cd packages/cli/dist sha256sum ${{ matrix.binary }} > ${{ matrix.binary }}.sha256 - name: Generate checksum (macOS) if: runner.os == 'macOS' run: | cd packages/cli/dist shasum -a 256 ${{ matrix.binary }} > ${{ matrix.binary }}.sha256 - name: Generate checksum (Windows) if: runner.os == 'Windows' shell: pwsh run: | cd packages/cli/dist $hash = (Get-FileHash -Algorithm SHA256 "${{ matrix.binary }}").Hash.ToLower() "$hash ${{ matrix.binary }}" | Out-File -Encoding ascii "${{ matrix.binary }}.sha256" - name: Upload binary artifact uses: actions/upload-artifact@v4 with: name: ${{ matrix.binary }} path: | packages/cli/dist/${{ matrix.binary }} packages/cli/dist/${{ matrix.binary }}.sha256 release: name: Create Release needs: build runs-on: ubuntu-latest permissions: contents: write steps: - name: Download all artifacts uses: actions/download-artifact@v4 with: path: artifacts - name: Collect release files run: | mkdir -p release find artifacts -type f -exec cp {} release/ \; ls -la release/ - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: generate_release_notes: true files: release/*