refactor(ci): use .node-version instead of external-tools.json #72
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: 🌊 SEA Binaries | ||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| force: | ||
| description: 'Force rebuild (ignore cache)' | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
| build-linux: | ||
| description: 'Build Linux SEA binaries' | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| build-macos: | ||
| description: 'Build macOS SEA binaries' | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| build-windows: | ||
| description: 'Build Windows SEA binaries' | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| workflow_dispatch: | ||
| inputs: | ||
| force: | ||
| description: 'Force rebuild (ignore cache)' | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
| build-linux: | ||
| description: 'Build Linux SEA binaries' | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| build-macos: | ||
| description: 'Build macOS SEA binaries' | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| build-windows: | ||
| description: 'Build Windows SEA binaries' | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| permissions: | ||
| contents: read | ||
| concurrency: | ||
| group: build-sea-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | ||
| cancel-in-progress: true | ||
| env: | ||
| SOCKET_BTM_REPO: SocketDev/socket-btm | ||
| jobs: | ||
| build-sea: | ||
| name: 🌊 SEA - ${{ matrix.platform }}-${{ matrix.arch }} | ||
| runs-on: ${{ matrix.runner }} | ||
| timeout-minutes: 30 | ||
| strategy: | ||
| fail-fast: false | ||
| max-parallel: 8 | ||
| matrix: | ||
| include: | ||
| # Linux builds. | ||
| - runner: ubuntu-latest | ||
| os: linux | ||
| platform: linux | ||
| arch: x64 | ||
| - runner: ubuntu-24.04-arm | ||
| os: linux | ||
| platform: linux | ||
| arch: arm64 | ||
| # Alpine Linux builds - use musl binaries. | ||
| - runner: ubuntu-latest | ||
| os: linux | ||
| platform: linux-musl | ||
| arch: x64 | ||
| - runner: ubuntu-24.04-arm | ||
| os: linux | ||
| platform: linux-musl | ||
| arch: arm64 | ||
| # macOS builds. | ||
| - runner: macos-latest | ||
| os: darwin | ||
| platform: darwin | ||
| arch: x64 | ||
| - runner: macos-latest | ||
| os: darwin | ||
| platform: darwin | ||
| arch: arm64 | ||
| # Windows builds. | ||
| - runner: windows-latest | ||
| os: windows | ||
| platform: win32 | ||
| arch: x64 | ||
| - runner: windows-latest | ||
| os: windows | ||
| platform: win32 | ||
| arch: arm64 | ||
| steps: | ||
| - name: Check if platform is enabled | ||
| id: check-platform | ||
| shell: bash | ||
| run: | | ||
| SHOULD_RUN="false" | ||
| if [ "${{ matrix.platform }}" = "linux" ] || [ "${{ matrix.platform }}" = "linux-musl" ]; then | ||
| if [ "${{ inputs.build-linux }}" != "false" ]; then | ||
| SHOULD_RUN="true" | ||
| fi | ||
| elif [ "${{ matrix.platform }}" = "darwin" ]; then | ||
| if [ "${{ inputs.build-macos }}" != "false" ]; then | ||
| SHOULD_RUN="true" | ||
| fi | ||
| elif [ "${{ matrix.platform }}" = "win32" ]; then | ||
| if [ "${{ inputs.build-windows }}" != "false" ]; then | ||
| SHOULD_RUN="true" | ||
| fi | ||
| fi | ||
| echo "should-run=$SHOULD_RUN" >> $GITHUB_OUTPUT | ||
| if [ "$SHOULD_RUN" = "true" ]; then | ||
| echo "✓ Building ${{ matrix.platform }}-${{ matrix.arch }}" | ||
| else | ||
| echo "⊘ Skipping ${{ matrix.platform }}-${{ matrix.arch }} (disabled by inputs)" | ||
| fi | ||
| - name: Checkout | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Setup Node.js | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 | ||
| with: | ||
| node-version-file: .node-version | ||
| - name: Setup pnpm | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 | ||
| - name: Install dependencies | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| run: pnpm install --frozen-lockfile | ||
| - name: Build CLI | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| run: pnpm --filter @socketsecurity/cli run build | ||
| - name: Download binject from socket-btm | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| id: binject | ||
| shell: bash | ||
| run: | | ||
| echo "::group::Downloading binject from socket-btm" | ||
| # Determine platform suffix for binject binary. | ||
| if [ "${{ matrix.os }}" = "darwin" ]; then | ||
| BINJECT_SUFFIX="darwin-${{ matrix.arch }}" | ||
| elif [ "${{ matrix.os }}" = "windows" ]; then | ||
| BINJECT_SUFFIX="win-${{ matrix.arch }}.exe" | ||
| elif [ "${{ matrix.platform }}" = "linux-musl" ]; then | ||
| BINJECT_SUFFIX="linux-musl-${{ matrix.arch }}" | ||
| else | ||
| BINJECT_SUFFIX="linux-${{ matrix.arch }}" | ||
| fi | ||
| # Find latest binject release. | ||
| RELEASE_DATA=$(curl -sL "https://api.github.com/repos/${SOCKET_BTM_REPO}/releases" | \ | ||
| jq -r '[.[] | select(.tag_name | startswith("binject-"))] | first') | ||
| if [ "$RELEASE_DATA" = "null" ] || [ -z "$RELEASE_DATA" ]; then | ||
| echo "::error::No binject release found in socket-btm" | ||
| exit 1 | ||
| fi | ||
| TAG=$(echo "$RELEASE_DATA" | jq -r '.tag_name') | ||
| echo "Found binject release: $TAG" | ||
| # Download binject binary. | ||
| mkdir -p .cache/binject | ||
| BINJECT_PATH=".cache/binject/binject" | ||
| if [ "${{ matrix.os }}" = "windows" ]; then | ||
| BINJECT_PATH=".cache/binject/binject.exe" | ||
| fi | ||
| curl -sL "https://github.com/${SOCKET_BTM_REPO}/releases/download/${TAG}/binject-${BINJECT_SUFFIX}" \ | ||
| -o "$BINJECT_PATH" | ||
| chmod +x "$BINJECT_PATH" | ||
| echo "binject-path=$BINJECT_PATH" >> $GITHUB_OUTPUT | ||
| echo "✓ Downloaded binject-${BINJECT_SUFFIX}" | ||
| ls -lh "$BINJECT_PATH" | ||
| echo "::endgroup::" | ||
| - name: Download node-smol from socket-btm | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| id: node-smol | ||
| shell: bash | ||
| run: | | ||
| echo "::group::Downloading node-smol from socket-btm" | ||
| # Determine platform suffix for node-smol binary. | ||
| if [ "${{ matrix.os }}" = "darwin" ]; then | ||
| NODE_SUFFIX="darwin-${{ matrix.arch }}" | ||
| elif [ "${{ matrix.os }}" = "windows" ]; then | ||
| NODE_SUFFIX="win-${{ matrix.arch }}.exe" | ||
| elif [ "${{ matrix.platform }}" = "linux-musl" ]; then | ||
| NODE_SUFFIX="linux-${{ matrix.arch }}-musl" | ||
| else | ||
| NODE_SUFFIX="linux-${{ matrix.arch }}" | ||
| fi | ||
| # Find latest node-smol release. | ||
| RELEASE_DATA=$(curl -sL "https://api.github.com/repos/${SOCKET_BTM_REPO}/releases" | \ | ||
| jq -r '[.[] | select(.tag_name | startswith("node-smol-"))] | first') | ||
| if [ "$RELEASE_DATA" = "null" ] || [ -z "$RELEASE_DATA" ]; then | ||
| echo "::error::No node-smol release found in socket-btm" | ||
| exit 1 | ||
| fi | ||
| TAG=$(echo "$RELEASE_DATA" | jq -r '.tag_name') | ||
| echo "Found node-smol release: $TAG" | ||
| # Download node-smol binary. | ||
| mkdir -p .cache/node-smol | ||
| NODE_PATH=".cache/node-smol/node" | ||
| if [ "${{ matrix.os }}" = "windows" ]; then | ||
| NODE_PATH=".cache/node-smol/node.exe" | ||
| fi | ||
| curl -sL "https://github.com/${SOCKET_BTM_REPO}/releases/download/${TAG}/node-${NODE_SUFFIX}" \ | ||
| -o "$NODE_PATH" | ||
| chmod +x "$NODE_PATH" | ||
| echo "node-path=$NODE_PATH" >> $GITHUB_OUTPUT | ||
| echo "✓ Downloaded node-${NODE_SUFFIX}" | ||
| ls -lh "$NODE_PATH" | ||
| echo "::endgroup::" | ||
| - name: Build SEA binary with binject | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| shell: bash | ||
| run: | | ||
| echo "::group::Building SEA binary with binject" | ||
| BINJECT="${STEPS_BINJECT_OUTPUTS_BINJECT_PATH}" | ||
| NODE_BINARY="${STEPS_NODE_SMOL_OUTPUTS_NODE_PATH}" | ||
| # Determine output binary name. | ||
| if [ "${{ matrix.platform }}" = "win32" ]; then | ||
| OUTPUT_NAME="socket-win-${{ matrix.arch }}.exe" | ||
| elif [ "${{ matrix.platform }}" = "darwin" ]; then | ||
| OUTPUT_NAME="socket-darwin-${{ matrix.arch }}" | ||
| elif [ "${{ matrix.platform }}" = "linux-musl" ]; then | ||
| OUTPUT_NAME="socket-linux-${{ matrix.arch }}-musl" | ||
| else | ||
| OUTPUT_NAME="socket-${{ matrix.platform }}-${{ matrix.arch }}" | ||
| fi | ||
| mkdir -p packages/cli/dist/sea | ||
| # Generate SEA config (paths relative to packages/cli). | ||
| cat > packages/cli/sea-config.json << 'SEACONFIG' | ||
| { | ||
| "main": "dist/cli.mjs", | ||
| "output": "dist/sea-prep.blob", | ||
| "disableExperimentalSEAWarning": true, | ||
| "useSnapshot": false, | ||
| "useCodeCache": true | ||
| } | ||
| SEACONFIG | ||
| # Use binject to inject SEA blob into node-smol binary. | ||
| # binject --sea with .json runs: node --experimental-sea-config <path> | ||
| cd packages/cli | ||
| echo "Running: binject inject -e node-smol --sea sea-config.json -o dist/sea/$OUTPUT_NAME" | ||
| "../../$BINJECT" inject \ | ||
| -e "../../$NODE_BINARY" \ | ||
| --sea sea-config.json \ | ||
| -o "dist/sea/$OUTPUT_NAME" | ||
| cd ../.. | ||
| chmod +x "packages/cli/dist/sea/$OUTPUT_NAME" | ||
| echo "✓ Built SEA binary: $OUTPUT_NAME" | ||
| ls -lh "packages/cli/dist/sea/$OUTPUT_NAME" | ||
| echo "::endgroup::" | ||
| env: | ||
| STEPS_BINJECT_OUTPUTS_BINJECT_PATH: ${{ steps.binject.outputs.binject-path }} | ||
| STEPS_NODE_SMOL_OUTPUTS_NODE_PATH: ${{ steps.node-smol.outputs.node-path }} | ||
| - name: Verify SEA binary | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| shell: bash | ||
| run: | | ||
| echo "=== SEA Binary Artifacts ===" | ||
| # Determine binary name. | ||
| if [ "${{ matrix.platform }}" = "win32" ]; then | ||
| BINARY_NAME="socket-win-${{ matrix.arch }}.exe" | ||
| elif [ "${{ matrix.platform }}" = "darwin" ]; then | ||
| BINARY_NAME="socket-darwin-${{ matrix.arch }}" | ||
| elif [ "${{ matrix.platform }}" = "linux-musl" ]; then | ||
| BINARY_NAME="socket-linux-${{ matrix.arch }}-musl" | ||
| else | ||
| BINARY_NAME="socket-${{ matrix.platform }}-${{ matrix.arch }}" | ||
| fi | ||
| BINARY_PATH="packages/cli/dist/sea/$BINARY_NAME" | ||
| if [ -f "$BINARY_PATH" ]; then | ||
| echo "✓ $BINARY_NAME: $(du -h $BINARY_PATH | cut -f1)" | ||
| else | ||
| echo "::error::Binary not found: $BINARY_PATH" | ||
| exit 1 | ||
| fi | ||
| - name: Copy binary to socketbin package | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| shell: bash | ||
| run: | | ||
| # Determine binary name and target package. | ||
| if [ "${{ matrix.platform }}" = "win32" ]; then | ||
| BINARY_NAME="socket-win-${{ matrix.arch }}.exe" | ||
| PACKAGE_NAME="socketbin-cli-win32-${{ matrix.arch }}" | ||
| TARGET_NAME="socket.exe" | ||
| elif [ "${{ matrix.platform }}" = "darwin" ]; then | ||
| BINARY_NAME="socket-darwin-${{ matrix.arch }}" | ||
| PACKAGE_NAME="socketbin-cli-darwin-${{ matrix.arch }}" | ||
| TARGET_NAME="socket" | ||
| elif [ "${{ matrix.platform }}" = "linux-musl" ]; then | ||
| BINARY_NAME="socket-linux-${{ matrix.arch }}-musl" | ||
| PACKAGE_NAME="socketbin-cli-linux-musl-${{ matrix.arch }}" | ||
| TARGET_NAME="socket" | ||
| else | ||
| BINARY_NAME="socket-${{ matrix.platform }}-${{ matrix.arch }}" | ||
| PACKAGE_NAME="socketbin-cli-${{ matrix.platform }}-${{ matrix.arch }}" | ||
| TARGET_NAME="socket" | ||
| fi | ||
| # Copy binary to package bin directory. | ||
| mkdir -p "packages/$PACKAGE_NAME/bin" | ||
| cp "packages/cli/dist/sea/$BINARY_NAME" "packages/$PACKAGE_NAME/bin/$TARGET_NAME" | ||
| chmod +x "packages/$PACKAGE_NAME/bin/$TARGET_NAME" | ||
| echo "✓ Copied to packages/$PACKAGE_NAME/bin/$TARGET_NAME" | ||
| - name: Upload SEA binary | ||
| if: steps.check-platform.outputs.should-run == 'true' | ||
| uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 | ||
| with: | ||
| name: socket-sea-${{ matrix.platform }}-${{ matrix.arch }} | ||
| path: packages/cli/dist/sea/socket-* | ||
| retention-days: 7 | ||
| summary: | ||
| name: 📊 SEA Build Summary | ||
| needs: [build-sea] | ||
| if: always() && !cancelled() | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Generate summary | ||
| run: | | ||
| echo "# 🌊 SEA Build Summary" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| BUILD_STATUS="${NEEDS_BUILD_SEA_RESULT}" | ||
| if [ "$BUILD_STATUS" = "failure" ]; then | ||
| echo "## ✗ Build Failed" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "One or more builds failed. Check the logs for details." >> $GITHUB_STEP_SUMMARY | ||
| elif [ "$BUILD_STATUS" = "skipped" ]; then | ||
| echo "## ⊘ Builds Skipped" >> $GITHUB_STEP_SUMMARY | ||
| else | ||
| echo "## ✓ Build Complete" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "SEA binaries built using pre-built node-smol + binject from socket-btm." >> $GITHUB_STEP_SUMMARY | ||
| fi | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "### 🎯 Platforms" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Platform | Architecture |" >> $GITHUB_STEP_SUMMARY | ||
| echo "|----------|--------------|" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Linux | x64, arm64 |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Linux (musl) | x64, arm64 |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| macOS | x64, arm64 |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Windows | x64, arm64 |" >> $GITHUB_STEP_SUMMARY | ||
| env: | ||
| NEEDS_BUILD_SEA_RESULT: ${{ needs.build-sea.result }} | ||