Build #97
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: Build | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Version to build (e.g., 1.0.0)" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| actions: write | |
| pull-requests: write | |
| jobs: | |
| # Pre-build SvelteKit app once and share across all platforms | |
| prebuild: | |
| name: Build SvelteKit App | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24" | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: | | |
| npm ci --prefer-offline || \ | |
| npm ci --prefer-offline || \ | |
| npm ci | |
| env: | |
| ONNXRUNTIME_NODE_INSTALL_CUDA: skip | |
| - name: Build SvelteKit | |
| run: npm run build | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: sveltekit-build | |
| path: build/ | |
| retention-days: 1 | |
| build: | |
| name: Build (${{ matrix.platform }}) | |
| runs-on: ${{ matrix.os }} | |
| needs: prebuild | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: macos-14 | |
| platform: mac-arm64 | |
| arch: arm64 | |
| - os: macos-14 | |
| platform: mac-x64 | |
| arch: x64 | |
| - os: windows-latest | |
| platform: win-x64 | |
| arch: x64 | |
| - os: windows-latest | |
| platform: win-arm64 | |
| arch: arm64 | |
| - os: ubuntu-latest | |
| platform: linux-x64 | |
| arch: x64 | |
| linux_targets: deb rpm AppImage | |
| - os: ubuntu-latest | |
| platform: linux-arm64 | |
| arch: arm64 | |
| linux_targets: AppImage | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Get version from tag, release or input | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "release" ]; then | |
| VERSION="${{ github.event.release.tag_name }}" | |
| VERSION="${VERSION#v}" | |
| elif [ "${{ github.event_name }}" = "push" ]; then | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| else | |
| VERSION="${{ inputs.version }}" | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| shell: bash | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24" | |
| cache: "npm" | |
| - name: Cache Electron binaries | |
| uses: actions/cache@v5 | |
| with: | |
| path: | | |
| ~/Library/Caches/electron | |
| ~/Library/Caches/electron-builder | |
| ~/.cache/electron | |
| ~/.cache/electron-builder | |
| ~/AppData/Local/electron/Cache | |
| ~/AppData/Local/electron-builder/Cache | |
| key: ${{ runner.os }}-${{ matrix.arch }}-electron-${{ hashFiles('**/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-${{ matrix.arch }}-electron- | |
| - name: Install dependencies | |
| run: | | |
| npm ci --prefer-offline || \ | |
| npm ci --prefer-offline || \ | |
| npm ci | |
| env: | |
| ONNXRUNTIME_NODE_INSTALL_CUDA: skip | |
| - name: Download SvelteKit build | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: sveltekit-build | |
| path: build/ | |
| - name: Update package.json version | |
| run: npm version ${{ steps.version.outputs.version }} --no-git-tag-version --allow-same-version | |
| - name: Build Electron (macOS) | |
| if: startsWith(matrix.platform, 'mac-') | |
| run: npm run electron:build:mac -- --${{ matrix.arch }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build Electron (Windows) | |
| if: startsWith(matrix.platform, 'win-') | |
| run: npm run electron:build:win -- --${{ matrix.arch }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build Electron (Linux) | |
| if: startsWith(matrix.platform, 'linux-') | |
| run: npm run build && npx electron-builder --linux ${{ matrix.linux_targets }} --${{ matrix.arch }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload Artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: build-${{ matrix.platform }} | |
| path: | | |
| dist-electron/*.dmg | |
| dist-electron/*.zip | |
| dist-electron/*.exe | |
| dist-electron/*.deb | |
| dist-electron/*.rpm | |
| dist-electron/*.AppImage | |
| retention-days: 7 | |
| publish-release: | |
| name: Publish Release | |
| runs-on: ubuntu-latest | |
| needs: build | |
| if: success() | |
| steps: | |
| - name: Get version from input | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "release" ]; then | |
| VERSION="${{ github.event.release.tag_name }}" | |
| elif [ "${{ github.event_name }}" = "push" ]; then | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| else | |
| VERSION="v${{ inputs.version }}" | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| shell: bash | |
| - name: Publish Draft Release | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { data: releases } = await github.rest.repos.listReleases({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| }); | |
| const draftRelease = releases.find(r => r.tag_name === '${{ steps.version.outputs.version }}' && r.draft); | |
| if (draftRelease) { | |
| await github.rest.repos.updateRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| release_id: draftRelease.id, | |
| draft: false | |
| }); | |
| console.log(`✅ Published release ${draftRelease.tag_name}`); | |
| } else { | |
| console.log('⚠️ No draft release found for ${{ steps.version.outputs.version }}'); | |
| } | |
| - name: Sync main to dev | |
| continue-on-error: true | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { data: comparison } = await github.rest.repos.compareCommits({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| base: 'dev', | |
| head: 'main' | |
| }); | |
| if (comparison.ahead_by > 0) { | |
| // Check for existing PR | |
| const { data: prs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| head: `${context.repo.owner}:main`, | |
| base: 'dev', | |
| state: 'open' | |
| }); | |
| let pr; | |
| if (prs.length > 0) { | |
| pr = prs[0]; | |
| console.log(`📋 Found existing PR #${pr.number}`); | |
| } else { | |
| const { data: newPr } = await github.rest.pulls.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| head: 'main', | |
| base: 'dev', | |
| title: 'chore: sync main to dev after ${{ steps.version.outputs.version }}', | |
| body: 'Automated PR to sync release changes from main to dev.' | |
| }); | |
| pr = newPr; | |
| console.log(`📋 Created PR #${pr.number}`); | |
| } | |
| // Enable auto-merge | |
| try { | |
| await github.rest.pulls.merge({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: pr.number, | |
| merge_method: 'merge' | |
| }); | |
| console.log('✅ Merged PR'); | |
| } catch (e) { | |
| console.log('⚠️ Could not merge (may need manual approval):', e.message); | |
| } | |
| } else { | |
| console.log('ℹ️ dev is up to date with main'); | |
| } | |
| - name: Trigger Deploy Workflow | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| await github.rest.actions.createWorkflowDispatch({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| workflow_id: 'deploy.yml', | |
| ref: 'main' | |
| }) | |
| cleanup-failed-release: | |
| name: Cleanup Failed Release | |
| runs-on: ubuntu-latest | |
| needs: build | |
| if: failure() || cancelled() | |
| steps: | |
| - name: Get version from input | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "release" ]; then | |
| VERSION="${{ github.event.release.tag_name }}" | |
| elif [ "${{ github.event_name }}" = "push" ]; then | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| else | |
| VERSION="v${{ inputs.version }}" | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| shell: bash | |
| - name: Delete Draft Release | |
| uses: actions/github-script@v8 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const { data: releases } = await github.rest.repos.listReleases({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| }); | |
| const draftRelease = releases.find(r => r.tag_name === '${{ steps.version.outputs.version }}' && r.draft); | |
| if (draftRelease) { | |
| await github.rest.repos.deleteRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| release_id: draftRelease.id | |
| }); | |
| console.log(`🗑️ Deleted failed draft release ${draftRelease.tag_name}`); | |
| } else { | |
| console.log('⚠️ No draft release found to delete for ${{ steps.version.outputs.version }}'); | |
| } |