HakobuHakobu

CI/CD Integration

Automate cross-platform builds with GitHub Actions and other CI systems.

Overview

Hakobu is designed to work seamlessly in CI/CD pipelines. This guide covers GitHub Actions workflows for building, signing, and releasing cross-platform executables.

GitHub Actions Matrix Build

The recommended approach uses a matrix strategy to build each platform on its native runner:

.github/workflows/release.yml
name: Build & Release

on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: node24-linux-x64
            os: ubuntu-latest
          - target: node24-linux-arm64
            os: ubuntu-24.04-arm
          - target: node24-win-x64
            os: windows-latest
          - target: node24-macos-arm64
            os: macos-latest
          - target: node24-macos-x64
            os: macos-13

    runs-on: ${{ matrix.os }}

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '24'

      - name: Install dependencies
        run: npm ci

      - name: Build executable
        run: npx hakobu . --target ${{ matrix.target }} --output ./dist/

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: build-${{ matrix.target }}
          path: ./dist/*

Use fail-fast: false so that a failure on one platform does not cancel builds for the other platforms.

Caching Base Binaries

Hakobu downloads patched Node.js base binaries on first use and caches them in ~/.hakobu/cache/. Cache this directory to speed up subsequent builds:

.github/workflows/release.yml
- name: Cache Hakobu base binaries
  uses: actions/cache@v4
  with:
    path: ~/.hakobu/cache
    key: hakobu-base-${{ matrix.target }}-${{ hashFiles('package-lock.json') }}
    restore-keys: |
      hakobu-base-${{ matrix.target }}-

The cache path is configurable via the HAKOBU_CACHE_PATH environment variable if ~/.hakobu/cache does not suit your CI setup.

Adding Code Signing

Extend the matrix workflow to sign executables on each platform.

macOS signing and notarization

.github/workflows/release.yml
- name: Install signing certificate
  if: runner.os == 'macOS'
  env:
    P12_BASE64: ${{ secrets.APPLE_DEVELOPER_ID_P12 }}
    P12_PASSWORD: ${{ secrets.APPLE_DEVELOPER_ID_PASSWORD }}
  run: |
    echo "$P12_BASE64" | base64 --decode > cert.p12
    security create-keychain -p "" build.keychain
    security default-keychain -s build.keychain
    security unlock-keychain -p "" build.keychain
    security import cert.p12 -k build.keychain -P "$P12_PASSWORD" -T /usr/bin/codesign
    security set-key-partition-list -S apple-tool:,apple: -s -k "" build.keychain
    rm cert.p12

- name: Build executable (macOS)
  if: runner.os == 'macOS'
  env:
    HAKOBU_SIGN_IDENTITY: ${{ secrets.APPLE_SIGN_IDENTITY }}
    HAKOBU_APPLE_ID: ${{ secrets.APPLE_ID }}
    HAKOBU_APPLE_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
    HAKOBU_APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
  run: npx hakobu . --target ${{ matrix.target }} --output ./dist/ --notarize

Windows Authenticode signing

.github/workflows/release.yml
- name: Decode signing certificate
  if: runner.os == 'Windows'
  run: |
    echo "${{ secrets.WIN_CERT_BASE64 }}" > cert-base64.txt
    certutil -decode cert-base64.txt cert.pfx
    del cert-base64.txt
  shell: cmd

- name: Build executable (Windows)
  if: runner.os == 'Windows'
  env:
    HAKOBU_WIN_CERT: cert.pfx
    HAKOBU_WIN_CERT_PASSWORD: ${{ secrets.WIN_CERT_PASSWORD }}
  run: npx hakobu . --target ${{ matrix.target }} --output ./dist/

- name: Clean up certificate
  if: always() && runner.os == 'Windows'
  run: del cert.pfx
  shell: cmd

Creating a Release

Add a job that collects all build artifacts and creates a GitHub Release:

.github/workflows/release.yml
release:
  needs: build
  runs-on: ubuntu-latest
  permissions:
    contents: write

  steps:
    - name: Download all artifacts
      uses: actions/download-artifact@v4
      with:
        path: ./artifacts
        merge-multiple: true

    - name: Generate checksums
      run: |
        cd artifacts
        sha256sum * > CHECKSUMS.sha256

    - name: Create GitHub Release
      uses: softprops/action-gh-release@v2
      with:
        files: ./artifacts/*
        generate_release_notes: true

Complete Workflow

Here is the full workflow combining all steps -- matrix builds, caching, signing, and release creation:

Configure repository secrets

Add these secrets in your repository settings (Settings, then Secrets and variables, then Actions):

SecretPurpose
APPLE_DEVELOPER_ID_P12Base64-encoded .p12 certificate
APPLE_DEVELOPER_ID_PASSWORDPassword for the .p12
APPLE_SIGN_IDENTITYSigning identity string
APPLE_IDApple ID email
APPLE_APP_SPECIFIC_PASSWORDApp-specific password
APPLE_TEAM_IDApple Developer Team ID
WIN_CERT_BASE64Base64-encoded .pfx certificate
WIN_CERT_PASSWORDPFX password

Create the workflow file

Create .github/workflows/release.yml with the matrix build, signing steps, and release job shown in the sections above.

Tag a release

Push a version tag to trigger the workflow:

git tag v1.0.0
git push origin v1.0.0

The workflow builds executables for all platforms, signs them, generates checksums, and publishes a GitHub Release with all artifacts.

Cross-Platform Builds from a Single Runner

If you prefer not to use a matrix strategy, Hakobu can build for all platforms from a single machine:

.github/workflows/release.yml
- name: Build all targets
  run: npx hakobu . --target all --output ./dist/

Cross-platform builds from a single runner cannot natively sign executables for other platforms. macOS notarization requires a macOS runner, and Windows signtool requires a Windows runner. Use osslsigncode on Linux/macOS for cross-signing Windows binaries.

Other CI Systems

The same principles apply to any CI system. The key requirements are:

  1. Node.js 24.x available on the runner
  2. Hakobu installed as a dev dependency or via npx
  3. Base binary cache persisted between builds for speed
  4. Signing credentials stored securely and available as environment variables
  5. Platform-specific runners for native signing (macOS notarization, Windows signtool)

For example, in GitLab CI:

.gitlab-ci.yml
build:linux:
  image: node:24
  script:
    - npm ci
    - npx hakobu . --target node24-linux-x64 --output ./dist/
  artifacts:
    paths:
      - dist/
  cache:
    key: hakobu-linux
    paths:
      - ~/.hakobu/cache/

On this page