v1.4.0 — restore path end-to-end (this is the launch release) #4
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |