name: Setup Node environment description: > Install Node 24 by default, pnpm, optionally Bun, and optionally run pnpm install. Requires actions/checkout to run first. inputs: node-version: description: Node.js version to install. required: false default: "24.x" install-bun: description: Whether to install Bun alongside Node. required: false default: "true" install-deps: description: Whether to run pnpm install after environment setup. required: false default: "true" frozen-lockfile: description: Whether to use --frozen-lockfile for install. required: false default: "true" use-actions-cache: description: Whether to restore and save the pnpm store with actions/cache. required: false default: "true" runs: using: composite steps: - name: Normalize container toolcache shell: bash run: | set -euo pipefail if [[ -d /__t && ! -e /opt/hostedtoolcache ]]; then mkdir -p /opt ln -s /__t /opt/hostedtoolcache fi - name: Setup Node.js shell: bash env: REQUESTED_NODE_VERSION: ${{ inputs.node-version }} run: | set -euo pipefail source "$GITHUB_ACTION_PATH/../setup-pnpm-store-cache/ensure-node.sh" openclaw_ensure_node "$REQUESTED_NODE_VERSION" - name: Setup pnpm uses: ./.github/actions/setup-pnpm-store-cache with: node-version: ${{ inputs.node-version }} use-actions-cache: ${{ inputs.use-actions-cache }} - name: Setup Bun if: inputs.install-bun == 'true' shell: bash run: | set -euo pipefail npm install -g bun@1.3.14 - name: Runtime versions shell: bash run: | node -v npm -v pnpm -v if command -v bun &>/dev/null; then bun -v; fi - name: Capture node path shell: bash run: | node_bin="$(dirname "$(node -p 'process.execPath')")" if command -v cygpath >/dev/null 2>&1; then node_bin="$(cygpath -u "$node_bin")" fi # zizmor: ignore[github-env] node_bin comes from trusted actions/setup-node output in this composite action. echo "NODE_BIN=$node_bin" >> "$GITHUB_ENV" echo "$node_bin" >> "$GITHUB_PATH" - name: Install dependencies if: inputs.install-deps == 'true' shell: bash env: CI: "true" FROZEN_LOCKFILE: ${{ inputs.frozen-lockfile }} run: | set -euo pipefail export PATH="$NODE_BIN:$PATH" which node node -v pnpm -v case "$FROZEN_LOCKFILE" in true) LOCKFILE_FLAG="--frozen-lockfile" ;; false) LOCKFILE_FLAG="" ;; *) echo "::error::Invalid frozen-lockfile input: '$FROZEN_LOCKFILE' (expected true or false)" exit 2 ;; esac install_args=( install --prefer-offline --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true --config.side-effects-cache=true ) if [ -n "$LOCKFILE_FLAG" ]; then install_args+=("$LOCKFILE_FLAG") fi append_pnpm_option_arg() { local env_name="$1" local option_name="$2" local value="${!env_name-}" if [ -n "$value" ]; then install_args+=("--${option_name}=${value}") fi } append_pnpm_option_arg PNPM_CONFIG_CHILD_CONCURRENCY child-concurrency append_pnpm_option_arg PNPM_CONFIG_MODULES_DIR modules-dir append_pnpm_option_arg PNPM_CONFIG_NETWORK_CONCURRENCY network-concurrency append_pnpm_option_arg PNPM_CONFIG_VIRTUAL_STORE_DIR virtual-store-dir if [ -n "${PNPM_CONFIG_MODULES_DIR:-}" ]; then mkdir -p "$PNPM_CONFIG_MODULES_DIR" ln -sfn . "$PNPM_CONFIG_MODULES_DIR/node_modules" fi pnpm "${install_args[@]}" || pnpm "${install_args[@]}" if [ -n "${PNPM_CONFIG_MODULES_DIR:-}" ]; then rm -rf node_modules ln -sfn "$PNPM_CONFIG_MODULES_DIR" node_modules ln -sfn . "$PNPM_CONFIG_MODULES_DIR/node_modules" fi