build workflow (WiseLibs/better-sqlite3)
The build workflow from WiseLibs/better-sqlite3, explained and optimized by Latchkey.
CI health: F - at risk
Point runs-on at Latchkey and get caching, run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the build workflow from the WiseLibs/better-sqlite3 repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: build
on:
push:
branches:
- master
pull_request:
branches:
- master
release:
types:
- released
workflow_dispatch: {}
env:
# See https://github.com/nodejs/release#release-schedule
# Node.js v22 EOL = 2027-04-30. v24 EOL = 2028-04-30.
# Node.js 22-24 can build with GCC 10 (bullseye)
NODE_BUILD_CMD_LEGACY: npx --no-install prebuild -r node -t 22.0.0 -t 24.0.0 --include-regex 'better_sqlite3.node$'
# Node.js v25 EOL = 2026-06-01. v26 EOL = 2029-04-30.
# Node.js 25+ requires GCC 11+ for <source_location> header (bookworm)
NODE_BUILD_CMD_MODERN: npx --no-install prebuild -r node -t 25.0.0 -t 26.0.0 --include-regex 'better_sqlite3.node$'
# See https://www.electronjs.org/docs/latest/tutorial/electron-timelines#version-support-policy
# Electron v29 EOL = 2024-08-20. v30 EOL = 2024-10-15. v31 EOL = 2025-01-14. v32 EOL = 2025-03-11. v33 EOL = 2025-05-13. v34 EOL = 2025-06-24. v35 EOL = 2025-09-02. v36 EOL = 2025-10-28. v37 EOL = 2026-01-13. v38 EOL = 2026-03-10.
# Electron 29-38 can build with GCC 10 (bullseye)
ELECTRON_BUILD_CMD_LEGACY: npx --no-install prebuild -r electron -t 29.0.0 -t 30.0.0 -t 31.0.0 -t 32.0.0 -t 33.0.0 -t 34.0.0 -t 35.0.0 -t 36.0.0 -t 37.0.0 -t 38.0.0 --include-regex 'better_sqlite3.node$'
# Electron v39 EOL = 2026-05-05. v40 EOL = 2026-06-30. v41 EOL = 2026-08-25. v42 EOL = 2026-09-22.
# Electron 39+ requires GCC 11+ for <source_location> header (bookworm).
ELECTRON_BUILD_CMD_MODERN: npx --no-install prebuild -r electron -t 39.0.0 -t 40.0.0 -t 41.0.0 -t 42.3.0 -t 43.0.0 --include-regex 'better_sqlite3.node$'
jobs:
test:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-22.04
- macos-15
- macos-15-intel
- windows-2022
node:
- 22
- 24
- 25
- 26
name: Testing Node ${{ matrix.node }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
- if: ${{ startsWith(matrix.os, 'windows') }}
run: pip.exe install setuptools
- if: ${{ startsWith(matrix.os, 'macos') }}
run: brew install python-setuptools
- if: ${{ !startsWith(matrix.os, 'windows') && !startsWith(matrix.os, 'macos') }}
run: python3 -m pip install setuptools
- if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.node < 25 }}
run: |
sudo apt update
sudo apt install gcc-10 g++-10 -y
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10
- if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.node >= 25 }}
run: |
sudo apt update
sudo apt install gcc-11 g++-11 -y
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100 --slave /usr/bin/g++ g++ /usr/bin/g++-11 --slave /usr/bin/gcov gcov /usr/bin/gcov-11
- run: npm install --ignore-scripts
- run: npm run build-debug
- run: npm test
- name: Test SpatiaLite extension
if: ${{ startsWith(matrix.os, 'ubuntu') }}
run: |
sudo apt update
sudo apt install libsqlite3-mod-spatialite -y
node -e "require('./lib/index.js')(':memory:').loadExtension('mod_spatialite').exec('SELECT InitSpatialMetaData();')"
publish:
if: ${{ github.event_name == 'release' }}
name: Publishing to NPM
runs-on: ubuntu-22.04
permissions:
id-token: write # Required for OIDC trusted publishing
contents: read
needs:
- prebuild
- prebuild-alpine
- prebuild-alpine-arm
- prebuild-linux-x64
- prebuild-linux-arm
- prebuild-linux-x64-node-modern
- prebuild-linux-x64-electron-modern
- prebuild-linux-arm-node-modern
- prebuild-linux-arm64-electron-modern
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 20
registry-url: https://registry.npmjs.org
- name: Upgrade npm for OIDC support
run: npm install -g npm@latest
- run: npm publish --provenance
prebuild:
if: ${{ github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
os:
- macos-15
- macos-15-intel
- windows-2022
name: Prebuild on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
needs: test
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 20
- if: ${{ startsWith(matrix.os, 'windows') }}
run: pip.exe install setuptools
- if: ${{ startsWith(matrix.os, 'macos') }}
run: brew install python-setuptools
- run: npm install --ignore-scripts
- run: ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }}
- run: ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}
- run: ${{ env.ELECTRON_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }}
- run: ${{ env.ELECTRON_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}
- if: matrix.os == 'windows-2022'
run: |
${{ env.NODE_BUILD_CMD_LEGACY }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }}
${{ env.NODE_BUILD_CMD_MODERN }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }}
${{ env.NODE_BUILD_CMD_LEGACY }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}
${{ env.NODE_BUILD_CMD_MODERN }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}
${{ env.ELECTRON_BUILD_CMD_LEGACY }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }}
${{ env.ELECTRON_BUILD_CMD_MODERN }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }}
${{ env.ELECTRON_BUILD_CMD_LEGACY }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}
${{ env.ELECTRON_BUILD_CMD_MODERN }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}
prebuild-linux-x64:
if: ${{ github.event_name == 'release' }}
name: Prebuild on Linux x64
runs-on: ubuntu-latest
container: node:20-bullseye
needs: test
steps:
- uses: actions/checkout@v6
- run: npm install --ignore-scripts
- run: ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }}
- run: ${{ env.ELECTRON_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }}
prebuild-linux-x64-node-modern:
if: ${{ github.event_name == 'release' }}
name: Prebuild on Linux x64 (Node 25+)
runs-on: ubuntu-latest
container: node:20-bookworm
needs: test
steps:
- uses: actions/checkout@v6
- run: npm install --ignore-scripts
- run: ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}
prebuild-linux-x64-electron-modern:
if: ${{ github.event_name == 'release' }}
name: Prebuild on Linux x64 (Electron 39+)
runs-on: ubuntu-latest
container: node:20-bookworm
needs: test
steps:
- uses: actions/checkout@v6
- run: npm install --ignore-scripts
- run: ${{ env.ELECTRON_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}
prebuild-alpine:
if: ${{ github.event_name == 'release' }}
name: Prebuild on alpine
runs-on: ubuntu-latest
container: node:20-alpine
needs: test
steps:
- uses: actions/checkout@v6
- run: apk add build-base git python3 py3-setuptools --update-cache
- run: npm install --ignore-scripts
- run: ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }}
- run: ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}
prebuild-alpine-arm:
if: ${{ github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
arch:
- arm/v7
- arm64
name: Prebuild on alpine (${{ matrix.arch }})
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v6
- uses: docker/setup-qemu-action@v4
- run: |
docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:20-alpine -c "\
apk add build-base git python3 py3-setuptools --update-cache && \
cd /tmp/project && \
npm install --ignore-scripts && \
${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} && \
${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}"
prebuild-linux-arm:
if: ${{ github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
arch:
- arm/v7
- arm64
name: Prebuild on Linux (${{ matrix.arch }})
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v6
- uses: docker/setup-qemu-action@v4
- run: |
docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:20-bullseye -c "\
cd /tmp/project && \
npm install --ignore-scripts && \
${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} && \
if [ '${{ matrix.arch }}' = 'arm64' ]; then ${{ env.ELECTRON_BUILD_CMD_LEGACY }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}; fi"
prebuild-linux-arm-node-modern:
if: ${{ github.event_name == 'release' }}
strategy:
fail-fast: false
matrix:
arch:
- arm/v7
- arm64
name: Prebuild on Linux (${{ matrix.arch }}) (Node 25+)
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v6
- uses: docker/setup-qemu-action@v4
- run: |
docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:20-bookworm -c "\
cd /tmp/project && \
npm install --ignore-scripts && \
${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}"
prebuild-linux-arm64-electron-modern:
if: ${{ github.event_name == 'release' }}
name: Prebuild on Linux arm64 (Electron 39+)
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v6
- uses: docker/setup-qemu-action@v4
- run: |
docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/arm64 node:20-bookworm -c "\
cd /tmp/project && \
npm install --ignore-scripts && \
${{ env.ELECTRON_BUILD_CMD_MODERN }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}"
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: build on: push: branches: - master pull_request: branches: - master release: types: - released workflow_dispatch: {} env: # See https://github.com/nodejs/release#release-schedule # Node.js v22 EOL = 2027-04-30. v24 EOL = 2028-04-30. # Node.js 22-24 can build with GCC 10 (bullseye) NODE_BUILD_CMD_LEGACY: npx --no-install prebuild -r node -t 22.0.0 -t 24.0.0 --include-regex 'better_sqlite3.node$' # Node.js v25 EOL = 2026-06-01. v26 EOL = 2029-04-30. # Node.js 25+ requires GCC 11+ for <source_location> header (bookworm) NODE_BUILD_CMD_MODERN: npx --no-install prebuild -r node -t 25.0.0 -t 26.0.0 --include-regex 'better_sqlite3.node$' # See https://www.electronjs.org/docs/latest/tutorial/electron-timelines#version-support-policy # Electron v29 EOL = 2024-08-20. v30 EOL = 2024-10-15. v31 EOL = 2025-01-14. v32 EOL = 2025-03-11. v33 EOL = 2025-05-13. v34 EOL = 2025-06-24. v35 EOL = 2025-09-02. v36 EOL = 2025-10-28. v37 EOL = 2026-01-13. v38 EOL = 2026-03-10. # Electron 29-38 can build with GCC 10 (bullseye) ELECTRON_BUILD_CMD_LEGACY: npx --no-install prebuild -r electron -t 29.0.0 -t 30.0.0 -t 31.0.0 -t 32.0.0 -t 33.0.0 -t 34.0.0 -t 35.0.0 -t 36.0.0 -t 37.0.0 -t 38.0.0 --include-regex 'better_sqlite3.node$' # Electron v39 EOL = 2026-05-05. v40 EOL = 2026-06-30. v41 EOL = 2026-08-25. v42 EOL = 2026-09-22. # Electron 39+ requires GCC 11+ for <source_location> header (bookworm). ELECTRON_BUILD_CMD_MODERN: npx --no-install prebuild -r electron -t 39.0.0 -t 40.0.0 -t 41.0.0 -t 42.3.0 -t 43.0.0 --include-regex 'better_sqlite3.node$' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: timeout-minutes: 30 strategy: fail-fast: false matrix: os: - ubuntu-22.04 - macos-15 - macos-15-intel - windows-2022 node: - 22 - 24 - 25 - 26 name: Testing Node ${{ matrix.node }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: cache: 'npm' node-version: ${{ matrix.node }} - if: ${{ startsWith(matrix.os, 'windows') }} run: pip.exe install setuptools - if: ${{ startsWith(matrix.os, 'macos') }} run: brew install python-setuptools - if: ${{ !startsWith(matrix.os, 'windows') && !startsWith(matrix.os, 'macos') }} run: python3 -m pip install setuptools - if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.node < 25 }} run: | sudo apt update sudo apt install gcc-10 g++-10 -y sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10 - if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.node >= 25 }} run: | sudo apt update sudo apt install gcc-11 g++-11 -y sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 100 --slave /usr/bin/g++ g++ /usr/bin/g++-11 --slave /usr/bin/gcov gcov /usr/bin/gcov-11 - run: npm install --ignore-scripts - run: npm run build-debug - run: npm test - name: Test SpatiaLite extension if: ${{ startsWith(matrix.os, 'ubuntu') }} run: | sudo apt update sudo apt install libsqlite3-mod-spatialite -y node -e "require('./lib/index.js')(':memory:').loadExtension('mod_spatialite').exec('SELECT InitSpatialMetaData();')" publish: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} name: Publishing to NPM runs-on: latchkey-small permissions: id-token: write # Required for OIDC trusted publishing contents: read needs: - prebuild - prebuild-alpine - prebuild-alpine-arm - prebuild-linux-x64 - prebuild-linux-arm - prebuild-linux-x64-node-modern - prebuild-linux-x64-electron-modern - prebuild-linux-arm-node-modern - prebuild-linux-arm64-electron-modern steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: cache: 'npm' node-version: 20 registry-url: https://registry.npmjs.org - name: Upgrade npm for OIDC support run: npm install -g npm@latest - run: npm publish --provenance prebuild: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} strategy: fail-fast: false matrix: os: - macos-15 - macos-15-intel - windows-2022 name: Prebuild on ${{ matrix.os }} runs-on: ${{ matrix.os }} needs: test steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: cache: 'npm' node-version: 20 - if: ${{ startsWith(matrix.os, 'windows') }} run: pip.exe install setuptools - if: ${{ startsWith(matrix.os, 'macos') }} run: brew install python-setuptools - run: npm install --ignore-scripts - run: ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} - run: ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }} - run: ${{ env.ELECTRON_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} - run: ${{ env.ELECTRON_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }} - if: matrix.os == 'windows-2022' run: | ${{ env.NODE_BUILD_CMD_LEGACY }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }} ${{ env.NODE_BUILD_CMD_MODERN }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }} ${{ env.NODE_BUILD_CMD_LEGACY }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }} ${{ env.NODE_BUILD_CMD_MODERN }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }} ${{ env.ELECTRON_BUILD_CMD_LEGACY }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }} ${{ env.ELECTRON_BUILD_CMD_MODERN }} --arch ia32 -u ${{ secrets.GITHUB_TOKEN }} ${{ env.ELECTRON_BUILD_CMD_LEGACY }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }} ${{ env.ELECTRON_BUILD_CMD_MODERN }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }} prebuild-linux-x64: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} name: Prebuild on Linux x64 runs-on: latchkey-small container: node:20-bullseye needs: test steps: - uses: actions/checkout@v6 - run: npm install --ignore-scripts - run: ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} - run: ${{ env.ELECTRON_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} prebuild-linux-x64-node-modern: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} name: Prebuild on Linux x64 (Node 25+) runs-on: latchkey-small container: node:20-bookworm needs: test steps: - uses: actions/checkout@v6 - run: npm install --ignore-scripts - run: ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }} prebuild-linux-x64-electron-modern: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} name: Prebuild on Linux x64 (Electron 39+) runs-on: latchkey-small container: node:20-bookworm needs: test steps: - uses: actions/checkout@v6 - run: npm install --ignore-scripts - run: ${{ env.ELECTRON_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }} prebuild-alpine: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} name: Prebuild on alpine runs-on: latchkey-small container: node:20-alpine needs: test steps: - uses: actions/checkout@v6 - run: apk add build-base git python3 py3-setuptools --update-cache - run: npm install --ignore-scripts - run: ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} - run: ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }} prebuild-alpine-arm: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} strategy: fail-fast: false matrix: arch: - arm/v7 - arm64 name: Prebuild on alpine (${{ matrix.arch }}) runs-on: latchkey-small needs: test steps: - uses: actions/checkout@v6 - uses: docker/setup-qemu-action@v4 - run: | docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:20-alpine -c "\ apk add build-base git python3 py3-setuptools --update-cache && \ cd /tmp/project && \ npm install --ignore-scripts && \ ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} && \ ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}" prebuild-linux-arm: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} strategy: fail-fast: false matrix: arch: - arm/v7 - arm64 name: Prebuild on Linux (${{ matrix.arch }}) runs-on: latchkey-small needs: test steps: - uses: actions/checkout@v6 - uses: docker/setup-qemu-action@v4 - run: | docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:20-bullseye -c "\ cd /tmp/project && \ npm install --ignore-scripts && \ ${{ env.NODE_BUILD_CMD_LEGACY }} -u ${{ secrets.GITHUB_TOKEN }} && \ if [ '${{ matrix.arch }}' = 'arm64' ]; then ${{ env.ELECTRON_BUILD_CMD_LEGACY }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}; fi" prebuild-linux-arm-node-modern: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} strategy: fail-fast: false matrix: arch: - arm/v7 - arm64 name: Prebuild on Linux (${{ matrix.arch }}) (Node 25+) runs-on: latchkey-small needs: test steps: - uses: actions/checkout@v6 - uses: docker/setup-qemu-action@v4 - run: | docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/${{ matrix.arch }} node:20-bookworm -c "\ cd /tmp/project && \ npm install --ignore-scripts && \ ${{ env.NODE_BUILD_CMD_MODERN }} -u ${{ secrets.GITHUB_TOKEN }}" prebuild-linux-arm64-electron-modern: timeout-minutes: 30 if: ${{ github.event_name == 'release' }} name: Prebuild on Linux arm64 (Electron 39+) runs-on: latchkey-small needs: test steps: - uses: actions/checkout@v6 - uses: docker/setup-qemu-action@v4 - run: | docker run --rm -v $(pwd):/tmp/project --entrypoint /bin/sh --platform linux/arm64 node:20-bookworm -c "\ cd /tmp/project && \ npm install --ignore-scripts && \ ${{ env.ELECTRON_BUILD_CMD_MODERN }} --arch arm64 -u ${{ secrets.GITHUB_TOKEN }}"
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
This workflow runs 11 jobs (31 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.