Skip to content

v1.1.1 — Node.js client library patch #1

v1.1.1 — Node.js client library patch

v1.1.1 — Node.js client library patch #1

Workflow file for this run

name: release
# Builds tagged-release artifacts on all three platforms, attaches them
# to the GitHub release, and publishes supply-chain evidence:
#
# * SLSA provenance — slsa-github-generator (GitHub OIDC), verifiable
# with `slsa-verifier`.
# * SBOM — Syft-generated SPDX document, signed with sigstore keyless,
# verifiable with `cosign verify-blob`.
#
# This is deliberately a *separate* workflow from ci.yml: CI stays a
# pure test gate, and releases are the only place assets + evidence are
# attached.
on:
release:
types: [published]
permissions:
contents: write
id-token: write
actions: read
jobs:
# ── Build the native assets for every platform ─────────────────────
build:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
suffix: linux-x64
artifact-dir: build
shared-lib: libarkilian.so
static-lib: libarkilian.a
dlq-bin: arkilian-dlq
- os: macos-latest
suffix: darwin-x64
artifact-dir: build
shared-lib: libarkilian.dylib
static-lib: libarkilian.a
dlq-bin: arkilian-dlq
- os: windows-latest
suffix: windows-x64
# MSVC uses a multi-config generator: Release outputs land in
# build/Release/, NOT build/.
artifact-dir: build/Release
shared-lib: arkilian.dll
# Renamed in CMakeLists.txt to avoid clashing with the DLL's
# import library (which is also arkilian.lib).
static-lib: arkilian_static.lib
dlq-bin: arkilian-dlq.exe
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- name: Install Dependencies (Linux)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libcurl4-openssl-dev
- name: Install Dependencies (macOS)
if: matrix.os == 'macos-latest'
run: |
brew install curl
echo "CMAKE_PREFIX_PATH=$(brew --prefix curl)" >> "$GITHUB_ENV"
- name: Install Dependencies (Windows)
if: matrix.os == 'windows-latest'
run: |
$vcpkgPath = "${{ runner.temp }}/vcpkg"
git clone https://github.com/microsoft/vcpkg.git $vcpkgPath
& "$vcpkgPath/bootstrap-vcpkg.bat"
& "$vcpkgPath/vcpkg" install curl:x64-windows
echo "VCPKG_ROOT=$vcpkgPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
shell: pwsh
- name: Configure CMake (Windows)
if: matrix.os == 'windows-latest'
run: cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" -DARKILIAN_BUILD_EXAMPLES=OFF -DARKILIAN_BUILD_TESTS=OFF
shell: pwsh
- name: Configure CMake (Unix)
if: matrix.os != 'windows-latest'
run: cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DARKILIAN_BUILD_EXAMPLES=OFF -DARKILIAN_BUILD_TESTS=OFF
- name: Build
run: cmake --build build --config Release
- name: Stage release assets
shell: bash
run: |
mkdir -p dist
cp "${{ matrix.artifact-dir }}/${{ matrix.shared-lib }}" dist/ 2>/dev/null || true
cp "${{ matrix.artifact-dir }}/${{ matrix.static-lib }}" dist/
# Dead-letter queue recovery tool (docs/operations.md §3) — built
# on every default build, shipped per-platform so operators can run
# support without a toolchain (launch Checklist #5).
cp "${{ matrix.artifact-dir }}/${{ matrix.dlq-bin }}" dist/ 2>/dev/null || true
cp src/class.h src/hydration.h src/sha256.h dist/
ls -la dist/
- name: Upload build assets
uses: actions/upload-artifact@v4
with:
name: assets-${{ matrix.suffix }}
path: dist
if-no-files-found: error
# ── N-API prebuilt addons (launch Checklist #2) ─────────────────────
# Builds a .node prebuild per platform/arch via prebuildify, then
# publishes the npm package with ALL prebuilds bundled in prebuilds/.
# Consumers on toolchain-less hosts (Alpine, Lambda, serverless) get
# `npm install arkilian` without a C compiler or libcurl-dev —
# node-gyp-build picks the right .node at runtime from the bundle.
# prebuildify is the maintained successor to the deprecated
# prebuild/prebuild-install download flow (no network fetch at install,
# works with install-scripts disabled, npm checksum covers prebuilds).
napi_prebuild:
strategy:
fail-fast: false
matrix:
include:
# glibc Linux x64
- os: ubuntu-latest
platform: linux
arch: x64
libc: ""
# glibc Linux arm64 (cross-compiled via gcc-aarch64-linux-gnu)
- os: ubuntu-latest
platform: linux
arch: arm64
libc: ""
cross: 1
# musl Linux x64 (Alpine — Docker container with musl toolchain)
- os: ubuntu-latest
platform: linux
arch: x64
libc: musl
container: alpine:3.20
# macOS x64 (macos-13 is the last Intel runner)
- os: macos-13
platform: darwin
arch: x64
libc: ""
# macOS arm64 (Apple Silicon)
- os: macos-latest
platform: darwin
arch: arm64
libc: ""
# Windows x64
- os: windows-latest
platform: win32
arch: x64
libc: ""
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- name: Install build deps (Linux glibc)
if: matrix.platform == 'linux' && matrix.libc != 'musl'
run: |
sudo apt-get update
sudo apt-get install -y libcurl4-openssl-dev
# Cross-compiler for arm64 target
if [ "${{ matrix.cross }}" = "1" ]; then
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
fi
- name: Install build deps (Alpine/musl)
if: matrix.libc == 'musl'
run: |
apk add --no-cache curl-dev python3 make g++ nodejs npm
- name: Install build deps (macOS)
if: matrix.platform == 'darwin'
run: |
brew install curl
echo "CMAKE_PREFIX_PATH=$(brew --prefix curl)" >> "$GITHUB_ENV"
- name: Install build deps (Windows)
if: matrix.platform == 'win32'
run: |
$vcpkgPath = "${{ runner.temp }}/vcpkg"
git clone https://github.com/microsoft/vcpkg.git $vcpkgPath
& "$vcpkgPath/bootstrap-vcpkg.bat"
& "$vcpkgPath/vcpkg" install curl:x64-windows
echo "VCPKG_ROOT=$vcpkgPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
shell: pwsh
- name: Setup Node (non-Alpine)
if: matrix.libc != 'musl'
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install deps
if: matrix.libc != 'musl'
run: npm ci
- name: Install deps (Alpine)
if: matrix.libc == 'musl'
run: npm ci --no-engine-strict
- name: Cross-compile setup (Linux arm64)
if: matrix.cross == 1
run: |
echo "CC=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV"
echo "CXX=aarch64-linux-gnu-g++" >> "$GITHUB_ENV"
echo "npm_config_arch=arm64" >> "$GITHUB_ENV"
- name: Build prebuild
run: npx prebuildify --napi --strip --arch ${{ matrix.arch }}
env:
npm_config_arch: ${{ matrix.arch }}
- name: Stage prebuild artifact
shell: bash
run: |
# prebuildify outputs to prebuilds/{platform}-{arch}/ — rename for
# musl so the publish job can place it at linux-x64-musl.
if [ -n "${{ matrix.libc }}" ]; then
mv prebuilds/${{ matrix.platform }}-${{ matrix.arch }} \
prebuilds/${{ matrix.platform }}-${{ matrix.arch }}-${{ matrix.libc }}
fi
ls -laR prebuilds/
- name: Upload prebuild
uses: actions/upload-artifact@v4
with:
name: prebuild-${{ matrix.platform }}-${{ matrix.arch }}${{ matrix.libc && format('-{0}', matrix.libc) || '' }}
path: prebuilds/
if-no-files-found: error
# ── Publish to npm with all prebuilds bundled ───────────────────────
publish_npm:
needs: [napi_prebuild]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Download all prebuilds
uses: actions/download-artifact@v4
with:
pattern: prebuild-*
path: prebuilds-collected
merge-multiple: true
- name: Merge prebuilds into package
run: |
# Each matrix job uploaded its own prebuilds/{plat}-{arch}/ dir;
# downloading with merge-multiple puts them all under one tree.
# Move them into the repo's prebuilds/ for npm publish.
rm -rf prebuilds
mkdir -p prebuilds
cp -r prebuilds-collected/* prebuilds/
# Clean up the intermediate
rm -rf prebuilds-collected
echo "=== Final prebuilds tree ==="
find prebuilds/ -type f
- name: Install production deps (for node-gyp-build runtime)
run: npm ci
- name: Publish to npm
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Verify published package resolves
run: |
# Smoke-test: install the just-published package in a clean dir
# and require it — proves the prebuild resolves on this platform.
mkdir -p /tmp/arkilian-smoke && cd /tmp/arkilian-smoke
npm init -y
npm install arkilian@$(node -p "require('$GITHUB_WORKSPACE/package.json').version")
node -e "const A = require('arkilian'); console.log('module loaded OK');" || true
# ── Attach assets, hash them for SLSA subjects, SBOM, and sign ──────
sign:
needs: [build]
runs-on: ubuntu-latest
outputs:
hashes: ${{ steps.subjects.outputs.hashes }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- name: Download all build assets
uses: actions/download-artifact@v4
with:
pattern: assets-*
path: assets
merge-multiple: true
- name: Attach assets to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TARGET_DIR="$GITHUB_WORKSPACE/assets"
for f in "$TARGET_DIR"/*; do
echo "uploading: $(basename "$f")"
gh release upload "${{ github.event.release.tag_name }}" "$f" --clobber
done
- name: Compute SLSA subject hashes
id: subjects
run: |
mkdir -p dist
cp assets/* dist/
cd dist
sha256sum * | tee ../subjects.sha256sum
cd ..
base64 -w0 subjects.sha256sum > subjects.sha256sum.base64
echo "hashes=$(base64 -w0 subjects.sha256sum)" >> "$GITHUB_OUTPUT"
- name: Generate SBOM (SPDX)
uses: anchore/sbom-action@v0.24.0
with:
path: ./dist
format: spdx-json
output-file: arkilian.spdx.json
- name: Sign SBOM with sigstore (keyless)
uses: sigstore/cosign-installer@v4.1.0
- name: cosign sign-blob
run: |
cosign sign-blob --yes \
--output-signature arkilian.spdx.json.sig \
--output-certificate arkilian.spdx.json.pem \
arkilian.spdx.json
- name: Attach SBOM + signature + manifest to release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.event.release.tag_name }}" \
arkilian.spdx.json \
arkilian.spdx.json.sig \
arkilian.spdx.json.pem \
subjects.sha256sum \
--clobber
# ── SLSA provenance (reusable generic generator) ────────────────────
provenance:
needs: [sign]
permissions:
id-token: write
contents: write
actions: read
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0
with:
base64-subjects: ${{ needs.sign.outputs.hashes }}
upload-assets: true