name: Prepare native runtime description: Restore and probe source-built native modules for the requested runtime. inputs: native-runtime: description: Native runtime to prepare (none, node, or electron). required: false default: none node-version: description: Resolved Node.js version provided by setup-node. required: true persist-native-cache: description: Save native modules at job end unless a later step changes their ABI. required: false default: 'true' outputs: cache-scope: description: Operating-system image scope used by the native module cache. value: ${{ steps.native-cache-scope.outputs.scope }} cache-key: description: Exact key requested for this runtime, independent of whether restoration succeeds. value: ${{ steps.native-cache-scope.outputs.key }} cache-path: description: Native build directories covered by the requested cache. value: ${{ steps.native-cache-scope.outputs.path }} cache-hit: description: Whether compiled native modules were restored under the exact requested key. value: ${{ steps.native-cache-restore.outputs.cache-hit || steps.native-cache-restore-only.outputs.cache-hit }} runs: using: composite steps: - name: Validate native runtime shell: bash env: NATIVE_RUNTIME: ${{ inputs.native-runtime }} NODE_VERSION: ${{ inputs.node-version }} run: | case "$NATIVE_RUNTIME" in none) ;; node|electron) test -n "$NODE_VERSION" ;; *) echo "::error::native-runtime must be none, node, or electron" exit 2 ;; esac # Exact keys separate runtime, architecture and host libc; every restored addon is probed. - name: Resolve native cache scope id: native-cache-scope if: inputs.native-runtime != 'none' shell: bash env: NATIVE_RUNTIME: ${{ inputs.native-runtime }} NODE_VERSION: ${{ inputs.node-version }} NATIVE_SOURCE_HASH: ${{ hashFiles('.npmrc', 'config/pnpmfile.cjs', '.github/actions/prepare-native-runtime/action.yml', 'config/scripts/native-build/node-addons/ensure-native-runtime.mjs', 'config/scripts/native-build/windows/initialize-windows-native-toolchain.mjs', 'config/scripts/native-build/windows/capture-windows-native-environment.cmd', 'config/scripts/native-build/node-addons/rebuild-native-deps.mjs', 'config/scripts/native-build/node-addons/node-pty-job-ownership.cjs', 'config/scripts/native-build/windows/windows-pe-machine.cjs', 'config/scripts/native-build/windows/windows-process-tree-gyp-rebuild.mjs', 'config/scripts/native-build/windows/windows-process-tree-creation-time.cjs', 'config/scripts/electron-installation/platform-layout/install-electron-package-binary.mjs', 'config/scripts/electron-installation/platform-layout/electron-platform-path.mjs', 'config/scripts/zip-extractor-command.mjs', 'src/shared/zip-extractor-command.ts', 'config/scripts/electron-installation/shared-dist-cache/shared-electron-dist-cache.mjs', 'config/scripts/artifact-storage/reflink-copy/space-sharing-copy.mjs', 'config/scripts/artifact-storage/atomic-publication/shared-tree-publish.mjs', 'config/scripts/native-build/node-addons/native-build-entry.cjs', 'config/scripts/native-build/node-addons/native-build-entry-probe.cjs', 'config/scripts/native-build/node-addons/shared-native-build.mjs', 'config/scripts/orcad-distribution/prebuilds/orcad-prebuild-node-gyp.mjs', 'config/scripts/native-build/windows/msbuild-file-tracking.mjs', 'config/scripts/native-build/node-addons/native-dependency-lock-digest.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch', 'native/windows-registry/src/addon.cc', 'native/windows-registry/binding.gyp', 'native/windows-registry/package.json', 'native/windows-registry/index.js', 'native/windows-security/src/addon.cc', 'native/windows-security/src/isolated-spawn.cc', 'native/windows-security/src/isolated-spawn.h', 'native/windows-security/binding.gyp', 'native/windows-security/package.json', 'native/windows-security/index.js') }} run: | scope="${ImageOS:-$RUNNER_OS}" if [ -r /etc/os-release ]; then . /etc/os-release scope="${ID:-linux}-${VERSION_ID:-unknown}" fi pnpm_version="$(pnpm --version)" test -n "$pnpm_version" # Locked native closures and the Electron release, not the whole lockfile. lock_digest="$(node config/scripts/native-build/node-addons/native-dependency-lock-digest.mjs)" test -n "$lock_digest" printf 'scope=%s\n' "$scope" >> "$GITHUB_OUTPUT" printf 'key=native-modules-%s-%s-%s-%s-node%s-pnpm%s-%s-%s\n' "$RUNNER_OS" "$scope" "$RUNNER_ARCH" "$NATIVE_RUNTIME" "$NODE_VERSION" "$pnpm_version" "$NATIVE_SOURCE_HASH" "$lock_digest" >> "$GITHUB_OUTPUT" cat >> "$GITHUB_OUTPUT" <<'ORCA_NATIVE_CACHE_PATHS' path<- inputs.native-runtime != 'none' && inputs.persist-native-cache != 'false' && !(github.event_name == 'pull_request' && (runner.os == 'Windows' || runner.os == 'Linux' && inputs.native-runtime == 'electron' && runner.environment == 'github-hosted')) uses: actions/cache@v5 with: # Post-job saving cannot resolve nested composite step outputs. path: | node_modules/.pnpm/node-pty@*/node_modules/node-pty/build native/windows-registry/build native/windows-security/build node_modules/.pnpm/@vscode+windows-process-tre*/node_modules/@vscode/windows-process-tree/build key: ${{ steps.native-cache-scope.outputs.key }} - name: Restore compiled native modules without saving id: native-cache-restore-only if: >- inputs.native-runtime != 'none' && (inputs.persist-native-cache == 'false' || github.event_name == 'pull_request' && (runner.os == 'Windows' || runner.os == 'Linux' && inputs.native-runtime == 'electron' && runner.environment == 'github-hosted')) uses: actions/cache/restore@v5 with: path: | node_modules/.pnpm/node-pty@*/node_modules/node-pty/build native/windows-registry/build native/windows-security/build node_modules/.pnpm/@vscode+windows-process-tre*/node_modules/@vscode/windows-process-tree/build key: ${{ steps.native-cache-scope.outputs.key }} # pnpm's bundled gyp_main.py is not executable; Electron rebuild uses its own node-gyp API. - name: Use external node-gyp if: runner.os == 'Linux' && inputs.native-runtime == 'node' shell: bash env: NATIVE_RUNTIME: ${{ inputs.native-runtime }} NATIVE_CACHE_HIT: ${{ steps.native-cache-restore.outputs.cache-hit || steps.native-cache-restore-only.outputs.cache-hit }} run: | # A cache hit can contain unusable addons; probe before skipping the rebuild toolchain. if [ "$NATIVE_RUNTIME" = node ] && [ "$NATIVE_CACHE_HIT" = true ] && node config/scripts/native-build/node-addons/ensure-native-runtime.mjs --check-only; then exit 0 fi npm install -g node-gyp@11.5.0 echo "npm_config_node_gyp=$(npm root -g)/node-gyp/bin/node-gyp.js" >> "$GITHUB_ENV" - name: Prepare native runtime if: inputs.native-runtime != 'none' shell: bash env: NATIVE_RUNTIME: ${{ inputs.native-runtime }} run: | if [ "$RUNNER_OS" = Windows ] && [ "$NATIVE_RUNTIME" = node ]; then node config/scripts/native-build/windows/initialize-windows-native-toolchain.mjs else node config/scripts/native-build/node-addons/ensure-native-runtime.mjs --runtime="$NATIVE_RUNTIME" fi