diff --git a/.github/workflows/bindings-nodejs-publish.yml b/.github/workflows/bindings-nodejs-publish.yml new file mode 100644 index 0000000000..a1c25e7e15 --- /dev/null +++ b/.github/workflows/bindings-nodejs-publish.yml @@ -0,0 +1,181 @@ +name: Node.js publish to NPM + +on: workflow_dispatch + +env: + CARGO_INCREMENTAL: 0 + +jobs: + publish-nodejs: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: bindings/nodejs + + steps: + - uses: actions/checkout@v3 + + - name: Set up Rust + uses: ./.github/actions/setup-rust + + # Required for ledger-nano + - name: Install required packages + run: | + sudo apt-get update + sudo apt-get install libudev-dev libusb-1.0-0-dev + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: "18.x" + registry-url: "https://registry.npmjs.org" + + - name: Install Yarn + run: npm i -g yarn + + - name: Install JS dependencies + run: yarn + + - name: Build project + run: yarn build + + - name: Update Cargo.toml with git + run: sed -i 's#path = "../core"#git = "https://github.com/iotaledger/iota-sdk", rev = "'$GITHUB_SHA'"#g' Cargo.toml + + - name: Print Cargo.toml + run: cat Cargo.toml + + - name: Publish nodejs bindings to NPM + shell: sh + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npm publish --access public + + nodejs-binding-prebuild: + runs-on: ${{ matrix.os }} + needs: publish-nodejs + strategy: + fail-fast: false + matrix: + # The GitHub hosted Windows 2022 image comes with Visual Studio 2022, but node-gyp + # (which is used by neon-sys) sadly fails to recognize it. As a mitigation, we still run the + # tests on Windows 2019, until we can figure out a way to fix the problem. + os: [ubuntu-20.04, macos-13, windows-2019] + node-version: ["18.x"] + + steps: + - uses: actions/checkout@v3 + + - name: Set up Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + + - name: Install Yarn + run: npm i -g yarn + + - name: Select Xcode + uses: maxim-lobanov/setup-xcode@v1 + if: matrix.os == 'macos-13' + with: + xcode-version: '14.3' + + # Temporary fix for "ValueError: invalid mode: 'rU' while trying to load binding.gyp" + # This can be removed when "prebuild" updates "node-gyp" + - name: Set up Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + # This step can be removed as soon as official Windows arm64 builds are published: + # https://github.com/nodejs/build/issues/2450#issuecomment-705853342 + - name: Install Windows arm64 node.lib + if: ${{ matrix.os == 'windows-2019' }} + run: | + $NodeVersion = (node --version) -replace '^.' + $NodeFallbackVersion = "16.19.0" + & .\scripts\download-node-lib-win-arm64.ps1 $NodeVersion $NodeFallbackVersion + working-directory: bindings/nodejs + + - name: Install LLVM and Clang (Windows) # required for bindgen to work, see https://github.com/rust-lang/rust-bindgen/issues/1797 + uses: KyleMayes/install-llvm-action@32c4866ebb71e0949e8833eb49beeebed48532bd + if: matrix.os == 'windows-2019' + with: + version: "11.0" + directory: ${{ runner.temp }}/llvm + + - name: Set LIBCLANG_PATH (Windows) + run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV + if: matrix.os == 'windows-2019' + + - name: Set deployment target (macOS) + run: echo "MACOSX_DEPLOYMENT_TARGET=10.13" >> $GITHUB_ENV + if: matrix.os == 'macos-13' + + - name: Get current date + run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV + if: matrix.os == 'macos-13' || ${{ startsWith(matrix.os, 'ubuntu') }} + + - name: Get current date + if: matrix.os == 'windows-2019' + run: echo "CURRENT_DATE=$(Get-Date -Format "yyyy-MM-dd")" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + - name: Install required packages (Ubuntu) + if: ${{ startsWith(matrix.os, 'ubuntu') }} + run: | + sudo apt-get update + sudo apt-get install libudev-dev libusb-1.0-0-dev + + - name: Cache cargo registry + uses: actions/cache@v3 + with: + path: ~/.cargo/registry + # Add date to the cache to keep it up to date + key: ${{ matrix.os }}-stable-cargo-registry-${{ hashFiles('**/Cargo.lock') }}-${{ env.CURRENT_DATE }} + # Restore from outdated cache for speed + restore-keys: | + ${{ matrix.os }}-stable-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + ${{ matrix.os }}-stable-cargo-registry- + - name: Cache cargo index + uses: actions/cache@v3 + with: + path: ~/.cargo/git + # Add date to the cache to keep it up to date + key: ${{ matrix.os }}-stable-cargo-index-${{ hashFiles('**/Cargo.lock') }}-${{ env.CURRENT_DATE }} + # Restore from outdated cache for speed + restore-keys: | + ${{ matrix.os }}-stable-cargo-index-${{ hashFiles('**/Cargo.lock') }} + ${{ matrix.os }}-stable-cargo-index- + + # This step is required to support macOS 10.13 + - name: Patch librocksdb-sys (macOS) + if: ${{ startsWith(matrix.os, 'macos') }} + run: | + cargo install cargo-patch + cp ${{ github.workspace }}/.patches/rocksdb_faligned_allocation.patch . + git apply --ignore-space-change --ignore-whitespace ${{ github.workspace }}/.patches/macos_cargo_toml.patch + cat Cargo.toml + cargo patch + + - name: Install dependencies + run: yarn install --frozen-lockfile + working-directory: bindings/nodejs + + - name: Build Node.js prebuild (x64) + run: yarn run prebuild-x64 + working-directory: bindings/nodejs + + - name: Build Node.js prebuild (arm64) + run: yarn run prebuild-arm64 + working-directory: bindings/nodejs + + - name: Upload prebuild to GitHub release + run: npx prebuild --upload-all ${{ secrets.GITHUB_TOKEN }} --tag-prefix iota-sdk-nodejs-v + working-directory: bindings/nodejs diff --git a/bindings/nodejs/package.json b/bindings/nodejs/package.json index 20e7694c01..1c729c267b 100644 --- a/bindings/nodejs/package.json +++ b/bindings/nodejs/package.json @@ -14,7 +14,7 @@ "prebuild-x64": "prebuild --runtime napi --target 6 --prepack scripts/neon-build.js --strip --arch x64", "prebuild-arm64": "prebuild --runtime napi --target 6 --prepack scripts/neon-build.js --strip --arch arm64", "rebuild": "node scripts/neon-build && tsc && node scripts/strip.js", - "install": "prebuild-install --runtime napi --tag-prefix='sdk-binding-v' && tsc || npm run rebuild", + "install": "prebuild-install --runtime napi --tag-prefix='iota-sdk-nodejs-v' && tsc || npm run rebuild", "test": "jest --forceExit" }, "author": "IOTA Foundation ", diff --git a/bindings/nodejs/scripts/download-node-lib-win-arm64.ps1 b/bindings/nodejs/scripts/download-node-lib-win-arm64.ps1 new file mode 100644 index 0000000000..3b81d852c1 --- /dev/null +++ b/bindings/nodejs/scripts/download-node-lib-win-arm64.ps1 @@ -0,0 +1,36 @@ +# This script can be removed as soon as official Windows arm64 builds are published: +# https://github.com/nodejs/build/issues/2450#issuecomment-705853342 + +$nodeVersion = $args[0] +$fallbackVersion = $args[1] + +If ($null -eq $nodeVersion -Or $null -eq $fallbackVersion) { + Write-Error "No NodeJS version given as argument to this file. Run it like download-nodejs-win-arm64.ps1 NODE_VERSION NODE_FALLBACK_VERSION" + exit 1 +} + +$url = "https://unofficial-builds.nodejs.org/download/release/v$nodeVersion/win-arm64/node.lib" +$fallbackUrl = "https://unofficial-builds.nodejs.org/download/release/v$fallbackVersion/win-arm64/node.lib" + +# Always write to the $nodeVersion cache folder, even if we're using the fallbackVersion +$cacheFolder = "$env:TEMP\prebuild\napi\$nodeVersion\arm64" + +If (!(Test-Path $cacheFolder)) { + New-Item -ItemType Directory -Force -Path $cacheFolder +} + +$output = "$cacheFolder\node.lib" +$start_time = Get-Date + +Try { + Invoke-WebRequest -Uri $url -OutFile $output + $downloadedNodeVersion = $nodeVersion +} Catch { + If ($_.Exception.Response -And $_.Exception.Response.StatusCode -eq "NotFound") { + Write-Output "No arm64 node.lib found for Node Windows $nodeVersion, trying fallback version $fallbackVersion..." + Invoke-WebRequest -Uri $fallbackUrl -OutFile $output + $downloadedNodeVersion = $fallbackVersion + } +} + +Write-Output "Downloaded arm64 NodeJS lib v$downloadedNodeVersion to $output in $((Get-Date).Subtract($start_time).Seconds) second(s)"