ci: skip create-release when release already exists #30
Workflow file for this run
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 GUI | |
| permissions: | |
| contents: write | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Tag name (e.g. v0.1.0)' | |
| required: false | |
| jobs: | |
| create-release: | |
| runs-on: ubuntu-latest | |
| if: startsWith(github.ref, 'refs/tags/') | |
| steps: | |
| - name: Check if release exists | |
| id: check | |
| run: | | |
| STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ | |
| -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
| "https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }}") | |
| echo "exists=$( [ "$STATUS" = "200" ] && echo true || echo false )" >> "$GITHUB_OUTPUT" | |
| - name: Create GitHub Release | |
| if: steps.check.outputs.exists == 'false' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| draft: false | |
| generate_release_notes: true | |
| make_latest: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| build-windows: | |
| needs: create-release | |
| if: always() && (needs.create-release.result == 'success' || !startsWith(github.ref, 'refs/tags/')) | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Install proxy dependencies | |
| run: cd copilot-proxy && npm install --ignore-scripts --no-package-lock | |
| - name: Generate icons | |
| run: node scripts/generate-icons.cjs | |
| - name: Build frontend | |
| run: npx vite build | |
| - name: Bundle proxy server (JS) | |
| run: node scripts/bundle-proxy.cjs | |
| - name: Package with electron-builder | |
| run: npx electron-builder --win --config electron-builder.yml | |
| - name: Generate update manifest | |
| run: | | |
| node -e " | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const crypto = require('crypto'); | |
| const sha256 = f => crypto.createHash('sha256').update(fs.readFileSync(f)).digest('hex'); | |
| const asarPath = path.join('release', 'win-unpacked', 'resources', 'app.asar'); | |
| const bundlePath = path.join('build', 'copilot-proxy-bundle.mjs'); | |
| if (!fs.existsSync(asarPath) || !fs.existsSync(bundlePath)) { console.error('Missing assets'); process.exit(1); } | |
| const pkg = require('./package.json'); | |
| const ePkg = require('./node_modules/electron/package.json'); | |
| const manifest = { | |
| version: pkg.version, | |
| minElectronVersion: ePkg.version.split('.')[0] + '.0.0', | |
| assets: { | |
| 'app.asar': { size: fs.statSync(asarPath).size, sha256: sha256(asarPath) }, | |
| 'copilot-proxy-bundle.mjs': { size: fs.statSync(bundlePath).size, sha256: sha256(bundlePath) }, | |
| }, | |
| }; | |
| fs.writeFileSync('release/update-manifest.json', JSON.stringify(manifest, null, 2)); | |
| fs.copyFileSync(asarPath, 'release/app.asar'); | |
| fs.copyFileSync(bundlePath, 'release/copilot-proxy-bundle.mjs'); | |
| console.log(JSON.stringify(manifest, null, 2)); | |
| " | |
| - name: Upload to GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| release/*.exe | |
| release/update-manifest.json | |
| release/app.asar | |
| release/copilot-proxy-bundle.mjs | |
| fail_on_unmatched_files: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload artifacts (for non-tag builds) | |
| if: "!startsWith(github.ref, 'refs/tags/')" | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-release | |
| path: release/*.exe | |
| retention-days: 30 | |
| build-macos: | |
| needs: create-release | |
| if: always() && (needs.create-release.result == 'success' || !startsWith(github.ref, 'refs/tags/')) | |
| runs-on: macos-latest | |
| strategy: | |
| matrix: | |
| arch: [arm64, x64] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Install proxy dependencies | |
| run: cd copilot-proxy && npm install --ignore-scripts --no-package-lock | |
| - name: Generate icons | |
| run: node scripts/generate-icons.cjs | |
| - name: Build frontend | |
| run: npx vite build | |
| - name: Bundle proxy server (JS) | |
| run: node scripts/bundle-proxy.cjs | |
| - name: Package with electron-builder | |
| run: npx electron-builder --mac --${{ matrix.arch }} --config electron-builder.yml | |
| env: | |
| CSC_IDENTITY_AUTO_DISCOVERY: false | |
| - name: Verify DMG integrity | |
| run: | | |
| for f in release/*.dmg; do | |
| echo "Verifying: $f" | |
| ls -lh "$f" | |
| shasum -a 256 "$f" | |
| hdiutil verify "$f" | |
| done | |
| - name: Upload to GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: release/*.dmg | |
| fail_on_unmatched_files: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload artifacts (for non-tag builds) | |
| if: "!startsWith(github.ref, 'refs/tags/')" | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: macos-release-${{ matrix.arch }} | |
| path: release/*.dmg | |
| retention-days: 30 |