name: Node.js Package on: push: branches: ['**'] paths: - 'nodejs/**' - '.github/workflows/nodejs-package.yml' - 'src/**' - 'include/**' - 'cmake/**' - 'CMakeLists.txt' - 'vcpkg*.json' - 'ports/**' - 'LICENSE' pull_request: paths: - 'nodejs/**' - '.github/workflows/nodejs-package.yml' - 'src/**' - 'include/**' - 'cmake/**' - 'CMakeLists.txt' - 'vcpkg*.json' - 'ports/**' - 'LICENSE' workflow_call: workflow_dispatch: permissions: contents: read packages: read jobs: build: name: Build ${{ matrix.target }} runs-on: ${{ matrix.os }} container: image: ${{ matrix.container }} credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} timeout-minutes: 45 defaults: run: working-directory: nodejs strategy: fail-fast: false matrix: include: - os: ubuntu-26.04 target: linux-x64 container: ghcr.io/${{ github.repository }}/opendht-deps-noble:latest - os: macos-15 target: darwin-arm64 - os: macos-15-intel target: darwin-x64 - os: windows-2022 target: win32-x64 env: VCPKG_DISABLE_METRICS: '1' VCPKG_DEFAULT_TRIPLET: x64-windows-release VCPKG_INSTALLED_DIR: ${{ github.workspace }}/vcpkg_installed VCPKG_BINARY_SOURCES: clear;files,${{ github.workspace }}/vcpkg-binary-cache,readwrite steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: '22' cache: npm cache-dependency-path: nodejs/package-lock.json - name: Install macOS dependencies if: runner.os == 'macOS' run: brew install cmake ninja pkg-config dylibbundler gnutls nettle argon2 msgpack-cxx fmt jsoncpp simdutf asio llhttp openssl - name: Install restinio if: runner.os == 'macOS' env: RESTINIO_VERSION: '0.7.10' run: | include="$RUNNER_TEMP/opendht-proxy/include" mkdir -p "$include/nonstd" curl -fsSL --retry 3 https://raw.githubusercontent.com/martinmoene/expected-lite/v0.10.0/include/nonstd/expected.hpp -o "$include/nonstd/expected.hpp" curl -fsSL --retry 3 "https://github.com/Stiffstream/restinio/releases/download/v${RESTINIO_VERSION}/restinio-${RESTINIO_VERSION}.tar.bz2" -o "$RUNNER_TEMP/restinio.tar.bz2" tar -xjf "$RUNNER_TEMP/restinio.tar.bz2" -C "$RUNNER_TEMP" cp -R "$RUNNER_TEMP/restinio-${RESTINIO_VERSION}/dev/restinio" "$include/" echo "CMAKE_PREFIX_PATH=$RUNNER_TEMP/opendht-proxy" >> "$GITHUB_ENV" - name: Set up MSVC if: runner.os == 'Windows' uses: ilammy/msvc-dev-cmd@v1 with: arch: x64 - name: Set up vcpkg if: runner.os == 'Windows' uses: lukka/run-vcpkg@v11 with: vcpkgJsonGlob: vcpkg.json vcpkgConfigurationJsonGlob: vcpkg-configuration.json - name: Cache Windows native dependencies if: runner.os == 'Windows' uses: actions/cache@v6 with: path: ${{ github.workspace }}/vcpkg-binary-cache key: node-vcpkg-${{ env.VCPKG_DEFAULT_TRIPLET }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json', 'ports/**') }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | node-vcpkg-${{ env.VCPKG_DEFAULT_TRIPLET }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json', 'ports/**') }}- - run: npm ci --no-audit --no-fund - name: Build Unix addon if: runner.os != 'Windows' shell: bash run: | if [[ "$RUNNER_OS" == 'macOS' ]]; then export MACOSX_DEPLOYMENT_TARGET=15.0 openssl_prefix=$(brew --prefix openssl) export PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" fi npm run build -- --CDOPENDHT_DOWNLOAD_DEPS=OFF - name: Build Windows addon if: runner.os == 'Windows' shell: pwsh run: | npm run build -- ` "--CDCMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" ` "--CDVCPKG_MANIFEST_DIR=$env:GITHUB_WORKSPACE" ` "--CDVCPKG_INSTALLED_DIR=$env:VCPKG_INSTALLED_DIR" ` "--CDVCPKG_TARGET_TRIPLET=$env:VCPKG_DEFAULT_TRIPLET" ` --CDVCPKG_MANIFEST_NO_DEFAULT_FEATURES=ON ` --CDVCPKG_MANIFEST_FEATURES=proxy ` --CDCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ` --CDOPENDHT_DOWNLOAD_DEPS=OFF if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } "$env:VCPKG_INSTALLED_DIR/$env:VCPKG_DEFAULT_TRIPLET/bin" >> $env:GITHUB_PATH "OPENDHT_LIBRARY_PATH=$env:VCPKG_INSTALLED_DIR/$env:VCPKG_DEFAULT_TRIPLET/bin" >> $env:GITHUB_ENV - run: npm test - run: npm run typecheck - run: npm run bundle - name: Include static simdutf licenses if: runner.os == 'Linux' run: | mkdir -p prebuilds/linux-x64/licenses/simdutf cp /usr/share/doc/simdutf/LICENSE-* prebuilds/linux-x64/licenses/simdutf/ - run: npm run test:package - uses: actions/upload-artifact@v7 with: name: opendht-node-prebuild-${{ matrix.target }} path: nodejs/prebuilds/ if-no-files-found: error package: name: Assemble npm archive needs: build runs-on: ubuntu-26.04 steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: '22' - uses: actions/download-artifact@v8 with: pattern: opendht-node-prebuild-* path: nodejs/prebuilds merge-multiple: true - name: Set release version if: github.event_name == 'push' && github.ref_type == 'tag' working-directory: nodejs env: RELEASE_TAG: ${{ github.ref_name }} run: | release_version=$(npm version "${RELEASE_TAG#v}" --no-git-tag-version --ignore-scripts --allow-same-version) if [[ "$release_version" != "$RELEASE_TAG" ]]; then printf '::error::Release tag %s is not an exact npm semantic version (normalized to %s).\n' "$RELEASE_TAG" "$release_version" >&2 exit 1 fi - name: Pack all platforms working-directory: nodejs run: | npm ci --ignore-scripts mkdir -p dist npm pack --pack-destination dist - uses: actions/upload-artifact@v7 with: name: opendht-node-npm path: nodejs/dist/*.tgz if-no-files-found: error smoke: name: Install on ${{ matrix.os }} / Node ${{ matrix.node }} needs: package runs-on: ${{ matrix.os }} timeout-minutes: 10 strategy: fail-fast: false matrix: os: [ubuntu-24.04, ubuntu-26.04, macos-15, macos-15-intel, windows-2022] node: ['22', '24', '26'] steps: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: node-version: ${{ matrix.node }} - uses: actions/download-artifact@v8 with: name: opendht-node-npm path: nodejs/dist - name: Test installed archive without a native build toolchain working-directory: nodejs run: npm run test:package -- dist