From 5d8eb43aa9f8b27e1e9a106daaa93d989bc503e5 Mon Sep 17 00:00:00 2001 From: Simon Davies Date: Thu, 17 Sep 2026 22:22:50 +0100 Subject: [PATCH] Support multiple Rust toolchain files Accept one or two toolchain directories and install the versions, components, and targets declared by their native rustup files. Document the breaking v2 interface and explicit default selection. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Signed-off-by: Simon Davies --- README.md | 44 ++++++++++++++----- action.yml | 127 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 119 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 8a4a18d..9acc0ae 100644 --- a/README.md +++ b/README.md @@ -9,32 +9,56 @@ jobs: setup: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 - - uses: hyperlight-dev/ci-setup-workflow@v1.0.0 - with: - rust-toolchain: "1.74.0" + - uses: hyperlight-dev/ci-setup-workflow@v2.0.0 + with: + toolchain-directories: | + . + guests + default-directory: . ``` +Check out the consumer repository before invoking the action. + ## Inputs ### Parameters | Name | Description | | ---- | ----------- | -| `rust-toolchain` | The rust toolchain version to use. | +| `toolchain-directories` | One or two newline-separated directories containing `rust-toolchain.toml` or `rust-toolchain`. Required. | +| `default-directory` | One of the listed directories, whose compiler becomes the global default. Defaults to the first entry. | +| `just-version` | Version of Just to install; defaults to `1.41`. | + +List each directory whose compiler you need installed. Paths are relative to the +checked-out workspace; absolute paths also work. Blank lines and surrounding +whitespace are ignored. + +Rustup reads the version, profile, components, and targets from each directory's +toolchain file. Put required extras such as `clippy`, `rustfmt`, +`x86_64-unknown-none`, or cross-compilation targets in those files. + +The selected compiler becomes the global default; no directory override is set. +Consumer toolchain files still select the compiler when building in their directories. +The default must select a channel or named toolchain, not an absolute compiler +`path` inside the toolchain file. Absolute directory inputs are still supported. ## Overview This action performs the following steps: -- Installs the Rust tool chain at the specified version. -- Installs additional rust components like clippy, rustfmt, ect -- Installs Just -- Sets up the clang toolchain on Linux machines (this should probably get moved into the hosted runner image setup...) -- Installs the `x86_64-pc-windows-msvc` rust target for cross-compilation on Linux machines +- Installs rustup if needed and the toolchains specified by the listed directories. +- Sets the selected default compiler. +- Installs the requested components and targets. +- Installs Just. +- Sets up the clang toolchain on Linux. +- Enables the Windows Hypervisor Platform on Windows. - Sets up environment variables needed to build / run tests based on the machine's configuration. +Runners need Bash 5 and rustup or curl. The setup action installs rustup when +missing and installs Bash through Homebrew on macOS. + ## Code of Conduct See the [Code of Conduct](./CODE_OF_CONDUCT.md). diff --git a/action.yml b/action.yml index 71dd0ad..91681c3 100644 --- a/action.yml +++ b/action.yml @@ -4,10 +4,12 @@ name: "Hyperlight Workflow Setup" description: "Common setup steps for GitHub workflows in the Hyperlight project" inputs: - rust-toolchain: - description: "(Default: 1.94.0) Rust toolchain specification to install - see https://rust-lang.github.io/rustup/concepts/toolchains.html#toolchain-specification" + toolchain-directories: + description: "One or two newline-separated directories containing Rust toolchain files." + required: true + default-directory: + description: "Directory selecting the global default compiler. Defaults to the first listed directory." required: false - default: "1.94.0" just-version: description: '(Default: 1.41) Version of just to install.' required: false @@ -16,12 +18,87 @@ runs: using: composite steps: - - uses: dtolnay/rust-toolchain@master + - name: Validate toolchain directories + id: toolchains + shell: bash + env: + TOOLCHAIN_DIRECTORIES: ${{ inputs.toolchain-directories }} + DEFAULT_DIRECTORY: ${{ inputs.default-directory }} + run: | + fail() { echo "$*" >&2; exit 1; } + trim() { printf '%s\n' "$1" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//'; } + cd "$GITHUB_WORKSPACE" + directories=() + while IFS= read -r directory; do + [[ -n "$directory" ]] || continue + [[ -f "$directory/rust-toolchain.toml" || -f "$directory/rust-toolchain" ]] || + fail "No toolchain file in directory: $directory" + directories+=("$(cd -- "$directory" && pwd -P)") + done <<< "$(trim "$TOOLCHAIN_DIRECTORIES")" + [[ "${#directories[@]}" -ge 1 && "${#directories[@]}" -le 2 ]] || + fail "Supply one or two toolchain directories." + first="${directories[0]}"; second="${directories[1]:-}" + # Normalize paths so "." and an absolute path can select the same directory. + default="$(trim "$DEFAULT_DIRECTORY")" + requested_default="${default:-$first}" + default="$(cd -- "$requested_default" && pwd -P)" || + fail "default-directory not found: $requested_default" + [[ -n "$default" && ( "$default" == "$first" || "$default" == "$second" ) ]] || + fail "default-directory must be in toolchain-directories." + if [[ "$RUNNER_OS" == Windows ]]; then + first="$(cygpath -m "$first")" + if [[ -n "$second" ]]; then second="$(cygpath -m "$second")"; fi + default="$(cygpath -m "$default")" + fi + printf 'first-directory=%s\nsecond-directory=%s\ndefault-directory=%s\n' \ + "$first" "$second" "$default" >> "$GITHUB_OUTPUT" + + - name: Install first Rust toolchain + uses: actions-rust-lang/setup-rust-toolchain@ecabd13d1c56bd1345c230e542e9144811ad706f # v2 + env: + RUSTUP_TOOLCHAIN: '' + RUSTUP_AUTO_INSTALL: '1' + CARGO_PROFILE_DEV_DEBUG: ${{ env.CARGO_PROFILE_DEV_DEBUG || '2' }} + with: + rust-src-dir: ${{ steps.toolchains.outputs.first-directory }} + override: 'false' + cache: 'false' + matcher: 'false' + build-warnings: '' + + - name: Install second Rust toolchain + if: ${{ steps.toolchains.outputs.second-directory != '' }} + uses: actions-rust-lang/setup-rust-toolchain@ecabd13d1c56bd1345c230e542e9144811ad706f # v2 + env: + RUSTUP_TOOLCHAIN: '' + RUSTUP_AUTO_INSTALL: '1' + CARGO_PROFILE_DEV_DEBUG: ${{ env.CARGO_PROFILE_DEV_DEBUG || '2' }} with: - toolchain: ${{ inputs.rust-toolchain }} - components: clippy, rustfmt - - - uses: extractions/setup-just@v4 + rust-src-dir: ${{ steps.toolchains.outputs.second-directory }} + override: 'false' + cache: 'false' + matcher: 'false' + build-warnings: '' + + - name: Select default Rust toolchain + shell: bash + env: + DEFAULT_DIRECTORY: ${{ steps.toolchains.outputs.default-directory }} + RUSTUP_AUTO_INSTALL: '0' + run: | + unset RUSTUP_TOOLCHAIN + cd -- "$DEFAULT_DIRECTORY" + selected="$(rustup show active-toolchain)" + selected="${selected%% (*}" # Strip the reason suffix, preserving spaces and parens in paths. + case "$selected" in + /*|\\*|[A-Za-z]:[\\/]*) + echo "Path-based toolchains cannot be the global default. Use a channel-based toolchain file." >&2 + exit 1 ;; + '') echo "Rustup did not report an active toolchain." >&2; exit 1 ;; + esac + rustup default "$selected" + + - uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4 with: just-version: ${{ inputs.just-version }} @@ -87,21 +164,6 @@ runs: fi shell: bash - # This is needed to build the rust guests - - name: Install x86_64-unknown-none target - if: ${{ (runner.os == 'Linux') }} - run: | - rustup target add x86_64-unknown-none - shell: bash - - # We do this in case there is toolchain skew between repos - - name: Install older rust toolchain(s) - if: ${{ (runner.os == 'Linux') }} - run: | - rustup toolchain install 1.85.0 - rustup toolchain install 1.86.0 - shell: bash - - name: Set up env vars (Linux) if: ${{ (runner.os == 'Linux') }} run: | @@ -125,25 +187,6 @@ runs: run: Enable-WindowsOptionalFeature -Online -FeatureName HyperVisorPlatform shell: pwsh - - name: Install x86_64-pc-windows-msvc target (Windows) - if: ${{ (runner.os == 'Windows') }} - run: | - rustup target add x86_64-pc-windows-msvc - shell: pwsh - - - name: Install x86_64-unknown-none target (Windows) - if: ${{ (runner.os == 'Windows') }} - run: | - rustup target add x86_64-unknown-none - shell: pwsh - - - name: Install older rust toolchain(s) (Windows) - if: ${{ (runner.os == 'Windows') }} - run: | - rustup toolchain install 1.85.0 - rustup toolchain install 1.86.0 - shell: pwsh - - name: Set up env vars (Windows) if: ${{ (runner.os == 'Windows') }} run: |