Skip to content
Latchkey

build workflow (WiseLibs/better-sqlite3)

The build workflow from WiseLibs/better-sqlite3, explained and optimized by Latchkey.

F

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.

Grade your own workflow free or run it on Latchkey →
Source: WiseLibs/better-sqlite3.github/workflows/build.ymlLicense MITView source

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

workflow (.yml)
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

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:

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.

Actions used in this workflow