Use WASM patchelf equivalent #101
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| env: | |
| DEBUG: napi:* | |
| APP_NAME: python-node | |
| MACOSX_DEPLOYMENT_TARGET: '10.13' | |
| CARGO_NET_GIT_FETCH_WITH_CLI: 'true' | |
| permissions: | |
| contents: write | |
| id-token: write | |
| on: | |
| push: | |
| branches: | |
| - main | |
| tags-ignore: | |
| - '**' | |
| paths-ignore: | |
| - '**/*.md' | |
| - LICENSE | |
| - '**/*.gitignore' | |
| - .editorconfig | |
| - docs/** | |
| pull_request: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }}-ci | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: macos-latest | |
| target: x86_64-apple-darwin | |
| build: pnpm run build --target x86_64-apple-darwin | |
| - host: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian | |
| build: pnpm run build --target x86_64-unknown-linux-gnu | |
| - host: macos-latest | |
| target: aarch64-apple-darwin | |
| build: pnpm run build --target aarch64-apple-darwin | |
| name: stable - ${{ matrix.settings.target }} - node@20 | |
| runs-on: ${{ matrix.settings.host }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: webfactory/ssh-agent@v0.9.0 | |
| with: | |
| ssh-private-key: | | |
| ${{ secrets.HTTP_HANDLER_ACCESS_TOKEN }} | |
| ${{ secrets.HTTP_REWRITER_ACCESS_TOKEN }} | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: latest | |
| - uses: actions/setup-node@v4 | |
| if: ${{ !matrix.settings.docker }} | |
| with: | |
| node-version: 20 | |
| - name: Install | |
| uses: dtolnay/rust-toolchain@stable | |
| if: ${{ !matrix.settings.docker }} | |
| with: | |
| toolchain: stable | |
| targets: ${{ matrix.settings.target }} | |
| - name: Cache cargo | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry/index/ | |
| ~/.cargo/registry/cache/ | |
| ~/.cargo/git/db/ | |
| .cargo-cache | |
| target/ | |
| key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }} | |
| - uses: goto-bus-stop/setup-zig@v2 | |
| if: ${{ matrix.settings.target == 'armv7-unknown-linux-gnueabihf' || matrix.settings.target == 'armv7-unknown-linux-musleabihf' }} | |
| with: | |
| version: 0.13.0 | |
| - name: Setup toolchain | |
| run: ${{ matrix.settings.setup }} | |
| if: ${{ matrix.settings.setup }} | |
| shell: bash | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Build in docker | |
| uses: addnab/docker-run-action@v3 | |
| if: ${{ matrix.settings.docker }} | |
| with: | |
| image: ${{ matrix.settings.docker }} | |
| options: '--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build' | |
| run: | | |
| set -x | |
| export CARGO_NET_GIT_FETCH_WITH_CLI=true | |
| # Install apt dependencies | |
| apt-get update -y | |
| apt-get install -y openssh-client python3 python3-dev | |
| # Setup pnpm | |
| corepack disable | |
| npm i -gf pnpm | |
| # Set up SSH keys (to checkout private repos with cargo) | |
| mkdir -p ~/.ssh | |
| chmod 700 ~/.ssh | |
| # Save SSH keys to files | |
| echo "${{ secrets.HTTP_HANDLER_ACCESS_TOKEN }}" | tr -d '\r' > ~/.ssh/http_handler_key | |
| echo "${{ secrets.HTTP_REWRITER_ACCESS_TOKEN }}" | tr -d '\r' > ~/.ssh/http_rewriter_key | |
| chmod 600 ~/.ssh/http_handler_key | |
| chmod 600 ~/.ssh/http_rewriter_key | |
| # Add GitHub to known hosts (for all aliases) | |
| ssh-keyscan -H github.com >> ~/.ssh/known_hosts | |
| # Create SSH config with host aliases | |
| cat > ~/.ssh/config <<'EOF' | |
| Host github.com-http-handler | |
| HostName github.com | |
| User git | |
| IdentityFile ~/.ssh/http_handler_key | |
| IdentitiesOnly yes | |
| Host github.com-http-rewriter | |
| HostName github.com | |
| User git | |
| IdentityFile ~/.ssh/http_rewriter_key | |
| IdentitiesOnly yes | |
| EOF | |
| chmod 600 ~/.ssh/config | |
| # Configure git to rewrite URLs to use the correct host alias | |
| git config --global url."ssh://git@github.com-http-handler/platformatic/http-handler".insteadOf "ssh://git@github.com/platformatic/http-handler" | |
| git config --global url."ssh://git@github.com-http-rewriter/platformatic/http-rewriter".insteadOf "ssh://git@github.com/platformatic/http-rewriter" | |
| # Also handle variations without .git suffix | |
| git config --global url."ssh://git@github.com-http-handler/platformatic/http-handler.git".insteadOf "ssh://git@github.com/platformatic/http-handler.git" | |
| git config --global url."ssh://git@github.com-http-rewriter/platformatic/http-rewriter.git".insteadOf "ssh://git@github.com/platformatic/http-rewriter.git" | |
| # Build the main binary | |
| ${{ matrix.settings.build }} | |
| # Build the WASI module for Linux targets | |
| if [ "${{ matrix.settings.target }}" = "x86_64-unknown-linux-gnu" ]; then | |
| echo "===== Building fix-python-soname WASI module =====" | |
| rustup target add wasm32-wasip1 | |
| echo "===== Entering fix-python-soname directory =====" | |
| cd fix-python-soname | |
| pwd | |
| ls -la | |
| echo "===== Building WASM with cargo =====" | |
| cargo build --target wasm32-wasip1 --release || { | |
| echo "ERROR: Cargo build failed!" | |
| exit 1 | |
| } | |
| echo "===== Checking build output =====" | |
| echo "Finding all files in target directory:" | |
| find target -type f 2>/dev/null || echo "No target directory found" | |
| echo "Looking for WASM files specifically:" | |
| find . -name "*.wasm" -type f 2>/dev/null || echo "No WASM files found" | |
| echo "Looking for any files with 'fix-python-soname' in name:" | |
| find . -name "*fix-python-soname*" -type f 2>/dev/null || echo "No fix-python-soname files found" | |
| echo "Checking target structure:" | |
| ls -la target/ 2>/dev/null || echo "No target directory" | |
| ls -la target/wasm32-wasip1/ 2>/dev/null || echo "No wasm32-wasip1 directory" | |
| ls -la target/wasm32-wasip1/release/ 2>/dev/null || echo "No release directory" | |
| echo "===== Copying WASM to root =====" | |
| # WASM binaries might not have .wasm extension, try both | |
| if [ -f "target/wasm32-wasip1/release/fix-python-soname.wasm" ]; then | |
| cp target/wasm32-wasip1/release/fix-python-soname.wasm .. | |
| echo "Copied .wasm file" | |
| elif [ -f "target/wasm32-wasip1/release/fix-python-soname" ]; then | |
| cp target/wasm32-wasip1/release/fix-python-soname ../fix-python-soname.wasm | |
| echo "Copied binary file as .wasm" | |
| else | |
| echo "ERROR: No WASM or binary file found" | |
| ls -la target/wasm32-wasip1/release/ 2>/dev/null || echo "No release directory" | |
| exit 1 | |
| fi | |
| cd .. | |
| echo "===== Verifying WASM file in root =====" | |
| pwd | |
| ls -la fix-python-soname.wasm || { | |
| echo "ERROR: WASM file not found after copy" | |
| find . -name "*.wasm" -type f | |
| exit 1 | |
| } | |
| echo "===== WASM build complete =====" | |
| fi | |
| - name: Build | |
| run: ${{ matrix.settings.build }} | |
| if: ${{ !matrix.settings.docker }} | |
| shell: bash | |
| - name: List files before upload | |
| run: | | |
| echo "Files in current directory:" | |
| ls -la | |
| echo "Looking for WASM files:" | |
| find . -name "*.wasm" -type f | |
| if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} | |
| - name: Upload artifact (Linux with WASM) | |
| uses: actions/upload-artifact@v4 | |
| if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} | |
| with: | |
| name: bindings-${{ matrix.settings.target }} | |
| path: | | |
| ${{ env.APP_NAME }}.*.node | |
| index.d.ts | |
| index.js | |
| fix-python-soname.wasm | |
| fix-python-soname.js | |
| if-no-files-found: error | |
| - name: Upload artifact (non-Linux) | |
| uses: actions/upload-artifact@v4 | |
| if: ${{ matrix.settings.target != 'x86_64-unknown-linux-gnu' }} | |
| with: | |
| name: bindings-${{ matrix.settings.target }} | |
| path: | | |
| ${{ env.APP_NAME }}.*.node | |
| index.d.ts | |
| index.js | |
| if-no-files-found: error | |
| test-macOS-windows-binding: | |
| name: Test bindings on ${{ matrix.settings.target }} - node@${{ matrix.node }} | |
| needs: | |
| - build | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: macos-latest | |
| target: x86_64-apple-darwin | |
| node: | |
| - '18' | |
| - '20' | |
| runs-on: ${{ matrix.settings.host }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: webfactory/ssh-agent@v0.9.0 | |
| with: | |
| ssh-private-key: | | |
| ${{ secrets.HTTP_HANDLER_ACCESS_TOKEN }} | |
| ${{ secrets.HTTP_REWRITER_ACCESS_TOKEN }} | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: latest | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: pnpm | |
| architecture: x64 | |
| - run: pnpm install | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: bindings-${{ matrix.settings.target }} | |
| path: . | |
| - name: List packages | |
| run: ls -R . | |
| shell: bash | |
| - name: Check test directory | |
| run: | | |
| echo "Current directory: $(pwd)" | |
| echo "Test directory contents:" | |
| ls -la test/ || echo "test/ directory not found" | |
| echo "Looking for test files:" | |
| find . -name "*.test.mjs" -type f || echo "No test files found" | |
| shell: bash | |
| - run: cargo test | |
| - run: pnpm test | |
| test-linux-binding: | |
| name: Test bindings on ${{ matrix.settings.target }} - node@${{ matrix.node }} | |
| needs: | |
| - build | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| settings: | |
| - host: ubuntu-22.04 | |
| target: x86_64-unknown-linux-gnu | |
| # Not supported yet. | |
| # - host: ubuntu-22.04 | |
| # target: x86_64-unknown-linux-musl | |
| # Not supported yet, ubuntu-24.04-arm runner requires repo is public | |
| # - host: ubuntu-22.04-arm | |
| # target: aarch64-unknown-linux-gnu | |
| # - host: ubuntu-22.04-arm | |
| # target: aarch64-unknown-linux-musl | |
| node: | |
| - '18' | |
| - '20' | |
| runs-on: ${{ matrix.settings.host }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: latest | |
| - name: Setup node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: bindings-${{ matrix.settings.target }} | |
| path: . | |
| - name: List packages | |
| run: ls -R . | |
| shell: bash | |
| - name: Output docker params | |
| id: docker | |
| run: | | |
| node -e " | |
| if ('${{ matrix.settings.target }}'.startsWith('aarch64')) { | |
| console.log('PLATFORM=linux/arm64') | |
| } else if ('${{ matrix.settings.target }}'.startsWith('armv7')) { | |
| console.log('PLATFORM=linux/arm/v7') | |
| } else { | |
| console.log('PLATFORM=linux/amd64') | |
| } | |
| " >> $GITHUB_OUTPUT | |
| node -e " | |
| if ('${{ matrix.settings.target }}'.endsWith('-musl')) { | |
| console.log('IMAGE=node:${{ matrix.node }}-alpine') | |
| } else { | |
| console.log('IMAGE=node:${{ matrix.node }}-slim') | |
| } | |
| " >> $GITHUB_OUTPUT | |
| echo "PNPM_STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT | |
| - name: Test crates | |
| uses: addnab/docker-run-action@v3 | |
| with: | |
| image: ${{ steps.docker.outputs.IMAGE }} | |
| options: -v ${{ github.workspace }}:${{ github.workspace }} -w ${{ github.workspace }} --platform ${{ steps.docker.outputs.PLATFORM }} | |
| run: | | |
| set -x | |
| export CARGO_NET_GIT_FETCH_WITH_CLI=true | |
| # Install apt dependencies | |
| apt-get update -y | |
| apt-get install -y openssh-client curl git build-essential python3 python3-dev | |
| # Install rust toolchain | |
| curl https://sh.rustup.rs -sSf | bash -s -- -y -t ${{ matrix.settings.target }} | |
| . "$HOME/.cargo/env" | |
| # Set up SSH keys (to checkout private repos with cargo) | |
| mkdir -p ~/.ssh | |
| chmod 700 ~/.ssh | |
| # Save SSH keys to files | |
| echo "${{ secrets.HTTP_HANDLER_ACCESS_TOKEN }}" | tr -d '\r' > ~/.ssh/http_handler_key | |
| echo "${{ secrets.HTTP_REWRITER_ACCESS_TOKEN }}" | tr -d '\r' > ~/.ssh/http_rewriter_key | |
| chmod 600 ~/.ssh/http_handler_key | |
| chmod 600 ~/.ssh/http_rewriter_key | |
| # Add GitHub to known hosts (for all aliases) | |
| ssh-keyscan -H github.com >> ~/.ssh/known_hosts | |
| # Create SSH config with host aliases | |
| cat > ~/.ssh/config <<'EOF' | |
| Host github.com-http-handler | |
| HostName github.com | |
| User git | |
| IdentityFile ~/.ssh/http_handler_key | |
| IdentitiesOnly yes | |
| Host github.com-http-rewriter | |
| HostName github.com | |
| User git | |
| IdentityFile ~/.ssh/http_rewriter_key | |
| IdentitiesOnly yes | |
| EOF | |
| chmod 600 ~/.ssh/config | |
| # Configure git to rewrite URLs to use the correct host alias | |
| git config --global url."ssh://git@github.com-http-handler/platformatic/http-handler".insteadOf "ssh://git@github.com/platformatic/http-handler" | |
| git config --global url."ssh://git@github.com-http-rewriter/platformatic/http-rewriter".insteadOf "ssh://git@github.com/platformatic/http-rewriter" | |
| # Also handle variations without .git suffix | |
| git config --global url."ssh://git@github.com-http-handler/platformatic/http-handler.git".insteadOf "ssh://git@github.com/platformatic/http-handler.git" | |
| git config --global url."ssh://git@github.com-http-rewriter/platformatic/http-rewriter.git".insteadOf "ssh://git@github.com/platformatic/http-rewriter.git" | |
| cargo test --target ${{ matrix.settings.target }} | |
| - name: Test bindings | |
| uses: addnab/docker-run-action@v3 | |
| with: | |
| image: ${{ steps.docker.outputs.IMAGE }} | |
| options: -v ${{ steps.docker.outputs.PNPM_STORE_PATH }}:${{ steps.docker.outputs.PNPM_STORE_PATH }} -v ${{ github.workspace }}:${{ github.workspace }} -w ${{ github.workspace }} --platform ${{ steps.docker.outputs.PLATFORM }} -e CI=true -e GITHUB_ACTIONS=true | |
| run: | | |
| corepack disable | |
| npm i -gf pnpm | |
| pnpm install --prefer-offline | |
| # Check what files we have | |
| echo "Current directory contents:" | |
| ls -la | |
| # Look for WASM files | |
| echo "Looking for WASM files:" | |
| find . -name "*.wasm" -type f | head -20 | |
| # Debug: Check Python version and libraries available | |
| echo "Checking Python installation..." | |
| which python3 || true | |
| python3 --version || true | |
| echo "Looking for Python libraries..." | |
| find /usr/lib -name "libpython*.so*" 2>/dev/null | head -20 || true | |
| # Try to download the WASM file if not present | |
| if [ ! -f "fix-python-soname.wasm" ]; then | |
| echo "WASM file not found locally. Checking if we can get it from artifacts..." | |
| # The WASM should have been built during the Linux build | |
| # For now, skip the soname fixing if WASM is not available | |
| echo "Warning: fix-python-soname.wasm not found, skipping soname fix" | |
| else | |
| # Fix Python soname if WASI module is available | |
| if [ -f "fix-python-soname.js" ]; then | |
| echo "Fixing Python soname in .node file..." | |
| node fix-python-soname.js || echo "Warning: Failed to fix Python soname" | |
| # Check if backup was created | |
| if ls *.node.bak 2>/dev/null; then | |
| echo "Backup file created, soname fix was attempted" | |
| ls -la *.node.bak | |
| fi | |
| else | |
| echo "fix-python-soname.js not found" | |
| fi | |
| fi | |
| pnpm test | |
| publish: | |
| name: Publish | |
| runs-on: ubuntu-latest | |
| needs: | |
| - test-macOS-windows-binding | |
| - test-linux-binding | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: latest | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Move artifacts | |
| run: pnpm artifacts | |
| - name: Copy fix-python-soname files to Linux packages | |
| run: | | |
| # Find the WASM and JS files from Linux artifacts | |
| WASM_FILE=$(find artifacts -name "fix-python-soname.wasm" | head -n 1) | |
| JS_FILE=$(find artifacts -name "fix-python-soname.js" | head -n 1) | |
| if [ -n "$WASM_FILE" ] && [ -n "$JS_FILE" ]; then | |
| echo "Found WASM file: $WASM_FILE" | |
| echo "Found JS file: $JS_FILE" | |
| # Copy to all Linux npm directories | |
| for dir in npm/*/; do | |
| if [[ "$dir" == *"linux"* ]]; then | |
| echo "Copying files to $dir" | |
| cp "$WASM_FILE" "$dir" | |
| cp "$JS_FILE" "$dir" | |
| fi | |
| done | |
| else | |
| echo "Warning: fix-python-soname files not found in artifacts" | |
| fi | |
| - name: List packages | |
| run: ls -R ./npm | |
| shell: bash | |
| - name: Publish | |
| if: contains(github.ref, 'main') | |
| run: | | |
| npm config set //registry.npmjs.org/:_authToken=$NPM_TOKEN | |
| npm config set scope "@platformatic" | |
| # npm config set provenance true | |
| if git log -1 --pretty=%B | grep "^v\?[0-9]\+\.[0-9]\+\.[0-9]\+"; | |
| then | |
| npm publish --access public --dry-run | |
| elif git log -1 --pretty=%B | grep "^v\?[0-9]\+\.[0-9]\+\.[0-9]\+-\.+"; | |
| then | |
| npm publish --tag next --access public --dry-run | |
| else | |
| echo "Not a release, skipping publish" | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} |