Skip to content

Build and Release

Build and Release #68

Workflow file for this run

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 }}