Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
268 changes: 268 additions & 0 deletions .github/workflows/sdk-typescript-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
# Tag-gated publish for @codegraff/sdk to npm.
#
# Triggered by pushing a tag like sdk/typescript-v0.1.6. Rebuilds every native
# addon, assembles the per-triple npm subpackages, then publishes the lot to
# npm with provenance (signed by the GitHub OIDC token).
#
# Pre-flight (one-time, on npmjs.com):
# 1. Repo must be public for provenance to work.
# 2. Configure "Trusted Publisher" on each of these packages:
# @codegraff/sdk
# @codegraff/sdk-darwin-arm64
# @codegraff/sdk-darwin-x64
# @codegraff/sdk-linux-arm64-gnu
# @codegraff/sdk-linux-x64-gnu
# @codegraff/sdk-win32-x64-msvc
# Workflow file: .github/workflows/sdk-typescript-publish.yml.
# 3. Or add NPM_TOKEN as a repo secret as a fallback.
#
# Release flow:
# cd sdk/typescript
# npm run version # bumps main + every subpackage in lockstep
# git commit -am "release: sdk/typescript v0.1.6"
# git tag sdk/typescript-v0.1.6
# git push origin main --tags
#
# This workflow rejects the run if the tag version does not match package.json.

name: sdk-typescript-publish

on:
push:
tags:
- 'sdk/typescript-v*'

env:
RUSTFLAGS: '-Dwarnings'

defaults:
run:
working-directory: sdk/typescript

# id-token: write is required to mint the OIDC token npm verifies for provenance.
permissions:
contents: read
id-token: write

concurrency:
# Never let two publishes race on the same tag.
group: sdk-typescript-publish-${{ github.ref }}
cancel-in-progress: false

jobs:
verify-tag:
name: verify tag matches package.json
runs-on: ubuntu-latest
outputs:
version: ${{ steps.extract.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Extract version from tag and verify against package.json
id: extract
run: |
tag="${GITHUB_REF#refs/tags/sdk/typescript-v}"
pkg="$(node -p "require('./package.json').version")"
if [ "$tag" != "$pkg" ]; then
echo "::error::Tag version ($tag) does not match package.json version ($pkg)"
exit 1
fi
echo "version=$tag" >> "$GITHUB_OUTPUT"
echo "Publishing version $tag"

build:
name: build (${{ matrix.target }})
needs: verify-tag
runs-on: ${{ matrix.os }}
strategy:
# Fail the whole publish if any triple fails to build. We never want a
# partial release where only some platforms are on npm.
fail-fast: true
matrix:
include:
- target: aarch64-apple-darwin
os: macos-latest
- target: x86_64-apple-darwin
# macos-13 (Intel) runners are over-subscribed and routinely sit
# queued for an hour+. macos-latest is Apple Silicon and cross-
# compiles to x86_64-apple-darwin via the macOS SDK natively.
os: macos-latest
# NOTE: x86_64-unknown-linux-gnu intentionally NOT in this matrix.
# bare ubuntu-latest produces a .node that requires GLIBC 2.38
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 P1 — No aarch64-unknown-linux-gnu build anywhere

The pre-flight comment block (lines 12-17) lists @codegraff/sdk-linux-arm64-gnu as a subpackage requiring Trusted Publisher configuration. However, the build matrix (line 92-107) only covers aarch64-apple-darwin, x86_64-apple-darwin, and x86_64-pc-windows-msvc, and the build-linux job (line 162) only builds x86_64-unknown-linux-gnu. There is no job or matrix entry for aarch64-unknown-linux-gnu. Running this workflow as-is will publish a release that either omits the linux-arm64 subpackage entirely (stranding arm64 Linux users) or publishes it without a native .node binary, depending on napi prepublish behavior. Add the target: either add aarch64-unknown-linux-gnu as a matrix entry (if it can cross-compile from ubuntu-latest) or add a separate build-linux-arm64 job equivalent to build-linux.

# (Ubuntu 24.04 default), which fails to load on Vercel sandbox
# (GLIBC 2.34), RHEL 9, Amazon Linux 2023, etc. The build-linux
# job below runs in a debian-bullseye container (GLIBC 2.31) so
# the resulting .node is broadly compatible.
- target: x86_64-pc-windows-msvc
os: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: sdk/typescript/package-lock.json

- name: Setup protoc
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
target: ${{ matrix.target }}

- name: Cache Cargo build
uses: Swatinem/rust-cache@v2
with:
workspaces: . -> target
shared-key: sdk-typescript-${{ matrix.target }}

- name: Install npm dependencies
run: npm ci

- name: Build native addon
run: npm run build -- --target ${{ matrix.target }}

- name: Upload .node artifact
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.target }}
path: sdk/typescript/codegraff-sdk.*.node
if-no-files-found: error
retention-days: 7

build-linux:
name: build (x86_64-unknown-linux-gnu)
needs: verify-tag
runs-on: ubuntu-latest
# Debian Bullseye base = GLIBC 2.31. NATIVE compile (no cross-sysroot
# tricks) so aws-lc-sys is happy. node:20-bullseye gives us Node + a
# plain Debian Bullseye toolchain; we install Rust + protoc explicitly.
# The resulting .node loads on every Linux with GLIBC >= 2.31:
# Vercel sandbox, RHEL 9, Amazon Linux 2/2023, Debian 11+, Ubuntu 20+.
container: node:20-bullseye
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install build deps (build-essential, curl, unzip)
run: |
apt-get update
apt-get install -y --no-install-recommends \
build-essential \
pkg-config \
ca-certificates \
curl \
unzip

- name: Install protoc (release tarball, includes well-knowns)
# Debian Bullseye apt protobuf-compiler is 3.12 and doesn't ship the
# google/protobuf/*.proto well-known files where prost-build looks.
# Pull protoc 29.3 from the official release which bundles them.
run: |
PROTOC_VERSION=29.3
curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" -o /tmp/protoc.zip
unzip -o /tmp/protoc.zip -d /usr/local
chmod +x /usr/local/bin/protoc
protoc --version
ls /usr/local/include/google/protobuf/timestamp.proto

- name: Install Rust toolchain (matches rust-toolchain.toml)
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"

- name: Verify rustc + cargo
run: |
rustc --version
cargo --version

- name: Cache Cargo build
uses: Swatinem/rust-cache@v2
with:
workspaces: . -> target
shared-key: sdk-typescript-x86_64-unknown-linux-gnu

- name: Install npm dependencies
working-directory: sdk/typescript
run: npm ci

- name: Build native addon (linux x64 gnu, native debian-bullseye)
working-directory: sdk/typescript
run: npm run build -- --target x86_64-unknown-linux-gnu

- name: Verify .node GLIBC requirement is <= 2.31
working-directory: sdk/typescript
run: |
ls -lh codegraff-sdk.*.node
objdump -T codegraff-sdk.linux-x64-gnu.node | grep GLIBC | sort -u | tail -10 || true

- name: Upload .node artifact
uses: actions/upload-artifact@v4
with:
name: bindings-x86_64-unknown-linux-gnu
path: sdk/typescript/codegraff-sdk.*.node
if-no-files-found: error
retention-days: 7

publish:
name: publish to npm
needs: [verify-tag, build, build-linux]
runs-on: ubuntu-latest
environment:
name: npm-publish
url: https://www.npmjs.com/package/@codegraff/sdk
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
# registry-url makes setup-node write an .npmrc that picks up
# NODE_AUTH_TOKEN. Still required when using Trusted Publisher (OIDC)
# so npm publish targets the right registry.
registry-url: 'https://registry.npmjs.org'
cache: 'npm'
cache-dependency-path: sdk/typescript/package-lock.json

- name: Install npm dependencies
run: npm ci

- name: Download all build artifacts
uses: actions/download-artifact@v4
with:
path: sdk/typescript/artifacts
pattern: bindings-*
merge-multiple: false

- name: Move .node files into npm/<triple>/
run: npm run artifacts

- name: List assembled tree
run: |
echo "::group::sdk/typescript/npm tree"
find npm -type f -printf '%p (%s bytes)\n' | sort
echo "::endgroup::"

- name: Publish to npm (with provenance)
env:
# Provenance flag is read by both npm publish + napi prepublish.
NPM_CONFIG_PROVENANCE: 'true'
# Empty when using Trusted Publisher (OIDC handles auth).
# Populated when falling back to a classic automation token.
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx napi prepublish -t npm --skip-gh-release

- name: Summary
run: |
echo "Published @codegraff/sdk@${{ needs.verify-tag.outputs.version }}" >> "$GITHUB_STEP_SUMMARY"
echo "See: https://www.npmjs.com/package/@codegraff/sdk/v/${{ needs.verify-tag.outputs.version }}" >> "$GITHUB_STEP_SUMMARY"
Loading
Loading