mirror of
https://github.com/rust-vmm/rust-vmm-ci.git
synced 2026-08-05 03:08:31 +00:00
1. Enabled the aarch64 coverage test in `test_coverage` script. 2. Seperated the coverage json sample file to two sample files for different machine achitectures. 3. Updated Buildkite pipeline container version. 4. Updated README for the description of coverage files and container version. Signed-off-by: Henry Wang <henry.wang@arm.com>
213 lines
7.7 KiB
Markdown
213 lines
7.7 KiB
Markdown
# rust-vmm-ci
|
|
|
|
The `rust-vmm-ci` repository contains [integration tests](#integration-tests)
|
|
and [Buildkite pipeline](#buildkite-pipeline) definitions that are used for
|
|
running the CI for all rust-vmm crates.
|
|
|
|
Having a centralized place for the tests is one of the enablers for keeping the
|
|
same quality standard for all crates in rust-vmm.
|
|
|
|
## Getting Started with rust-vmm-ci
|
|
|
|
To run the integration tests defined in the pipeline as part of the CI:
|
|
|
|
1. Add rust-vmm-ci as a git submodule to your repository
|
|
|
|
```bash
|
|
# Add rust-vmm-ci as a submodule. This will point to the latest rust-vmm-ci
|
|
# commit from the master branch. The following command will also add a
|
|
# `.gitmodules` file and the `rust-vmm-ci` to the index.
|
|
git submodule add https://github.com/rust-vmm/rust-vmm-ci.git
|
|
# Commit the changes to your repository so that the CI can run using the
|
|
# rust-vmm-ci pipeline and tests.
|
|
git commit -s -m "Added rust-vmm-ci as submodule"
|
|
```
|
|
|
|
2. Create the coverage test configuration file named coverage_config_ARCH.json in
|
|
the root of the repository, where ARCH is the architecture of the machine.
|
|
There are two coverage test configuration files, one per each platform.
|
|
The example of the configuration file for x86_64 architecture can be found
|
|
in [coverage_config_x86_64.json.sample](coverage_config_x86_64.json.sample),
|
|
and the example of the configuration file for aarch64 architecture can be found
|
|
in [coverage_config_aarch64.json.sample](coverage_config_aarch64.json.sample).
|
|
|
|
The json must have the following fields:
|
|
- *coverage_score*: The coverage of the repository.
|
|
- *exclude_path*: This field is used for excluding files from the report. It
|
|
should be used to exclude autogenerated files. Files in *exclude_path* are
|
|
separated by one coma. If the repository does not have any autogenerated
|
|
files, *exclude_path* should be an empty string.
|
|
- *crate_features*: `cargo kcov` does not build crate features by default. To
|
|
get the coverage report including optional features these need to be
|
|
specified in *crate_features* separated by coma. If the crate does not have
|
|
any features, this field should be empty.
|
|
|
|
This file is required for the coverage integration so it needs to be added
|
|
to the repository as well.
|
|
|
|
3. Create a new pipeline definition in Buildkite. For this step ask one of the
|
|
rust-vmm Buildkite [admins](CODEOWNERS) to create one for you. Add a pipeline
|
|
step that is uploading the rust-vmm-ci pipeline:
|
|
|
|
```bash
|
|
buildkite-agent pipeline upload rust-vmm-ci/.buildkite/pipeline.yml
|
|
```
|
|
|
|
4. The code owner of the repository will have to setup a WebHook for triggering
|
|
the CI on Pull Requests and pushes.
|
|
|
|
## Buildkite Pipeline
|
|
|
|
The [Buildkite](https://buildkite.com) pipeline is the definition of tests to
|
|
be run as part of the CI. It includes steps for running unit tests and linters
|
|
(including coding style checks), and computing the coverage.
|
|
|
|
Currently the tests can run on Linux x86_64 and aarch64 hosts.
|
|
|
|
Example of step that checks the build:
|
|
|
|
```yaml
|
|
steps:
|
|
- label: "build-gnu-x86"
|
|
commands:
|
|
- cargo build --release
|
|
retry:
|
|
automatic: false
|
|
agents:
|
|
platform: x86_64.metal
|
|
plugins:
|
|
- docker#v3.0.1:
|
|
image: "rustvmm/dev:v5"
|
|
always-pull: true
|
|
```
|
|
|
|
To see all steps in the pipeline check the
|
|
[.buikite/pipeline.yml](.buildkite/pipeline.yml) file.
|
|
|
|
### Custom Pipeline
|
|
|
|
Some crates might need to test functionality that is specific to that
|
|
particular component and thus cannot be added to the common pipeline.
|
|
|
|
In this situation, the repositories need to create a custom pipeline (besides
|
|
the rust-vmm-ci pipeline) and add it in the repository. The preferred path for
|
|
the custom pipeline is `.buildkite/pipeline.yml`.
|
|
|
|
For example to test the build with one non-default
|
|
[feature](https://doc.rust-lang.org/1.19.0/book/first-edition/conditional-compilation.html)
|
|
enabled, the following step can be added in the custom pipeline under
|
|
`.buildkite/pipeline.yml`.
|
|
|
|
```yaml
|
|
steps:
|
|
- label: "build-gnu-x86-bzimage"
|
|
commands:
|
|
- cargo build --release --features bzimage
|
|
retry:
|
|
automatic: false
|
|
agents:
|
|
platform: x86_64.metal
|
|
plugins:
|
|
- docker#v3.0.1:
|
|
image: "rustvmm/dev:v5"
|
|
always-pull: true
|
|
```
|
|
|
|
### Custom Repository Hooks
|
|
|
|
The integration tests of some repositories have dependencies on external
|
|
resources. One example is
|
|
[linux-loader](https://github.com/rust-vmm/linux-loader/) which needs to
|
|
download a bzImage before running the unit tests. Because this is specific
|
|
to the linux-loader crate, the logic for downloading the required resources
|
|
cannot be part of the common pipeline. The mechanism used here is
|
|
[Repository Hooks](https://buildkite.com/docs/agent/v3/hooks#repository-hooks).
|
|
The hooks are defined per repository and live in the crate repository under
|
|
`.buildkite/hooks`.
|
|
|
|
Example of post-checkout hook that downloads and extracts a bzImage:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
DEB_NAME="linux-image-4.9.0-9-amd64_4.9.168-1_amd64.deb"
|
|
DEB_URL="http://ftp.debian.org/debian/pool/main/l/linux/${DEB_NAME}"
|
|
|
|
REPO_PATH="${BUILDKITE_BUILD_CHECKOUT_PATH}"
|
|
DEB_PATH="${REPO_PATH}/${DEB_NAME}"
|
|
EXTRACT_PATH="${REPO_PATH}/src/bzimage-archive"
|
|
BZIMAGE_PATH="${EXTRACT_PATH}/boot/vmlinuz-4.9.0-9-amd64"
|
|
|
|
mkdir -p ${EXTRACT_PATH}
|
|
|
|
wget ${DEB_URL} -P ${REPO_PATH}
|
|
dpkg-deb -x ${DEB_PATH} ${EXTRACT_PATH}
|
|
|
|
mv ${BZIMAGE_PATH} ${REPO_PATH}/src/bzimage
|
|
rm -r ${EXTRACT_PATH}
|
|
rm -f ${DEB_PATH}
|
|
```
|
|
|
|
In this example the post-checkout hook downloads a deb image, extracts the
|
|
contents of it and places it in `linux-loader/src/bzimage`. The unit tests
|
|
will use the relative path `src/bzimage` which does not depend on the image
|
|
being downloaded.
|
|
|
|
## Integration Tests
|
|
|
|
In addition to the one-liner tests defined in the
|
|
[Builkite Pipeline](#buildkite-pipeline), the rust-vmm-ci also has more
|
|
complex tests defined in [integration_tests](integration_tests).
|
|
|
|
### Test Profiles
|
|
|
|
The integration tests support two test profiles:
|
|
- **devel**: this is the recommended profile for running the integration tests
|
|
on a local development machine.
|
|
- **ci** (default option): this is the profile used when running the
|
|
integration tests as part of the the Continuous Integration (CI).
|
|
|
|
The test profiles are applicable to tests that run using pytest. Currently only
|
|
the [coverage test](tests/test_coverage.py) follows this model as all the other
|
|
integration tests are run using the
|
|
[Buildkite pipeline](https://buildkite.com/rust-vmm/kvm-ioctls-ci).
|
|
|
|
The difference between is declaring tests as passed or failed:
|
|
- with the **devel** profile the coverage test passes if the current coverage
|
|
is equal or higher than the upstream coverage value. In case the current
|
|
coverage is higher, the coverage file is updated to the new coverage value.
|
|
- with the **ci** profile the coverage test passes only if the current coverage
|
|
is equal to the upstream coverage value.
|
|
|
|
Further details about the coverage test can be found in the
|
|
[Adaptive Coverage](#adaptive-coverage) section.
|
|
|
|
### Adaptive Coverage
|
|
|
|
The line coverage is saved in [tests/coverage](tests/coverage). To update the
|
|
coverage before submitting a PR, run the coverage test:
|
|
|
|
```bash
|
|
docker run --device=/dev/kvm \
|
|
-it \
|
|
--security-opt seccomp=unconfined \
|
|
--volume $(pwd)/kvm-ioctls:/kvm-ioctls \
|
|
rustvmm/dev:v5
|
|
cd kvm-ioctls/
|
|
pytest --profile=devel rust-vmm-ci/integration_tests/test_coverage.py
|
|
```
|
|
|
|
If the PR coverage is higher than the upstream coverage, the coverage file
|
|
needs to be manually added to the commit before submitting the PR:
|
|
|
|
```bash
|
|
git add tests/coverage
|
|
```
|
|
|
|
Failing to do so will generate a fail on the CI pipeline when publishing the
|
|
PR.
|
|
|
|
**NOTE:** The coverage file is only updated in the `devel` test profile. In
|
|
the `ci` profile the coverage test will fail if the current coverage is higher
|
|
than the coverage reported in [tests/coverage](tests/coverage)
|