name: Cross-platform packages on: workflow_dispatch: push: branches: - main tags: - 'v*' permissions: contents: read concurrency: group: packages-${{ github.ref }} cancel-in-progress: ${{ github.ref_type != 'tag' }} jobs: validate: name: Validate source runs-on: ubuntu-24.04 timeout-minutes: 20 steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: 24 cache: npm - name: Verify release tag version if: github.ref_type == 'tag' run: node -e "const p=require('./package.json'); const expected='v'+p.version; if(process.env.GITHUB_REF_NAME!==expected){throw new Error('Expected tag '+expected+', received '+process.env.GITHUB_REF_NAME)}" - name: Install dependencies run: npm ci - name: Run validators run: | npm test npm run typecheck npm run lint - name: Build production bundle run: npm run build:bundle - name: Upload production bundle if: github.event_name == 'workflow_dispatch' || github.ref_type == 'tag' uses: actions/upload-artifact@v7 with: name: goodbuddy-production-bundle path: out if-no-files-found: error retention-days: 1 package: name: ${{ matrix.platform }} ${{ matrix.arch }} if: github.event_name == 'workflow_dispatch' || github.ref_type == 'tag' needs: validate strategy: fail-fast: false matrix: include: - platform: windows arch: x64 runner: windows-2025 - platform: windows arch: arm64 runner: windows-2025 - platform: macos arch: x64 runner: macos-15-intel - platform: macos arch: arm64 runner: macos-15 - platform: linux arch: x64 runner: ubuntu-24.04 - platform: linux arch: arm64 runner: ubuntu-24.04-arm runs-on: ${{ matrix.runner }} timeout-minutes: 75 steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: 24 cache: npm - name: Cache packaging toolsets uses: actions/cache@v6 with: path: | ${{ runner.temp }}/electron ${{ runner.temp }}/electron-builder key: packaging-${{ runner.os }}-${{ matrix.arch }}-${{ hashFiles('package-lock.json') }} restore-keys: packaging-${{ runner.os }}-${{ matrix.arch }}- - name: Install dependencies run: npm ci env: ELECTRON_CACHE: ${{ runner.temp }}/electron - name: Download production bundle uses: actions/download-artifact@v8 with: name: goodbuddy-production-bundle path: out - name: Build and verify release packages run: npm run release:package -- --platform ${{ matrix.platform }} --arch ${{ matrix.arch }} --skip-build env: ELECTRON_CACHE: ${{ runner.temp }}/electron ELECTRON_BUILDER_CACHE: ${{ runner.temp }}/electron-builder - name: Upload release packages uses: actions/upload-artifact@v7 with: name: goodbuddy-${{ matrix.platform }}-${{ matrix.arch }} path: dist/release/${{ matrix.platform }}-${{ matrix.arch }} if-no-files-found: error compression-level: 0 retention-days: 30 release: name: Publish GitHub Release if: github.event_name == 'push' && github.ref_type == 'tag' needs: package runs-on: ubuntu-24.04 timeout-minutes: 20 permissions: contents: write actions: read steps: - uses: actions/checkout@v7 with: fetch-depth: 0 - uses: actions/setup-node@v7 with: node-version: 24 - name: Verify release tag shell: bash run: | set -euo pipefail expected="v$(node -p "require('./package.json').version")" test "$GITHUB_REF_NAME" = "$expected" test "$(git rev-parse "refs/tags/$GITHUB_REF_NAME^{commit}")" = "$GITHUB_SHA" - name: Download Windows packages uses: actions/download-artifact@v8 with: pattern: goodbuddy-windows-* path: dist/release-downloads - name: Download macOS packages uses: actions/download-artifact@v8 with: pattern: goodbuddy-macos-* path: dist/release-downloads - name: Download Linux packages uses: actions/download-artifact@v8 with: pattern: goodbuddy-linux-* path: dist/release-downloads - name: Verify and aggregate release assets run: node build/aggregate-release.cjs --input dist/release-downloads --output dist/release-upload - name: Create or update draft release shell: bash env: GH_TOKEN: ${{ github.token }} run: | set -euo pipefail tag="$GITHUB_REF_NAME" if gh release view "$tag" >/dev/null 2>&1; then gh release edit "$tag" --draft else version="$(node -p "require('./package.json').version")" gh release create "$tag" --draft --verify-tag --generate-notes --title "GoodBuddy $version" fi gh release upload "$tag" dist/release-upload/* --clobber gh release edit "$tag" --draft=false --latest