rust¶
Cargo, with its caches kept between runs.
A Rust crate: format, lint, test, and a release build that waits for all three. Cargo's registry and target directory are kept between runs, which is most of what makes a Rust step that has to run tolerable.
flowchart LR
s0["fmt"]
s1["clippy"]
s2["test"]
s3["release build"]
s0 --> s3
s1 --> s3
s2 --> s3
The steps this script plans for a push about which nothing is known. An arrow is a needs.
# A Rust crate: format, lint, test, and a release build that waits for all
# three. Cargo's registry and target directory are kept between runs, which
# is most of what makes a Rust step that has to run tolerable.
RUST = "rust:1-slim-bookworm"
SOURCES = ["src", "tests", "Cargo.toml", "Cargo.lock"]
def cargo(name, command, needs = []):
return step(
name,
image = RUST,
run = command,
inputs = SOURCES,
needs = needs,
caches = {"cargo-registry": "/usr/local/cargo/registry", "cargo-target": "/workspace/target"},
)
def ci(ctx):
fmt = cargo("fmt", "rustup component add rustfmt && cargo fmt --check")
clippy = cargo("clippy", "rustup component add clippy && cargo clippy --all-targets -- -D warnings")
test = cargo("test", "cargo test --locked")
release = cargo("release build", "cargo build --release --locked", needs = [fmt, clippy, test])
return [fmt, clippy, test, release]
# Generated by `starci compile` from rust.ci.star. Edit that, not this.
#
# Each job is one step of the plan: the same image, command, tools and
# packages, given only the step's inputs. A job skips its work when it has
# already passed with the same inputs.
#
# What does not carry over:
# - Passes are remembered in this repository's Actions cache, which GitHub
# scopes by branch and evicts when old. starci's own store has neither
# limit.
name: CI
on:
push:
branches: ['**']
tags: ['**']
pull_request:
workflow_dispatch:
jobs:
fmt:
name: "fmt"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout-cone-mode: false
sparse-checkout: |
/Cargo.lock
/Cargo.toml
/src
/tests
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-fmt-5ad6145ce9906c86-${{ hashFiles('Cargo.lock', 'Cargo.lock/**', 'Cargo.toml', 'Cargo.toml/**', 'src', 'src/**', 'tests', 'tests/**') }}
- name: "Cache: cargo-registry"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-registry
key: starci-cache-cargo-registry-${{ github.run_id }}
restore-keys: starci-cache-cargo-registry-
- name: "Cache: cargo-target"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-target
key: starci-cache-cargo-target-${{ github.run_id }}
restore-keys: starci-cache-cargo-target-
- name: "fmt"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
rustup component add rustfmt && cargo fmt --check
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$RUNNER_TEMP/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$RUNNER_TEMP/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- name: Remember this pass
if: steps.passed.outputs.cache-hit != 'true'
run: mkdir -p "$RUNNER_TEMP/starci-passed" && date > "$RUNNER_TEMP/starci-passed/at"
clippy:
name: "clippy"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout-cone-mode: false
sparse-checkout: |
/Cargo.lock
/Cargo.toml
/src
/tests
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-clippy-9f4c64678c823d96-${{ hashFiles('Cargo.lock', 'Cargo.lock/**', 'Cargo.toml', 'Cargo.toml/**', 'src', 'src/**', 'tests', 'tests/**') }}
- name: "Cache: cargo-registry"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-registry
key: starci-cache-cargo-registry-${{ github.run_id }}
restore-keys: starci-cache-cargo-registry-
- name: "Cache: cargo-target"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-target
key: starci-cache-cargo-target-${{ github.run_id }}
restore-keys: starci-cache-cargo-target-
- name: "clippy"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
rustup component add clippy && cargo clippy --all-targets -- -D warnings
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$RUNNER_TEMP/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$RUNNER_TEMP/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- name: Remember this pass
if: steps.passed.outputs.cache-hit != 'true'
run: mkdir -p "$RUNNER_TEMP/starci-passed" && date > "$RUNNER_TEMP/starci-passed/at"
test:
name: "test"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout-cone-mode: false
sparse-checkout: |
/Cargo.lock
/Cargo.toml
/src
/tests
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-test-4b5177ea80753245-${{ hashFiles('Cargo.lock', 'Cargo.lock/**', 'Cargo.toml', 'Cargo.toml/**', 'src', 'src/**', 'tests', 'tests/**') }}
- name: "Cache: cargo-registry"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-registry
key: starci-cache-cargo-registry-${{ github.run_id }}
restore-keys: starci-cache-cargo-registry-
- name: "Cache: cargo-target"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-target
key: starci-cache-cargo-target-${{ github.run_id }}
restore-keys: starci-cache-cargo-target-
- name: "test"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
cargo test --locked
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$RUNNER_TEMP/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$RUNNER_TEMP/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- name: Remember this pass
if: steps.passed.outputs.cache-hit != 'true'
run: mkdir -p "$RUNNER_TEMP/starci-passed" && date > "$RUNNER_TEMP/starci-passed/at"
release-build:
name: "release build"
runs-on: ubuntu-latest
needs: [fmt, clippy, test]
steps:
- uses: actions/checkout@v4
with:
sparse-checkout-cone-mode: false
sparse-checkout: |
/Cargo.lock
/Cargo.toml
/src
/tests
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-release-build-f4d9509b82d7e2c2-${{ hashFiles('Cargo.lock', 'Cargo.lock/**', 'Cargo.toml', 'Cargo.toml/**', 'src', 'src/**', 'tests', 'tests/**') }}
- name: "Cache: cargo-registry"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-registry
key: starci-cache-cargo-registry-${{ github.run_id }}
restore-keys: starci-cache-cargo-registry-
- name: "Cache: cargo-target"
if: steps.passed.outputs.cache-hit != 'true'
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-cache/cargo-target
key: starci-cache-cargo-target-${{ github.run_id }}
restore-keys: starci-cache-cargo-target-
- name: "release build"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
cargo build --release --locked
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$RUNNER_TEMP/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$RUNNER_TEMP/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- name: Remember this pass
if: steps.passed.outputs.cache-hit != 'true'
run: mkdir -p "$RUNNER_TEMP/starci-passed" && date > "$RUNNER_TEMP/starci-passed/at"
# Generated by `starci compile --target circleci` from rust.ci.star. Edit that, not this.
#
# Each job is one step of the plan: the same image, command, tools and
# packages, given only the step's inputs. A job skips its work when it has
# already passed with the same inputs.
#
# What does not carry over:
# - Passes are remembered in this project's CircleCI cache, which expires.
# starci's own store does not.
version: 2.1
jobs:
fmt:
machine:
image: ubuntu-2404:current
resource_class: medium
steps:
- checkout
- run:
name: "Keep only this step's inputs"
command: |
git sparse-checkout set --no-cone '/Cargo.lock' '/Cargo.toml' '/src' '/tests'
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top,literal)Cargo.lock' ':(top,literal)Cargo.toml' ':(top,literal)src' ':(top,literal)tests' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-fmt-5ad6145ce9906c86-{{ checksum "/tmp/starci-inputs" }}
- run:
name: "Stop here if it has"
command: |
if [ -e ~/starci-passed/at ]; then
echo "Passed before with the same inputs, on $(cat ~/starci-passed/at). Nothing to do."
circleci-agent step halt
fi
- restore_cache:
name: "Cache: cargo-registry"
keys:
- starci-cache-cargo-registry-
- restore_cache:
name: "Cache: cargo-target"
keys:
- starci-cache-cargo-target-
- run:
name: "fmt"
environment:
STARCI_RUN: |-
rustup component add rustfmt && cargo fmt --check
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$HOME/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$HOME/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- save_cache:
name: "Save cache: cargo-registry"
key: starci-cache-cargo-registry-{{ .Revision }}
paths:
- ~/starci-cache/cargo-registry
- save_cache:
name: "Save cache: cargo-target"
key: starci-cache-cargo-target-{{ .Revision }}
paths:
- ~/starci-cache/cargo-target
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-fmt-5ad6145ce9906c86-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
clippy:
machine:
image: ubuntu-2404:current
resource_class: medium
steps:
- checkout
- run:
name: "Keep only this step's inputs"
command: |
git sparse-checkout set --no-cone '/Cargo.lock' '/Cargo.toml' '/src' '/tests'
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top,literal)Cargo.lock' ':(top,literal)Cargo.toml' ':(top,literal)src' ':(top,literal)tests' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-clippy-9f4c64678c823d96-{{ checksum "/tmp/starci-inputs" }}
- run:
name: "Stop here if it has"
command: |
if [ -e ~/starci-passed/at ]; then
echo "Passed before with the same inputs, on $(cat ~/starci-passed/at). Nothing to do."
circleci-agent step halt
fi
- restore_cache:
name: "Cache: cargo-registry"
keys:
- starci-cache-cargo-registry-
- restore_cache:
name: "Cache: cargo-target"
keys:
- starci-cache-cargo-target-
- run:
name: "clippy"
environment:
STARCI_RUN: |-
rustup component add clippy && cargo clippy --all-targets -- -D warnings
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$HOME/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$HOME/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- save_cache:
name: "Save cache: cargo-registry"
key: starci-cache-cargo-registry-{{ .Revision }}
paths:
- ~/starci-cache/cargo-registry
- save_cache:
name: "Save cache: cargo-target"
key: starci-cache-cargo-target-{{ .Revision }}
paths:
- ~/starci-cache/cargo-target
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-clippy-9f4c64678c823d96-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
test:
machine:
image: ubuntu-2404:current
resource_class: medium
steps:
- checkout
- run:
name: "Keep only this step's inputs"
command: |
git sparse-checkout set --no-cone '/Cargo.lock' '/Cargo.toml' '/src' '/tests'
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top,literal)Cargo.lock' ':(top,literal)Cargo.toml' ':(top,literal)src' ':(top,literal)tests' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-test-4b5177ea80753245-{{ checksum "/tmp/starci-inputs" }}
- run:
name: "Stop here if it has"
command: |
if [ -e ~/starci-passed/at ]; then
echo "Passed before with the same inputs, on $(cat ~/starci-passed/at). Nothing to do."
circleci-agent step halt
fi
- restore_cache:
name: "Cache: cargo-registry"
keys:
- starci-cache-cargo-registry-
- restore_cache:
name: "Cache: cargo-target"
keys:
- starci-cache-cargo-target-
- run:
name: "test"
environment:
STARCI_RUN: |-
cargo test --locked
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$HOME/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$HOME/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- save_cache:
name: "Save cache: cargo-registry"
key: starci-cache-cargo-registry-{{ .Revision }}
paths:
- ~/starci-cache/cargo-registry
- save_cache:
name: "Save cache: cargo-target"
key: starci-cache-cargo-target-{{ .Revision }}
paths:
- ~/starci-cache/cargo-target
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-test-4b5177ea80753245-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
release-build:
machine:
image: ubuntu-2404:current
resource_class: medium
steps:
- checkout
- run:
name: "Keep only this step's inputs"
command: |
git sparse-checkout set --no-cone '/Cargo.lock' '/Cargo.toml' '/src' '/tests'
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top,literal)Cargo.lock' ':(top,literal)Cargo.toml' ':(top,literal)src' ':(top,literal)tests' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-release-build-f4d9509b82d7e2c2-{{ checksum "/tmp/starci-inputs" }}
- run:
name: "Stop here if it has"
command: |
if [ -e ~/starci-passed/at ]; then
echo "Passed before with the same inputs, on $(cat ~/starci-passed/at). Nothing to do."
circleci-agent step halt
fi
- restore_cache:
name: "Cache: cargo-registry"
keys:
- starci-cache-cargo-registry-
- restore_cache:
name: "Cache: cargo-target"
keys:
- starci-cache-cargo-target-
- run:
name: "release build"
environment:
STARCI_RUN: |-
cargo build --release --locked
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-v "$HOME/starci-cache/cargo-registry:/usr/local/cargo/registry" \
-v "$HOME/starci-cache/cargo-target:/workspace/target" \
rust:1-slim-bookworm sh -c "$STARCI_RUN"
- save_cache:
name: "Save cache: cargo-registry"
key: starci-cache-cargo-registry-{{ .Revision }}
paths:
- ~/starci-cache/cargo-registry
- save_cache:
name: "Save cache: cargo-target"
key: starci-cache-cargo-target-{{ .Revision }}
paths:
- ~/starci-cache/cargo-target
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-release-build-f4d9509b82d7e2c2-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
workflows:
ci:
jobs:
- fmt
- clippy
- test
- release-build:
requires: [fmt, clippy, test]
Download: rust.ci.star, GitHub Actions, CircleCI