mirror of
https://github.com/rust-vmm/rust-vmm-ci.git
synced 2026-08-05 03:08:31 +00:00
If we clone rust-vmm-ci with SSH Buildkite requires an ssh key when cloning the repository for some reason. Signed-off-by: Andreea Florescu <fandree@amazon.com>
209 lines
7.4 KiB
Markdown
209 lines
7.4 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.json in
|
|
the root of the repository. One example of the configuration file can be found
|
|
in [coverage_config.json.sample](coverage_config.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:v3"
|
|
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:v3"
|
|
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:v3
|
|
cd kvm-ioctls/
|
|
pytest --profile=devel 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)
|