August 2023
A simple GitLab CI configuration for Rust
CI pipelines can be such a rabbit hole. Lucky for you, I dig holes for a living.
The setup below is what I found working best for me. I use it in a couple of different projects. Is this better than the official template? Yes. Should the official template just look like this instead? Probably not: I’m a code kobold, I have opinions, and my configuration is a bit opinionated.
It runs the clippy
linter and,
if linting is green, all tests. In parallel it runs a format checker. That’s it. Then again there are
a few tricks that one can pull to do the above efficiently: see the commented CI configuration below.
“Show me the code or I’ll tell the Dark Lord who has been stealing his body lotion”
Alrightalrightjeez! Just copy these two files in your repo at the locations indicated in their first lines.
It’s a simple spell, but quite unbreakable.
# .gitlab-ci.yml image: "rust:latest" variables: # move cargo data into the project directory so it can be cached CARGO_HOME: ${CI_PROJECT_DIR}/.cargo # treat compiler warnings as errors (in clippy, when running tests, etc.) RUSTFLAGS: -Dwarnings default: # cancel the job if a newer pipeline starts for the same MR or branch interruptible: true cache: # use the git branch or tag as cache key, so the cache will be # shared among CI runs for the same branch or tag key: ${CI_COMMIT_REF_SLUG} # we cache .cargo/ and target/, which effectively enables # incremental builds across different executions of the CI # for the same branch or the same merge request paths: - .cargo - target # a format check is run in parallel with the rest cargo:fmt: script: - rustup component add rustfmt - cargo fmt --check # the clippy linter runs before tests are executed cargo:clippy: script: - rustup component add clippy - cargo clippy --all-targets cargo:test: # this job is only run if clippy passes needs: ["cargo:clippy"] script: # install nextest (I swear this is the recommended way) - mkdir -p $CARGO_HOME/bin && curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C $CARGO_HOME/bin # run nextest with the "ci" profile, which produces a junit XML test report - cargo nextest run --profile ci artifacts: when: always reports: # point GitLab to the junit test report: it will automatically display it in a dashboard junit: $CI_PROJECT_DIR/target/nextest/ci/junit.xml
It is accompanied by this configuration for nextest
:
# .config/nextest.toml [profile.ci] # print out output for failing tests as soon as they fail, # and also at the end of the run (to make perusing easier) failure-output = "immediate-final" # do not bail out on the first failed test, run them all fail-fast = false [profile.ci.junit] path = "junit.xml"
Ta-daaaah! **jazz hands!**
What is this nextest
that you speak of?
I recently switched from the built-in cargo test
to nextest
as a test driver.
The main reason for the change was that, since Rust 1.70,
there is no good way that I know of to produce JUnit reports from the built-in cargo test
.
nextest
has first-class support for CI pipelines, including the production of JUnit reports
that look pretty in a GitLab dashboard. So far it gave me no reason to look back. So far…
Did you find this useful? Do you have any suggestion to improve the configuration? Let me know at codekobold@pm.me