Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/workflows/DailyArm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ jobs:
arch: arm64
config: ${{ matrix.config }}

# Miri on aarch64, which the build-and-test matrix no longer carries. It
# reads no guest binaries, so it waits for nothing and reports even when the
# guests fail to build.
miri:
uses: ./.github/workflows/dep_miri.yml
secrets: inherit
with:
arch: arm64

# Full aarch64 build-and-test. full_aarch64: "true" re-enables the
# single-driver steps that are skipped on PRs.
build-test:
Expand Down Expand Up @@ -100,8 +109,8 @@ jobs:
# `gh issue create` call will fail.
notify-failure:
runs-on: ubuntu-latest
needs: [build-guests, build-test, run-examples, fuzzing]
if: always() && (needs.build-guests.result == 'failure' || needs.build-test.result == 'failure' || needs.run-examples.result == 'failure' || needs.fuzzing.result == 'failure')
needs: [build-guests, miri, build-test, run-examples, fuzzing]
if: always() && (needs.build-guests.result == 'failure' || needs.miri.result == 'failure' || needs.build-test.result == 'failure' || needs.run-examples.result == 'failure' || needs.fuzzing.result == 'failure')
permissions:
# Job-level permissions replace (not merge with) the workflow-level grant,
# so contents:read must be re-declared for actions/checkout to work.
Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/RustNightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,6 @@ jobs:
- name: Build
run: just build ${{ matrix.config }}

- name: Install cargo-nextest
uses: taiki-e/install-action@4cef1412cce204788f482e778a0b9187f9626a29 # v2.87.21
with:
tool: cargo-nextest

- name: Run Miri tests
run: env -u RUSTC_WRAPPER just miri-tests

- name: Run Rust tests
run: |
# with default features
Expand Down Expand Up @@ -140,10 +132,18 @@ jobs:
RUST_LOG: debug
run: just test-rust-tracing ${{ matrix.config }}

# Miri asks nothing of a runner beyond its architecture, so it runs once on a
# hosted one rather than in every entry of the musl matrix.
miri:
uses: ./.github/workflows/dep_miri.yml
secrets: inherit
with:
arch: X64

notify-failure:
runs-on: ubuntu-latest
needs: musl
if: always() && needs.musl.result == 'failure'
needs: [musl, miri]
if: always() && (needs.musl.result == 'failure' || needs.miri.result == 'failure')
permissions:
issues: write
steps:
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/ValidatePullRequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,25 @@ jobs:
config: ${{ matrix.config }}
should_regen_goldens: ${{ needs.check-golden-label.outputs.should_regen_goldens }}

# Miri interprets rather than executing, so it reaches no hypervisor and only
# the architecture it compiles for changes what it covers. One job each is
# what the build-and-test matrix used to repeat ten times over.
miri:
Comment thread
jprendes marked this conversation as resolved.
Resolved
needs: [docs-pr, update-guest-locks]
# Required because update-guest-locks is skipped on non-dependabot PRs,
# and a skipped dependency transitively skips all downstream jobs.
# See: https://github.com/actions/runner/issues/2205
if: ${{ !cancelled() && !failure() }}
strategy:
fail-fast: false
matrix:
arch: [X64, arm64]
uses: ./.github/workflows/dep_miri.yml
secrets: inherit
with:
docs_only: ${{ needs.docs-pr.outputs.docs-only }}
arch: ${{ matrix.arch }}

# Run examples - needs guest artifacts, runs in parallel with build-test
run-examples:
needs:
Expand Down Expand Up @@ -347,6 +366,7 @@ jobs:
- update-guest-locks
- build-guests
- build-baseline-guests
- miri
- code-checks
- check-golden-label
- build-test
Expand Down
16 changes: 2 additions & 14 deletions .github/workflows/dep_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ on:
full_aarch64:
description: >-
When "true", also run the single-driver tests on aarch64. PRs leave
this "false" so the aarch64 runner builds and runs Miri and the default
Rust tests; the daily schedule (DailyArm64.yml) sets it "true". This
this "false" so the aarch64 runner builds and runs the default Rust
tests; the daily schedule (DailyArm64.yml) sets it "true". This
input only affects aarch64: it does not change X64, where those tests
already run on Linux and are skipped on Windows regardless.
required: false
Expand Down Expand Up @@ -134,18 +134,6 @@ jobs:
- name: Build
run: just build ${{ inputs.config }}

- name: Install cargo-nextest
if: runner.os == 'Linux'
uses: taiki-e/install-action@4cef1412cce204788f482e778a0b9187f9626a29 # v2.87.21
with:
tool: cargo-nextest

- name: Run Miri tests
# Linux on both architectures. arch/aarch64 carries no tests of its own
# yet, so aarch64 covers a subset until some land.
if: runner.os == 'Linux'
run: env -u RUSTC_WRAPPER just miri-tests

- name: Run Rust tests
run: |
# with default features
Expand Down
72 changes: 72 additions & 0 deletions .github/workflows/dep_miri.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json

# Reusable workflow to run the Miri tests for a single architecture.
#
# Miri interprets rather than executing, so it never reaches a hypervisor and
# nothing it does depends on which one the runner offers. It runs on the hosted
# runners for that reason. The only axis its results depend on is the target it
# compiles for, so one job per architecture covers what the whole
# build-and-test matrix used to repeat.
#
# `just miri-tests` takes no arguments. Should it ever take a profile or a
# feature, that becomes another axis and this matrix has to grow with it.

name: Miri

on:
workflow_call:
inputs:
docs_only:
description: Skip building if docs only
required: false
type: string
default: "false"
arch:
description: CPU architecture for the run, X64 or arm64 (passed from caller matrix)
required: true
type: string

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: full

permissions:
contents: read

defaults:
run:
shell: bash

jobs:
miri:
if: ${{ inputs.docs_only == 'false' }}
timeout-minutes: ${{ fromJSON(vars.MIRI_JOB_TIMEOUT || '30') }}
# Miri asks nothing of a runner beyond its architecture, so it runs on the
# hosted ones and leaves the hypervisor pools to the jobs that need them.
runs-on: ${{ inputs.arch == 'X64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

# The shared setup reads /dev/kvm to report what the runner offers, which
# a hosted one need not have. Miri wants a toolchain and two tools, so it
# asks for those rather than everything a hypervisor job needs.
- uses: dtolnay/rust-toolchain@7e38f4b43b4db5c8dd498af069a4f6196df1d067 # master
with:
toolchain: "1.94"

- uses: taiki-e/install-action@4cef1412cce204788f482e778a0b9187f9626a29 # v2.87.21
with:
tool: just,cargo-nextest

- name: Rust cache
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
shared-key: "${{ inputs.arch }}-Linux-miri"
cache-on-failure: "true"
# Only save on main as caches are not shared across branches.
save-if: ${{ github.ref == 'refs/heads/main' }}

# Miri reads no guest binaries: it covers hyperlight-common and the
# shared memory tests, neither of which loads one.
- name: Run Miri tests
run: env -u RUSTC_WRAPPER just miri-tests
8 changes: 6 additions & 2 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,14 @@ miri-jobs := env('MIRI_JOBS', num_cpus())
ensure-cargo-nextest:
{{ if os() == "windows" { "if (-not (cargo nextest --version 2>$null)) { cargo install --locked cargo-nextest }" } else { "cargo nextest --version >/dev/null 2>&1 || cargo install --locked cargo-nextest" } }}

miri-tests: (ensure-cargo-nextest)
# The pinned nightly and Miri, which a runner carries only if its image does
ensure-nightly-miri:
rustup toolchain list | grep -q '^{{nightly-toolchain}}' || rustup toolchain install {{nightly-toolchain}}
rustup +{{nightly-toolchain}} component list | grep -q 'miri.*installed' || rustup component add miri --toolchain {{nightly-toolchain}}

miri-tests: (ensure-cargo-nextest) (ensure-nightly-miri)
@# A Miri interpreter is single-threaded, so libtest's --test-threads cannot
@# use more than one core. Nextest spawns one Miri process per test.
rustup +{{nightly-toolchain}} component list | grep -q "miri.*installed" || rustup component add miri --toolchain {{nightly-toolchain}}
# We can add more as needed
cargo +{{nightly-toolchain}} miri nextest run -p hyperlight-common -F trace_guest -j {{miri-jobs}}
cargo +{{nightly-toolchain}} miri nextest run -p hyperlight-host --lib -E 'test(/mem::shared_mem::tests/)' -j {{miri-jobs}}
Expand Down
Loading