Skip to content

ci: Add GitHub Actions workflow for lni_nodejs multi-platform builds#28

Merged
ntheile merged 8 commits intomasterfrom
ci/nodejs-build
Jan 28, 2026
Merged

ci: Add GitHub Actions workflow for lni_nodejs multi-platform builds#28
ntheile merged 8 commits intomasterfrom
ci/nodejs-build

Conversation

@clawd21
Copy link
Collaborator

@clawd21 clawd21 commented Jan 28, 2026

✅ Created GitHub Actions workflow for Builds native Node.js bindings!

Branch: ci/nodejs-build

Build Targets:

Platform Target Artifact
Linux x64 x86_64-unknown-linux-gnu lni_js.linux-x64-gnu.node
Linux ARM64 aarch64-unknown-linux-gnu lni_js.linux-arm64-gnu.node
macOS x64 x86_64-apple-darwin lni_js.darwin-x64.node
macOS ARM64 aarch64-apple-darwin lni_js.darwin-arm64.node
Windows x64 x86_64-pc-windows-msvc lni_js.win32-x64-msvc.node

Triggers:

• Push to master/main → Build & test
• Push tag v* → Build, test, create Release
• Pull requests → Build & test

To create a release:

git tag v1.0.0
git push origin v1.0.0

Features:

  • Runs on push to master/main and tags
  • Creates GitHub Release on version tags (v*)
  • Uploads platform-specific .node binaries as release assets
  • Optional npm publish (requires NPM_TOKEN secret)
  • Test step to verify bindings load correctly

Summary by CodeRabbit

  • Chores
    • Added an automated CI pipeline for building native packages across Linux, macOS (universal), and Windows architectures.
  • Tests
    • Added automated verification that platform-specific native artifacts install and load correctly.
  • Release
    • Automated packaging and creation of per-platform release assets with optional publish to npm when credentials are provided.

✏️ Tip: You can customize this high-level summary in your review settings.

Builds native Node.js bindings for:
- Linux x64 (gnu)
- Linux ARM64 (gnu)
- macOS x64
- macOS ARM64
- macOS Universal (lipo)
- Windows x64 (msvc)

Features:
- Runs on push to master/main and tags
- Creates GitHub Release on version tags (v*)
- Uploads platform-specific .node binaries as release assets
- Optional npm publish (requires NPM_TOKEN secret)
- Test step to verify bindings load correctly
@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

Adds a new GitHub Actions workflow to build, test, and release multi-platform Node.js native bindings and updates Cargo config to add macOS (Darwin) Rust target settings for dynamic linking. (≤50 words)

Changes

Cohort / File(s) Summary
GitHub Actions workflow
.github/workflows/build-nodejs.yml
New matrixed build/test/release pipeline for Linux (x86_64, arm64), macOS (x64, arm64), and Windows (x64); sets up Node.js and Rust toolchains, installs platform deps, builds native Node addon via yarn napi, uploads/downloads artifacts, assembles macOS universal binary (lipo), creates tag-triggered GitHub releases, and optionally publishes to npm when NPM_TOKEN is present.
Cargo config (Darwin targets)
bindings/lni_nodejs/.cargo/config.toml
Adds aarch64-apple-darwin and x86_64-apple-darwin target sections with linker = "clang" and rustflags including -C link-arg=-undefined -C link-arg=dynamic_lookup to enable macOS dynamic_lookup linkage; preserves existing Linux and Windows target settings.

Sequence Diagram(s)

sequenceDiagram
    actor Developer
    participant GitHubActions as "GitHub Actions"
    participant Runner as "Platform Runner\n(Linux/macOS/Windows)"
    participant Toolchain as "Node & Rust Toolchain"
    participant Build as "Build (yarn napi / cargo)"
    participant Artifacts as "Artifact Storage"
    participant TestJob as "Test Job"
    participant ReleaseJob as "Release Job"
    participant GitHubRelease as "GitHub Release"
    participant NPM as "npm Registry"

    Developer->>GitHubActions: push or tag (v*)
    GitHubActions->>Runner: start matrix build jobs
    Runner->>Toolchain: setup Node.js and Rust (target toolchains)
    Runner->>Build: install deps and build native addon
    Build->>Artifacts: upload platform-specific artifacts
    GitHubActions->>TestJob: trigger tests (download artifacts)
    TestJob->>Artifacts: download artifacts
    TestJob->>Runner: run module load & verification
    alt tag triggered
        GitHubActions->>ReleaseJob: gather all artifacts
        ReleaseJob->>Artifacts: download platform artifacts
        ReleaseJob->>GitHubRelease: create release and attach assets
        alt NPM_TOKEN provided
            ReleaseJob->>NPM: publish package to npm
        end
    end
    GitHubRelease-->>Developer: release created with assets
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through CI with whiskers bright,
Built each arch by starlit night,
Spliced two macOS bones into one,
Bundled artifacts till morning sun,
A carrot-sized release — what delight! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding a GitHub Actions workflow for multi-platform Node.js builds, which is the primary focus of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ntheile
Copy link
Contributor

ntheile commented Jan 28, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

- Install protobuf-compiler on all platforms (needed for prost-build)
- Use 'yarn napi build' with --target flag directly
- Add brew/choco install steps for macOS/Windows
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/build-nodejs.yml:
- Around line 43-75: Replace all mutable GitHub Action references (e.g.,
actions/checkout@v4, actions/setup-node@v4, dtolnay/rust-toolchain@stable,
actions/upload-artifact@v4 and any other uses: entries across the workflow jobs)
with their reproducible commit SHA pins; for each replacement keep the original
tag in a comment immediately above the uses: line for clarity. Update every job
that uses a third-party action (build, universal-macos, test, release, publish)
to use the full commit SHA instead of the mutable tag, ensuring the same
behavior by selecting the SHA that corresponds to the current tag, and commit
those changes.
🧹 Nitpick comments (2)
.github/workflows/build-nodejs.yml (2)

115-152: Consider adding coverage for darwin‑x64 and linux‑arm64 artifacts.

Those outputs are currently untested. If they’re shipped, add an Intel macOS runner (or Rosetta) and an arm64 Linux runner/QEMU to catch loader regressions early.

💡 Example: add an Intel macOS test lane
         include:
           - os: ubuntu-latest
             artifact: bindings-linux-x64-gnu
+          - os: macos-13
+            artifact: bindings-darwin-x64
           - os: macos-latest
             artifact: bindings-darwin-arm64
           - os: windows-latest
             artifact: bindings-win32-x64-msvc

195-235: Skip the publish job when NPM_TOKEN is absent.

Gating the job keeps tag workflows clean and avoids a no‑op publish step.

✅ Suggested gating
-  publish:
-    if: startsWith(github.ref, 'refs/tags/v')
+  publish:
+    if: startsWith(github.ref, 'refs/tags/v') && secrets.NPM_TOKEN != ''
@@
-      - name: Publish to npm
-        working-directory: bindings/lni_nodejs
-        run: |
-          # Only publish if NPM_TOKEN is set
-          if [ -n "${{ secrets.NPM_TOKEN }}" ]; then
-            npm publish --access public
-          else
-            echo "NPM_TOKEN not set, skipping publish"
-          fi
+      - name: Publish to npm
+        working-directory: bindings/lni_nodejs
+        run: npm publish --access public

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/build-nodejs.yml:
- Around line 240-250: The workflow step named "Publish to npm" currently tests
the secret by interpolating ${{ secrets.NPM_TOKEN }} into the shell; change the
guard to check the environment variable instead (use NODE_AUTH_TOKEN already set
in env) and rely on NODE_AUTH_TOKEN in the shell check (e.g., if [ -n
"${NODE_AUTH_TOKEN}" ]), avoid echoing or printing the token, and keep npm
publish using the existing env variable rather than interpolating the secret
directly.
- Around line 200-208: Update the GitHub Actions step named "Create Release" to
use softprops/action-gh-release@v2 instead of `@v1` by changing the uses reference
(softprops/action-gh-release@v1 → softprops/action-gh-release@v2); keep the
existing inputs (files, generate_release_notes, draft, prerelease) and env
GITHUB_TOKEN as-is, and verify the v2 action supports the same fields in the
"Create Release" step to ensure compatibility.
🧹 Nitpick comments (2)
.github/workflows/build-nodejs.yml (2)

116-127: Add error handling for universal binary creation.

Two concerns with this job:

  1. The lipo command uses wildcards which could fail unexpectedly if there are multiple .node files or if the glob doesn't match.
  2. The upload step lacks if-no-files-found: error, unlike the build job, which could mask failures silently.
♻️ Suggested improvements
       - name: Create universal binary
         run: |
+          # Verify exactly one .node file in each directory
+          x64_file=$(ls artifacts/x64/*.node)
+          arm64_file=$(ls artifacts/arm64/*.node)
           lipo -create \
-            artifacts/x64/*.node \
-            artifacts/arm64/*.node \
+            "$x64_file" \
+            "$arm64_file" \
             -output lni_js.darwin-universal.node
 
       - name: Upload universal artifact
         uses: actions/upload-artifact@v4
         with:
           name: bindings-darwin-universal
           path: lni_js.darwin-universal.node
+          if-no-files-found: error

231-238: Avoid silently suppressing copy errors during npm publish preparation.

The 2>/dev/null || true pattern hides all errors, which could result in publishing an npm package with missing binaries. Consider validating that files were actually copied.

♻️ Suggested improvement
       - name: Prepare npm package
         working-directory: bindings/lni_nodejs
         run: |
           # Copy platform-specific binaries
           for dir in ../../artifacts/bindings-*; do
-            cp "$dir"/*.node . 2>/dev/null || true
+            if ls "$dir"/*.node 1>/dev/null 2>&1; then
+              cp "$dir"/*.node .
+            fi
           done
           ls -la *.node
+          # Verify at least one binary was copied
+          if ! ls *.node 1>/dev/null 2>&1; then
+            echo "Error: No .node binaries found"
+            exit 1
+          fi

Clawd added 4 commits January 27, 2026 21:13
Replace mutable tag references with reproducible commit SHA pins:
- actions/checkout@v4 → @34e114876b0b11c390a56381ad16ebd13914f8d5
- actions/setup-node@v4 → @49933ea5288caeca8642d1e84afbd3f7d6820020
- dtolnay/rust-toolchain@stable → @4be9e76fd7c4901c61fb841f559994984270fce7
- actions/upload-artifact@v4 → @ea165f8d65b6e75b540449e92b4886f43607fa02
- actions/download-artifact@v4 → @d3f86a106a0bac45b974a628896c90dbdf5c8093
- softprops/action-gh-release@v1 → @de2c0eb89ae2a093876385947365aca7b0e5f844

Original tags preserved in comments above each uses: line for clarity.
- darwin-x64: Use macos-13 (Intel runner) for native x86_64 build
- darwin-arm64: Use macos-14 (Apple Silicon runner) for native aarch64 build
- Update test and universal-macos jobs to use macos-14

macos-latest now defaults to arm64, causing cross-compilation issues.
…secret

Avoid interpolating ${{ secrets.NPM_TOKEN }} directly into shell script.
Instead, check the NODE_AUTH_TOKEN environment variable which is already
set via the env block. This prevents potential secret exposure in logs.
- v1 → v2 (SHA: a06a81a03ee405af7f2048a818ed3f03bbf83c7b)
- v2 uses node20 runtime (vs node16 in v1)
- All existing inputs (files, generate_release_notes, draft, prerelease) are compatible
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/build-nodejs.yml:
- Around line 28-34: The GitHub Actions job uses an invalid macOS runner label
for the darwin-x64 entry; update the runner value currently set to "macos-13" to
a supported Intel runner such as "macos-15-intel" (or
"macos-14-large"/"macos-15-large") so the darwin-x64 job (target:
x86_64-apple-darwin, name: darwin-x64) runs on a valid hosted runner.

Clawd added 2 commits January 27, 2026 21:27
The darwin builds were failing because the linker couldn't find N-API
symbols (_napi_create_error, _napi_create_function, etc.). These symbols
are provided by Node.js at runtime, so we need -undefined dynamic_lookup
to tell the linker to defer resolution.
- macos-13 (Intel) → macos-15-intel
- macos-14 (ARM64) → macos-latest

Per GitHub deprecation notice:
actions/runner-images#13046
@ntheile ntheile merged commit 95c2a21 into master Jan 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants