mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
The previous CI (removed in #7760) built natively inside a riscv64 QEMU VM over SSH on a self-hosted host. That setup was disabled for chronic infrastructure flakiness (#7758). Reintroduce coverage deliberately minimal: cross-compile the cloud-hypervisor binary on a stock ubuntu-latest runner, and nothing more. - No integration tests: no riscv64 hardware needed. - No clippy: cross clippy with -D warnings currently trips on riscv64-gated lints that need a separate cleanup commit first. Cross-compiling needs only a riscv64 linker, not Docker/cross: the binary does not pull openssl-sys (that arrives via a dev-dependency of test_infra, unused by -p cloud-hypervisor), so no cross sysroot is required. Signed-off-by: Gauthier Jolly <contact@gjolly.fr>
872 lines
35 KiB
YAML
872 lines
35 KiB
YAML
name: CI
|
|
on: [pull_request, merge_group]
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ github.event_name }}
|
|
cancel-in-progress: true
|
|
jobs:
|
|
preflight:
|
|
name: preflight
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
full: ${{ steps.classify.outputs.full }}
|
|
rust: ${{ steps.changes.outputs.rust }}
|
|
cargo: ${{ steps.changes.outputs.cargo }}
|
|
openapi: ${{ steps.changes.outputs.openapi }}
|
|
dockerfile: ${{ steps.changes.outputs.dockerfile }}
|
|
shell: ${{ steps.changes.outputs.shell }}
|
|
ci: ${{ steps.changes.outputs.ci }}
|
|
docs: ${{ steps.changes.outputs.docs }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- id: changes
|
|
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
|
|
with:
|
|
filters: |
|
|
rust:
|
|
- '**/*.rs'
|
|
- 'build.rs'
|
|
- '**/Cargo.toml'
|
|
- '**/Cargo.lock'
|
|
- 'rust-toolchain.toml'
|
|
cargo:
|
|
- '**/Cargo.toml'
|
|
- '**/Cargo.lock'
|
|
openapi:
|
|
- 'vmm/src/api/openapi/**'
|
|
dockerfile:
|
|
- 'resources/Dockerfile'
|
|
shell:
|
|
- '**/*.sh'
|
|
- 'scripts/**'
|
|
ci:
|
|
- '.github/workflows/**'
|
|
docs:
|
|
- 'docs/**'
|
|
- '**/*.md'
|
|
- '.github/ISSUE_TEMPLATE/**'
|
|
- 'LICENSES/**'
|
|
- 'CODEOWNERS'
|
|
- id: classify
|
|
name: Classify changes
|
|
run: |
|
|
set -eufo pipefail
|
|
full=false
|
|
if [[ "${{ steps.changes.outputs.rust }}" == "true" \
|
|
|| "${{ steps.changes.outputs.dockerfile }}" == "true" \
|
|
|| "${{ steps.changes.outputs.shell }}" == "true" \
|
|
|| "${{ steps.changes.outputs.ci }}" == "true" ]]; then
|
|
full=true
|
|
fi
|
|
echo "full=$full" >> "$GITHUB_OUTPUT"
|
|
echo "full=$full"
|
|
dco:
|
|
name: dco
|
|
needs: [preflight]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: Set up Python 3.x
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: '3.x'
|
|
- name: Check DCO
|
|
if: github.event_name == 'pull_request'
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eufo pipefail
|
|
pip3 install -U dco-check
|
|
dco-check -e "49699333+dependabot[bot]@users.noreply.github.com"
|
|
gitlint:
|
|
name: gitlint
|
|
needs: [preflight]
|
|
# PR-only: gitlint needs GITHUB_BASE_REF, unset on merge_group.
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
with:
|
|
# PR head, not the merge ref, so gitlint sees the PR's commits.
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
fetch-depth: 0
|
|
- name: Set up Python 3.10
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.10"
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install --upgrade gitlint
|
|
- name: Lint git commit messages
|
|
run: |
|
|
gitlint --commits "origin/$GITHUB_BASE_REF.."
|
|
lychee:
|
|
name: lychee
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.docs == 'true' || needs.preflight.outputs.full == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Get changed files in PR
|
|
id: changed-files
|
|
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
|
with:
|
|
base_sha: ${{ github.event.pull_request.base.sha }}
|
|
- name: Verify Changed Files
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "--- tj-actions/changed-files Outputs ---"
|
|
echo "any_changed: ${{ steps.changed-files.outputs.any_changed }}"
|
|
echo "all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}"
|
|
echo "added_files: ${{ steps.changed-files.outputs.added_files }}"
|
|
echo "modified_files: ${{ steps.changed-files.outputs.modified_files }}"
|
|
echo "deleted_files: ${{ steps.changed-files.outputs.deleted_files }}"
|
|
echo "renamed_files: ${{ steps.changed-files.outputs.renamed_files }}"
|
|
echo "----------------------------------------"
|
|
if [ -n "${{ steps.changed-files.outputs.all_changed_files }}" ]; then
|
|
echo "Detected changes: all_changed_files output is NOT empty."
|
|
else
|
|
echo "No changes detected: all_changed_files output IS empty."
|
|
fi
|
|
- name: Link Availability Check (Diff Only)
|
|
if: ${{ steps.changed-files.outputs.all_changed_files != '' }}
|
|
uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0
|
|
with:
|
|
args: --verbose --config .lychee.toml ${{ steps.changed-files.outputs.all_changed_files }}
|
|
failIfEmpty: false
|
|
fail: true
|
|
taplo:
|
|
name: taplo
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.cargo == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
- name: Install Rust toolchain
|
|
uses: dtolnay/rust-toolchain@stable
|
|
- name: Install build dependencies
|
|
run: sudo apt-get update && sudo apt-get -yqq install build-essential libssl-dev
|
|
- name: Install taplo
|
|
run: cargo install taplo-cli --locked
|
|
- name: Check formatting
|
|
run: taplo fmt --check
|
|
audit:
|
|
name: audit
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.cargo == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- uses: actions-rust-lang/audit@v1
|
|
with:
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
shlint:
|
|
name: shlint
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.shell == 'true' || needs.preflight.outputs.ci == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
- name: Run the shell script checkers
|
|
uses: luizm/action-sh-checker@883217215b11c1fabbf00eb1a9a041f62d74c744 # v0.10.0
|
|
env:
|
|
SHFMT_OPTS: -i 4 -d
|
|
SHELLCHECK_OPTS: -x --source-path scripts
|
|
hadolint:
|
|
name: hadolint
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.dockerfile == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v7
|
|
- name: Lint Dockerfile
|
|
uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0
|
|
with:
|
|
dockerfile: ./resources/Dockerfile
|
|
format: tty
|
|
no-fail: false
|
|
verbose: true
|
|
failure-threshold: info
|
|
reuse:
|
|
name: reuse
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.full == 'true' || needs.preflight.outputs.cargo == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: REUSE Compliance Check
|
|
uses: fsfe/reuse-action@v6
|
|
formatting:
|
|
name: formatting
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.full == 'true'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
rust: [nightly]
|
|
target:
|
|
- x86_64-unknown-linux-gnu
|
|
- aarch64-unknown-linux-musl
|
|
env:
|
|
RUSTFLAGS: -D warnings
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
- name: Install Rust toolchain (${{ matrix.rust }})
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
components: rustfmt
|
|
- name: Formatting (rustfmt)
|
|
run: cargo fmt --all -- --check
|
|
- name: Formatting (fuzz) (rustfmt)
|
|
run: cargo fmt --all --manifest-path fuzz/Cargo.toml -- --check
|
|
package-consistency:
|
|
name: package-consistency
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.full == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Install dependencies
|
|
run: sudo apt install -y python3
|
|
- name: Install Rust toolchain stable
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: stable
|
|
- name: Check Rust VMM Package Consistency of root Workspace
|
|
run: python3 scripts/package-consistency-check.py github.com/rust-vmm
|
|
- name: Check Rust VMM Package Consistency of fuzz Workspace
|
|
run: |
|
|
set -eufo pipefail
|
|
pushd fuzz
|
|
python3 ../scripts/package-consistency-check.py github.com/rust-vmm
|
|
popd
|
|
fuzz-build:
|
|
name: fuzz-build
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.full == 'true'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
rust: [nightly]
|
|
target: [x86_64-unknown-linux-gnu]
|
|
env:
|
|
RUSTFLAGS: -D warnings
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
- name: Install Rust toolchain (${{ matrix.rust }})
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
- name: Install Cargo fuzz
|
|
run: cargo install cargo-fuzz
|
|
- name: Fuzz Build
|
|
run: cargo fuzz build
|
|
- name: Fuzz Check
|
|
run: cargo fuzz check
|
|
openapi:
|
|
name: openapi
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.openapi == 'true'
|
|
runs-on: ubuntu-latest
|
|
container: openapitools/openapi-generator-cli
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: Validate OpenAPI
|
|
run: |
|
|
/usr/local/bin/docker-entrypoint.sh validate -i vmm/src/api/openapi/cloud-hypervisor.yaml
|
|
typos:
|
|
name: typos
|
|
needs: [preflight]
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- uses: crate-ci/typos@bee27e3a4fd1ea2111cf90ab89cd076c870fce14 # v1.48.0
|
|
quality:
|
|
name: quality
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.full == 'true'
|
|
runs-on: ubuntu-latest
|
|
# Beta clippy is non-blocking; continue-on-error below keeps the
|
|
# aggregated needs.quality.result green when only beta fails.
|
|
continue-on-error: ${{ matrix.experimental }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
rust:
|
|
- beta
|
|
- stable
|
|
target:
|
|
- aarch64-unknown-linux-gnu
|
|
- aarch64-unknown-linux-musl
|
|
- x86_64-unknown-linux-gnu
|
|
- x86_64-unknown-linux-musl
|
|
include:
|
|
- rust: beta
|
|
experimental: true
|
|
- rust: stable
|
|
experimental: false
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Install Rust toolchain (${{ matrix.rust }})
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
override: true
|
|
components: clippy
|
|
- name: Bisectability Check (default features)
|
|
if: ${{ github.event_name == 'pull_request' && matrix.target == 'x86_64-unknown-linux-gnu' }}
|
|
run: |
|
|
set -eufo pipefail
|
|
commits=$(git rev-list origin/${{ github.base_ref }}..${{ github.sha }})
|
|
for commit in $commits; do git checkout $commit; cargo check --tests --examples --all --target=${{ matrix.target }}; done
|
|
git checkout ${{ github.sha }}
|
|
- name: Clippy (kvm)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --no-default-features --tests --examples --features "kvm" -- -D warnings
|
|
- name: Clippy (mshv)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --no-default-features --tests --examples --features "mshv" -- -D warnings
|
|
- name: Clippy (mshv + kvm)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --no-default-features --tests --examples --features "mshv,kvm" -- -D warnings
|
|
- name: Clippy (default features)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --tests --examples -- -D warnings
|
|
- name: Clippy (default features + guest_debug)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --tests --examples --features "guest_debug" -- -D warnings
|
|
- name: Clippy (default features + pvmemcontrol)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --tests --examples --features "pvmemcontrol" -- -D warnings
|
|
- name: Clippy (default features + tracing)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --tests --examples --features "tracing" -- -D warnings
|
|
- name: Clippy (default features + fw_cfg)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --target=${{ matrix.target }} --locked --all --all-targets --tests --examples --features "fw_cfg" -- -D warnings
|
|
- name: Clippy (default features + ivshmem)
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --tests --examples --features "ivshmem" -- -D warnings
|
|
- name: Clippy (sev_snp)
|
|
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --no-default-features --tests --examples --features "sev_snp" -- -D warnings
|
|
- name: Clippy (igvm)
|
|
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --no-default-features --tests --examples --features "igvm" -- -D warnings
|
|
- name: Clippy (kvm + tdx)
|
|
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --no-default-features --tests --examples --features "tdx,kvm" -- -D warnings
|
|
- name: Clippy (kvm + igvm + sev_snp + fw_cfg)
|
|
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --no-default-features --tests --examples --features "kvm,igvm,sev_snp,fw_cfg" -- -D warnings
|
|
- name: Clippy (default features + sev_snp + igvm + fw_cfg)
|
|
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
|
|
uses: houseabsolute/actions-rust-cross@v1
|
|
with:
|
|
command: clippy
|
|
cross-version: 3e0957637b49b1bbced23ad909170650c5b70635
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
args: --locked --all --all-targets --tests --examples --features "sev_snp,igvm,fw_cfg" -- -D warnings
|
|
- name: Check build did not modify any files
|
|
run: test -z "$(git status --porcelain)"
|
|
build:
|
|
name: build
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.full == 'true'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
rust:
|
|
- stable
|
|
- beta
|
|
- nightly
|
|
- "1.89.0" # MSRV — keep quoted.
|
|
target:
|
|
- x86_64-unknown-linux-gnu
|
|
- x86_64-unknown-linux-musl
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Install musl-gcc
|
|
run: sudo apt install -y musl-tools
|
|
- name: Install Rust toolchain (${{ matrix.rust }})
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ matrix.rust }}
|
|
target: ${{ matrix.target }}
|
|
- name: Build (default features)
|
|
run: cargo build --locked --bin cloud-hypervisor
|
|
- name: Build (kvm)
|
|
run: cargo build --locked --bin cloud-hypervisor --no-default-features --features "kvm"
|
|
- name: Build (default features + tdx)
|
|
run: cargo build --locked --bin cloud-hypervisor --features "tdx"
|
|
- name: Build (default features + dbus_api)
|
|
run: cargo build --locked --bin cloud-hypervisor --features "dbus_api"
|
|
- name: Build (default features + guest_debug)
|
|
run: cargo build --locked --bin cloud-hypervisor --features "guest_debug"
|
|
- name: Build (default features + pvmemcontrol)
|
|
run: cargo build --locked --bin cloud-hypervisor --features "pvmemcontrol"
|
|
- name: Build (default features + fw_cfg)
|
|
run: cargo build --locked --bin cloud-hypervisor --features "fw_cfg"
|
|
- name: Build (default features + ivshmem)
|
|
run: cargo build --locked --bin cloud-hypervisor --features "ivshmem"
|
|
- name: Build (mshv)
|
|
run: cargo build --locked --bin cloud-hypervisor --no-default-features --features "mshv"
|
|
- name: Build (sev_snp)
|
|
run: cargo build --locked --bin cloud-hypervisor --no-default-features --features "sev_snp"
|
|
- name: Build (kvm + igvm + sev_snp + fw_cfg)
|
|
run: cargo build --locked --bin cloud-hypervisor --no-default-features --features "kvm,igvm,sev_snp,fw_cfg"
|
|
- name: Build (igvm)
|
|
run: cargo build --locked --bin cloud-hypervisor --no-default-features --features "igvm"
|
|
- name: Build (mshv + kvm)
|
|
run: cargo build --locked --bin cloud-hypervisor --no-default-features --features "mshv,kvm"
|
|
- name: Release Build (default features)
|
|
run: cargo build --locked --all --release --target=${{ matrix.target }}
|
|
- name: Check build did not modify any files
|
|
run: test -z "$(git status --porcelain)"
|
|
build-riscv64:
|
|
name: build-riscv64
|
|
needs: [preflight]
|
|
if: needs.preflight.outputs.full == 'true'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
rust:
|
|
- stable
|
|
- "1.89.0" # MSRV — keep quoted.
|
|
env:
|
|
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Install riscv64 cross linker
|
|
run: sudo apt-get update && sudo apt-get install -y gcc-riscv64-linux-gnu
|
|
- name: Install Rust toolchain (${{ matrix.rust }})
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ matrix.rust }}
|
|
target: riscv64gc-unknown-linux-gnu
|
|
- name: Build (kvm)
|
|
run: cargo build --locked --package cloud-hypervisor --no-default-features --features "kvm" --target riscv64gc-unknown-linux-gnu
|
|
- name: Check build did not modify any files
|
|
run: test -z "$(git status --porcelain)"
|
|
# garm-jammy + gnu: runs on PR and MQ. Other 3 matrix entries are in
|
|
# integration-x86-64-mq (sibling, MQ-only, runs in parallel).
|
|
integration-x86-64-pr:
|
|
name: integration-x86-64-pr
|
|
needs: [preflight, dco, quality, build]
|
|
if: >-
|
|
needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
timeout-minutes: 80
|
|
env:
|
|
# Our runner has 16 cores (nproc).
|
|
# We limit parallelism only to avoid exhausting disk space and memory
|
|
# resources, not to save CPU resources.
|
|
PARALLEL_INTEGRATION_TESTS_NUM: 12
|
|
runs-on: garm-jammy-16
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Install Docker
|
|
run: |
|
|
set -eufo pipefail
|
|
sudo apt-get update
|
|
sudo apt-get -y install ca-certificates curl gnupg
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
|
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
sudo apt-get update
|
|
sudo apt install -y docker-ce docker-ce-cli
|
|
- name: Prepare for VDPA
|
|
run: scripts/prepare_vdpa.sh
|
|
- name: Run unit tests
|
|
run: scripts/dev_cli.sh tests --unit --libc gnu
|
|
- name: Load openvswitch module
|
|
run: sudo modprobe openvswitch
|
|
- name: Run integration tests
|
|
timeout-minutes: 60
|
|
run: scripts/dev_cli.sh tests --integration --libc gnu
|
|
# MQ-only: the 3 matrix entries that integration-x86-64-pr does not cover.
|
|
integration-x86-64-mq:
|
|
name: integration-x86-64-mq
|
|
needs: [preflight, dco, quality, build]
|
|
if: >-
|
|
github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
timeout-minutes: 80
|
|
env:
|
|
# Our runner has 16 cores (nproc).
|
|
# We limit parallelism only to avoid exhausting disk space and memory
|
|
# resources, not to save CPU resources.
|
|
PARALLEL_INTEGRATION_TESTS_NUM: 12
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- {runner: garm-jammy, libc: musl}
|
|
- {runner: garm-jammy-amd, libc: gnu}
|
|
- {runner: garm-jammy-amd, libc: musl}
|
|
# format() because `${{ matrix.runner }}-16` is not valid in runs-on.
|
|
runs-on: ${{ format('{0}-16', matrix.runner) }}
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Install Docker
|
|
run: |
|
|
set -eufo pipefail
|
|
sudo apt-get update
|
|
sudo apt-get -y install ca-certificates curl gnupg
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
|
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
sudo apt-get update
|
|
sudo apt install -y docker-ce docker-ce-cli
|
|
- name: Prepare for VDPA
|
|
run: scripts/prepare_vdpa.sh
|
|
- name: Run unit tests
|
|
run: scripts/dev_cli.sh tests --unit --libc ${{ matrix.libc }}
|
|
- name: Load openvswitch module
|
|
run: sudo modprobe openvswitch
|
|
- name: Run integration tests
|
|
timeout-minutes: 60
|
|
run: scripts/dev_cli.sh tests --integration --libc ${{ matrix.libc }}
|
|
integration-arm64:
|
|
name: integration-arm64
|
|
needs: [preflight, dco, quality, build]
|
|
if: >-
|
|
github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
timeout-minutes: 120
|
|
env:
|
|
# Our runner has 80 cores (nproc).
|
|
# We limit parallelism only to avoid exhausting disk space and memory
|
|
# resources, not to save CPU resources.
|
|
PARALLEL_INTEGRATION_TESTS_NUM: 25
|
|
runs-on: bookworm-arm64
|
|
steps:
|
|
# arm64 runner user is "runner" (vfio's is "github-runner").
|
|
- name: Fix workspace permissions
|
|
run: sudo chown -R runner:runner ${GITHUB_WORKSPACE}
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Run unit tests (musl)
|
|
run: scripts/dev_cli.sh tests --unit --libc musl
|
|
- name: Load openvswitch module
|
|
run: sudo modprobe openvswitch
|
|
- name: Run integration tests (musl)
|
|
timeout-minutes: 60
|
|
run: scripts/dev_cli.sh tests --integration --libc musl
|
|
- name: Install Azure CLI
|
|
run: |
|
|
set -eufo pipefail
|
|
sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg
|
|
curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null
|
|
echo "deb [arch=arm64] https://packages.microsoft.com/repos/azure-cli/ bookworm main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
|
|
sudo apt update
|
|
sudo apt install -y azure-cli
|
|
- name: Download Windows image
|
|
shell: bash
|
|
run: |
|
|
set -eufo pipefail
|
|
IMG_BASENAME=windows-11-iot-enterprise-aarch64.raw
|
|
IMG_PATH=$HOME/workloads/$IMG_BASENAME
|
|
IMG_GZ_PATH=$HOME/workloads/$IMG_BASENAME.gz
|
|
IMG_GZ_BLOB_NAME=windows-11-iot-enterprise-aarch64-25h2-6.raw.gz
|
|
cp "scripts/$IMG_BASENAME.sha1" "$HOME/workloads/"
|
|
pushd "$HOME/workloads"
|
|
if sha1sum "$IMG_BASENAME.sha1" --check; then
|
|
exit
|
|
fi
|
|
popd
|
|
mkdir -p "$HOME/workloads"
|
|
rm -f "$IMG_PATH" "$IMG_GZ_PATH"
|
|
az storage blob download --container-name private-images --file "$IMG_GZ_PATH" --name "$IMG_GZ_BLOB_NAME" --connection-string "${{ secrets.CH_PRIVATE_IMAGES }}"
|
|
gzip -d "$IMG_GZ_PATH"
|
|
- name: Run Windows guest integration tests
|
|
timeout-minutes: 30
|
|
run: scripts/dev_cli.sh tests --integration-windows --libc musl
|
|
integration-vfio:
|
|
name: integration-vfio
|
|
needs: [preflight, dco, quality, build]
|
|
if: >-
|
|
github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
runs-on: vfio-nvidia
|
|
env:
|
|
AUTH_DOWNLOAD_TOKEN: ${{ secrets.AUTH_DOWNLOAD_TOKEN }}
|
|
steps:
|
|
# vfio-nvidia runner user is "github-runner" (not "runner" like arm64).
|
|
- name: Fix workspace permissions
|
|
run: sudo chown -R github-runner:github-runner "${GITHUB_WORKSPACE}"
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Run VFIO integration tests
|
|
timeout-minutes: 25
|
|
run: scripts/dev_cli.sh tests --integration-vfio
|
|
# Most tests are failing with musl, see #6790
|
|
# - name: Run VFIO integration tests for musl
|
|
# timeout-minutes: 25
|
|
# run: scripts/dev_cli.sh tests --integration-vfio --libc musl
|
|
integration-windows:
|
|
name: integration-windows
|
|
needs: [preflight, dco, quality, build]
|
|
if: >-
|
|
github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
runs-on: garm-jammy-16
|
|
steps:
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Install Docker
|
|
run: |
|
|
set -eufo pipefail
|
|
sudo apt-get update
|
|
sudo apt-get -y install ca-certificates curl gnupg
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
|
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
|
sudo apt-get update
|
|
sudo apt install -y docker-ce docker-ce-cli
|
|
- name: Install Azure CLI
|
|
run: |
|
|
set -eufo pipefail
|
|
sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg
|
|
curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null
|
|
echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ jammy main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
|
|
sudo apt update
|
|
sudo apt install -y azure-cli
|
|
- name: Download Windows image
|
|
run: |
|
|
set -eufo pipefail
|
|
mkdir $HOME/workloads
|
|
az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2025-amd64-1.raw" --name windows-server-2025-amd64-1.raw --connection-string "${{ secrets.CH_PRIVATE_IMAGES }}"
|
|
- name: Run Windows guest integration tests
|
|
timeout-minutes: 15
|
|
run: scripts/dev_cli.sh tests --integration-windows
|
|
- name: Run Windows guest integration tests for musl
|
|
timeout-minutes: 15
|
|
run: scripts/dev_cli.sh tests --integration-windows --libc musl
|
|
integration-mshv-x86-64:
|
|
name: integration-mshv-x86-64
|
|
needs: [preflight, dco, quality, build]
|
|
if: >-
|
|
github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
timeout-minutes: 35
|
|
runs-on: mshv
|
|
steps:
|
|
# mshv runner user is "lsgunner"
|
|
- name: Fix workspace and Docker socket permissions
|
|
run: |
|
|
sudo chown -R lsgrunner:lsgrunner ${GITHUB_WORKSPACE}
|
|
sudo chmod 666 /var/run/docker.sock
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Prepare for VDPA
|
|
run: scripts/prepare_vdpa.sh
|
|
- name: Run integration tests
|
|
timeout-minutes: 30
|
|
run: scripts/dev_cli.sh tests --integration
|
|
# Rate-limiter host is not available
|
|
# integration-rate-limiter:
|
|
# name: integration-rate-limiter
|
|
# needs: [preflight, dco, quality, build]
|
|
# if: >-
|
|
# github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
# runs-on: bare-metal-9950x
|
|
# env:
|
|
# AUTH_DOWNLOAD_TOKEN: ${{ secrets.AUTH_DOWNLOAD_TOKEN }}
|
|
# steps:
|
|
# - name: Code checkout
|
|
# uses: actions/checkout@v7
|
|
# with:
|
|
# fetch-depth: 0
|
|
# - name: Run rate-limiter integration tests
|
|
# timeout-minutes: 20
|
|
# run: scripts/dev_cli.sh tests --integration-rate-limiter
|
|
integration-sev-snp:
|
|
name: integration-sev-snp
|
|
needs: [preflight, dco, quality, build]
|
|
if: >-
|
|
github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
timeout-minutes: 30
|
|
runs-on: noble-sevsnp
|
|
steps:
|
|
# Self-hosted runners reuse their workdir; a previous privileged
|
|
# container run can leave root-owned files behind.
|
|
- name: Fix workspace permissions
|
|
run: sudo chown -R "$(id -un):$(id -gn)" "${GITHUB_WORKSPACE}"
|
|
- name: Code checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Sanity-check SEV-SNP prerequisites
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "Checking hypervisor device nodes..."
|
|
test -e /dev/kvm || { echo "::error::/dev/kvm missing"; exit 1; }
|
|
test -e /dev/sev || { echo "::error::/dev/sev missing"; exit 1; }
|
|
echo "Checking staged IGVM/kernel artifacts..."
|
|
test -d /usr/share/cloud-hypervisor/cvm \
|
|
|| { echo "::error::/usr/share/cloud-hypervisor/cvm missing"; exit 1; }
|
|
ls -l /usr/share/cloud-hypervisor/cvm
|
|
- name: Run CVM (SEV-SNP) integration tests
|
|
timeout-minutes: 20
|
|
run: scripts/dev_cli.sh tests --integration-cvm --hypervisor kvm
|
|
# Rate-limiter host is not available
|
|
# integration-rate-limiter:
|
|
# name: integration-rate-limiter
|
|
# needs: [preflight, dco, quality, build]
|
|
# if: >-
|
|
# github.event_name == 'merge_group' && needs.preflight.outputs.full == 'true' && needs.dco.result == 'success' && needs.quality.result == 'success' && needs.build.result == 'success'
|
|
# runs-on: bare-metal-9950x
|
|
# env:
|
|
# AUTH_DOWNLOAD_TOKEN: ${{ secrets.AUTH_DOWNLOAD_TOKEN }}
|
|
# steps:
|
|
# - name: Code checkout
|
|
# uses: actions/checkout@v7
|
|
# with:
|
|
# fetch-depth: 0
|
|
# - name: Run rate-limiter integration tests
|
|
# timeout-minutes: 20
|
|
# run: scripts/dev_cli.sh tests --integration-rate-limiter
|
|
# The single required-status check. Branch protection requires this one job.
|
|
all-green:
|
|
name: all-green
|
|
needs:
|
|
- audit
|
|
- build
|
|
- build-riscv64
|
|
- dco
|
|
- formatting
|
|
- fuzz-build
|
|
- gitlint
|
|
- hadolint
|
|
- integration-arm64
|
|
- integration-sev-snp
|
|
# VFIO worker is failing #8160
|
|
# - integration-vfio
|
|
- integration-mshv-x86-64
|
|
- integration-windows
|
|
- integration-x86-64-mq
|
|
- integration-x86-64-pr
|
|
- openapi
|
|
- package-consistency
|
|
- preflight
|
|
- quality
|
|
- reuse
|
|
- shlint
|
|
- taplo
|
|
- typos
|
|
if: always()
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Verify all dependencies succeeded or were skipped
|
|
env:
|
|
NEEDS_JSON: ${{ toJson(needs) }}
|
|
run: |
|
|
set -eufo pipefail
|
|
echo "$NEEDS_JSON" | jq .
|
|
# success or skipped = pass; failure or cancelled = red.
|
|
echo "$NEEDS_JSON" | jq -e '
|
|
to_entries
|
|
| map(select(.value.result != "success" and .value.result != "skipped"))
|
|
| length == 0
|
|
' >/dev/null
|