name: Publish Node Package
on:
release:
types:
- published
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
jobs:
build-linux:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
container:
image: node:20-bullseye
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-22.04
target: x86_64-unknown-linux-gnu
- runner: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
steps:
- uses: actions/checkout@v4
- name: Install build toolchain
run: |
apt-get update -qq
apt-get install -y --no-install-recommends build-essential cmake perl pkg-config
- name: Install Rust toolchain
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install Node dependencies
working-directory: node/mq-bridge-node
run: npm ci
- name: Build native addon (full)
working-directory: node/mq-bridge-node
env:
CARGO_NET_RETRY: "5"
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
CARGO_HTTP_MULTIPLEXING: "false"
run: >-
npx napi build --platform --release --strip
--target ${{ matrix.target }}
--js native.js --dts native.d.ts
- name: Upload addon
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.target }}
path: node/mq-bridge-node/*.node
if-no-files-found: error
- name: Upload loader
if: matrix.target == 'x86_64-unknown-linux-gnu'
uses: actions/upload-artifact@v4
with:
name: loader
path: |
node/mq-bridge-node/native.js
node/mq-bridge-node/native.d.ts
if-no-files-found: error
build-native:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- runner: macos-15-intel
target: x86_64-apple-darwin
- runner: macos-latest
target: aarch64-apple-darwin
- runner: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: node/mq-bridge-node/package-lock.json
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 with:
targets: ${{ matrix.target }}
- name: Install Node dependencies
working-directory: node/mq-bridge-node
run: npm ci
- name: Build native addon (full)
working-directory: node/mq-bridge-node
env:
CARGO_NET_RETRY: "5"
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
CARGO_HTTP_MULTIPLEXING: "false"
run: >-
npx napi build --platform --release --strip
--target ${{ matrix.target }}
--js native.js --dts native.d.ts
- name: Upload addon
uses: actions/upload-artifact@v4
with:
name: bindings-${{ matrix.target }}
path: node/mq-bridge-node/*.node
if-no-files-found: error
publish:
name: Publish to npm
runs-on: ubuntu-latest
needs: [build-linux, build-native]
permissions:
contents: read
id-token: write steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
cache: npm
cache-dependency-path: node/mq-bridge-node/package-lock.json
- name: Update npm
run: npm install -g npm@11.5.1
- name: Install Node dependencies
working-directory: node/mq-bridge-node
run: npm ci
- name: Sync version from Cargo workspace
working-directory: node/mq-bridge-node
run: npm run sync-version
- name: Download loader into package root
uses: actions/download-artifact@v4
with:
name: loader
path: node/mq-bridge-node
- name: Download platform addons
uses: actions/download-artifact@v4
with:
pattern: bindings-*
path: node/mq-bridge-node/artifacts
- name: Create per-platform npm dirs
working-directory: node/mq-bridge-node
run: npx napi create-npm-dirs
- name: Distribute addons into npm dirs
working-directory: node/mq-bridge-node
run: npx napi artifacts -d artifacts
- name: List npm dirs
working-directory: node/mq-bridge-node
run: ls -R npm
- name: Enrich platform package metadata
working-directory: node/mq-bridge-node
run: |
set -e
for dir in npm/*/; do
name=$(node -p "require('./$dir/package.json').name")
cat > "$dir/README.md" <<EOF
# $name
Prebuilt native binary for the [\`mq-bridge\`](https://github.com/marcomq/mq-bridge)
Node.js addon (napi-rs). This is a platform-specific dependency of the
\`mq-bridge\` package and is selected automatically via optionalDependencies —
you install \`mq-bridge\`, not this package directly.
EOF
node -e "const p='./$dir/package.json',j=require(p);j.description='Prebuilt '+j.name+' binary for the mq-bridge Node.js addon';j.homepage='https://github.com/marcomq/mq-bridge#readme';j.keywords=['mq-bridge','napi','native','prebuilt','addon'];require('fs').writeFileSync(p,JSON.stringify(j,null,2)+'\n')"
done
- name: Publish platform packages and root
working-directory: node/mq-bridge-node
env:
NPM_CONFIG_PROVENANCE: "true"
run: |
set -e
publish() {
local dir="$1" name ver
name=$(node -p "require('./$dir/package.json').name")
ver=$(node -p "require('./$dir/package.json').version")
# Skip if this exact version is already on the registry; a re-run
# after a partial publish must not fail on already-published dirs.
if npm view "$name@$ver" version >/dev/null 2>&1; then
echo "Skipping $name@$ver (already published)"
return 0
fi
echo "Publishing $dir ($name@$ver)"
npm publish "$dir" --access public
}
for dir in npm/*/; do
publish "$dir"
done
echo "Publishing root package"
root_name=$(node -p "require('./package.json').name")
root_ver=$(node -p "require('./package.json').version")
if npm view "$root_name@$root_ver" version >/dev/null 2>&1; then
echo "Skipping $root_name@$root_ver (already published)"
else
npm publish --access public
fi