Build and Release #68
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 and Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| delivery_profile: | |
| description: Select which platform set to package | |
| type: choice | |
| default: full | |
| options: | |
| - full | |
| - fast | |
| - windows-only | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.inputs.delivery_profile || 'tag' }} | |
| cancel-in-progress: ${{ github.event_name != 'push' }} | |
| env: | |
| NODE_VERSION: '20' | |
| jobs: | |
| resolve-matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.set-matrix.outputs.matrix }} | |
| steps: | |
| - name: Resolve build matrix | |
| id: set-matrix | |
| shell: bash | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| DELIVERY_PROFILE: ${{ inputs.delivery_profile }} | |
| run: | | |
| if [[ "$EVENT_NAME" == "workflow_dispatch" ]]; then | |
| profile="$DELIVERY_PROFILE" | |
| else | |
| profile="full" | |
| fi | |
| case "$profile" in | |
| windows-only) | |
| matrix='{"include":[{"os":"windows-latest","platform":"windows","build_command":"npx --no-install electron-builder --config electron-builder.yml --win --publish never"}]}' | |
| ;; | |
| fast) | |
| matrix='{"include":[{"os":"windows-latest","platform":"windows","build_command":"npx --no-install electron-builder --config electron-builder.yml --win --publish never"}]}' | |
| ;; | |
| *) | |
| matrix='{"include":[{"os":"windows-latest","platform":"windows","build_command":"npx --no-install electron-builder --config electron-builder.yml --win --publish never"},{"os":"macos-latest","platform":"macos","build_command":"npx --no-install electron-builder --config electron-builder.yml --mac --publish never"},{"os":"ubuntu-latest","platform":"linux","build_command":"npx --no-install electron-builder --config electron-builder.yml --linux --publish never"}]}' | |
| ;; | |
| esac | |
| echo "matrix=$matrix" >> "$GITHUB_OUTPUT" | |
| build: | |
| needs: resolve-matrix | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJSON(needs.resolve-matrix.outputs.matrix) }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Compute dependency cache key | |
| id: dep-cache-key | |
| shell: bash | |
| run: | | |
| hash=$(node -e "const crypto = require('crypto'); const fs = require('fs'); const lock = JSON.parse(fs.readFileSync('package-lock.json', 'utf8')); const normalizedPackages = Object.fromEntries(Object.entries(lock.packages || {}).map(([name, pkg]) => [name, { version: pkg.version, resolved: pkg.resolved, integrity: pkg.integrity, dependencies: pkg.dependencies, optionalDependencies: pkg.optionalDependencies, cpu: pkg.cpu, os: pkg.os, engines: pkg.engines, hasInstallScript: pkg.hasInstallScript }])); const normalizedLock = { lockfileVersion: lock.lockfileVersion, requires: lock.requires, packages: normalizedPackages, dependencies: lock.dependencies }; process.stdout.write(crypto.createHash('sha256').update(JSON.stringify(normalizedLock)).digest('hex'));") | |
| echo "value=$hash" >> "$GITHUB_OUTPUT" | |
| - name: Get npm cache directory | |
| shell: bash | |
| id: npm-cache-dir | |
| run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT" | |
| - name: Cache npm cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ steps.npm-cache-dir.outputs.dir }} | |
| key: ${{ runner.os }}-npm-${{ env.NODE_VERSION }}-${{ steps.dep-cache-key.outputs.value }} | |
| restore-keys: | | |
| ${{ runner.os }}-npm-${{ env.NODE_VERSION }}- | |
| - name: Cache Electron binaries (Windows) | |
| if: matrix.platform == 'windows' | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~\AppData\Local\electron\Cache | |
| ~\AppData\Local\electron-builder\Cache | |
| key: ${{ runner.os }}-electron-${{ steps.dep-cache-key.outputs.value }} | |
| restore-keys: | | |
| ${{ runner.os }}-electron- | |
| - name: Cache Electron binaries (Unix) | |
| if: matrix.platform != 'windows' | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cache/electron | |
| ~/.cache/electron-builder | |
| ~/Library/Caches/electron | |
| ~/Library/Caches/electron-builder | |
| key: ${{ runner.os }}-electron-${{ steps.dep-cache-key.outputs.value }} | |
| restore-keys: | | |
| ${{ runner.os }}-electron- | |
| - name: Cache node-gyp (Windows) | |
| if: matrix.platform == 'windows' | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~\AppData\Local\node-gyp | |
| key: ${{ runner.os }}-node-gyp-${{ env.NODE_VERSION }} | |
| restore-keys: | | |
| ${{ runner.os }}-node-gyp- | |
| - name: Install dependencies | |
| shell: bash | |
| run: | | |
| install_ok=true | |
| if ! npm ci --include=dev --prefer-offline --no-audit --ignore-scripts; then | |
| install_ok=false | |
| fi | |
| if [ "$install_ok" != "true" ] || [ ! -f node_modules/electron/package.json ] || [ ! -f node_modules/electron-builder/package.json ]; then | |
| echo "Build dependencies missing after npm ci, retrying once" | |
| rm -rf node_modules | |
| npm ci --include=dev --no-audit --ignore-scripts | |
| fi | |
| env: | |
| npm_config_fund: false | |
| npm_config_loglevel: warn | |
| npm_config_progress: false | |
| - name: Verify build dependencies | |
| shell: bash | |
| run: | | |
| test -f node_modules/electron/package.json | |
| test -f node_modules/electron-builder/package.json | |
| - name: Prepare bundled platform-tools | |
| run: npm run prepare:platform-tools | |
| - name: Build Electron app | |
| run: ${{ matrix.build_command }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| CSC_IDENTITY_AUTO_DISCOVERY: false | |
| - name: Upload artifacts (Windows) | |
| if: matrix.platform == 'windows' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-build | |
| path: | | |
| dist/*.exe | |
| dist/*.zip | |
| retention-days: 14 | |
| compression-level: 0 | |
| if-no-files-found: ignore | |
| - name: Upload artifacts (macOS) | |
| if: matrix.platform == 'macos' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: macos-build | |
| path: | | |
| dist/*.dmg | |
| dist/*.zip | |
| retention-days: 14 | |
| compression-level: 0 | |
| if-no-files-found: ignore | |
| - name: Upload artifacts (Linux) | |
| if: matrix.platform == 'linux' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-build | |
| path: | | |
| dist/*.AppImage | |
| dist/*.deb | |
| dist/*.zip | |
| retention-days: 14 | |
| compression-level: 0 | |
| if-no-files-found: ignore | |
| release: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: false | |
| - name: List artifacts | |
| run: find artifacts -type f | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| files: | | |
| artifacts/**/* | |
| generate_release_notes: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |