74 lines
3.5 KiB
Markdown
74 lines
3.5 KiB
Markdown
# pixi-build-rust
|
|
|
|
The container image the Gitea Actions runner uses to build Rust projects with pixi.
|
|
|
|
## What it is
|
|
|
|
A push to a Rust project runs its CI, nightly, and release workflows on a runner, and every one of those jobs needs the same Rust toolchain.
|
|
This image is the environment those jobs run in.
|
|
|
|
It is deliberately not small.
|
|
The runner host has one vCPU and a gigabyte of memory, so the slow parts of a build are downloading the toolchain and compiling from scratch.
|
|
This image front-loads both: the compiler is already in pixi's package cache before any job starts, and sccache is present so unchanged dependencies come from a cache instead of a rebuild.
|
|
A job that would otherwise spend minutes fetching rustc and gcc spends none.
|
|
|
|
Node runs the JavaScript actions Gitea uses to bootstrap a job, such as `actions/checkout`.
|
|
`git` performs the clone, commit, and push, `ca-certificates` lets it speak HTTPS, and `curl` is what the release workflow uses to call the Gitea API.
|
|
The compiler is not installed through the system package manager; it comes from pixi, along with a C compiler and pkg-config.
|
|
No credentials live in the image: the workflows authenticate with the built-in job token Gitea gives each run.
|
|
|
|
The toolchain is baked by pointing `PIXI_CACHE_DIR` at a fixed path and installing a throwaway environment at build time that pins the same `rust` version the projects use.
|
|
pixi stores the downloaded packages there, and a job's `pixi install` then hardlinks them into place without a download.
|
|
Keep the `RUST_VERSION` build argument in step with the projects' `pixi.toml`, and rebuild when it moves.
|
|
|
|
## Build
|
|
|
|
Build the image on your own machine and push it to Gitea's container registry.
|
|
The runner only ever pulls it.
|
|
|
|
You will need an access token with `package:write` access.
|
|
Authenticate Docker with it, then build for `linux/amd64`, since that is what the runner host is.
|
|
Architecture matters more here than for a lighter image: the toolchain pixi installs is built for glibc on amd64, so an `arm64` image will push but fail to start with an exec-format error.
|
|
|
|
```bash
|
|
docker login git.scient.ing
|
|
|
|
docker buildx build --platform linux/amd64 \
|
|
-t git.scient.ing/infra/pixi-build-rust:1 --push .
|
|
```
|
|
|
|
Bump the tag with a revision suffix (`:2`, `:3`) whenever the `Dockerfile` changes, including when you move the pinned `rust` or `sccache` version.
|
|
The image is always pulled by an explicit version, never `latest`, so a runner's behavior stays tied to a named artifact you can roll back to.
|
|
|
|
## Use
|
|
|
|
A runner advertises a label that maps to this image, and a project's workflows select it with `runs-on`.
|
|
|
|
```yaml
|
|
# in the runner's config.yaml
|
|
runner:
|
|
labels:
|
|
- "pixi-build-rust:docker://git.scient.ing/infra/pixi-build-rust:1"
|
|
```
|
|
|
|
```yaml
|
|
# in each Rust repository's .gitea/workflows/*.yml
|
|
jobs:
|
|
build:
|
|
runs-on: pixi-build-rust
|
|
```
|
|
|
|
The baked cache makes the first job on a fresh container fast, but job containers are removed when they finish, so anything a job writes is gone by the next run.
|
|
To keep the crate registry and the compile cache between runs, mount them as named volumes in the runner's `config.yaml`.
|
|
|
|
```yaml
|
|
# in the runner's config.yaml
|
|
container:
|
|
options: >-
|
|
-v pixi-cache:/opt/pixi/cache
|
|
-v cargo-home:/opt/cargo
|
|
-v sccache:/opt/sccache
|
|
```
|
|
|
|
Docker fills an empty named volume from the image's contents at that path the first time it is used, so the baked toolchain is present on the first job and the volume holds any later changes.
|
|
That is runner configuration, not part of this image. |