gpu¶
Shared base inputs plus per-step test files; a step that needs a GPU worker.
Tests that need different machines.
flowchart LR
s0["unit"]
s1["integration"]
s2["gpu"]
The steps this script plans for a push about which nothing is known. An arrow is a needs.
# Tests that need different machines.
#
# Every test step shares a base set of inputs — the source — and adds the test
# files it actually runs. A step is then reused unless the source or its own
# tests changed, and the GPU tests go only to a worker that has one.
BASE = ["src/**/*.py", "pyproject.toml", "uv.lock", "tests/conftest.py"]
def pytest(name, files, worker = {}, prefer = {}):
return step(
name,
image = "ghcr.io/astral-sh/uv:python3.13-bookworm-slim",
run = "uv sync --frozen && uv run pytest -q " + " ".join(files),
inputs = BASE + files,
worker = worker,
prefer = prefer,
)
def ci(ctx):
return [
pytest("unit", ["tests/test_runs.py", "tests/test_runs2.py"]),
pytest("integration", ["tests/integration/**/*.py"], prefer = {"speed": "fast"}),
# Waits for a GPU worker rather than failing on a machine without one.
pytest("gpu", ["tests/test_gpu.py"], worker = {"gpu": "true"}),
]
# Generated by `starci compile` from gpu.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:
# - `prefer` and `avoid` have no equivalent here and are dropped
# (integration). `worker` becomes runner labels.
# - 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:
unit:
name: "unit"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout-cone-mode: false
sparse-checkout: |
/pyproject.toml
/src/**/*.py
/tests/conftest.py
/tests/test_runs.py
/tests/test_runs2.py
/uv.lock
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-unit-338d1cbc9fe12195-${{ hashFiles('pyproject.toml', 'pyproject.toml/**', 'src/**/*.py', 'tests/conftest.py', 'tests/conftest.py/**', 'tests/test_runs.py', 'tests/test_runs.py/**', 'tests/test_runs2.py', 'tests/test_runs2.py/**', 'uv.lock', 'uv.lock/**') }}
- name: "unit"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
uv sync --frozen && uv run pytest -q tests/test_runs.py tests/test_runs2.py
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
ghcr.io/astral-sh/uv:python3.13-bookworm-slim 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"
integration:
name: "integration"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
sparse-checkout-cone-mode: false
sparse-checkout: |
/pyproject.toml
/src/**/*.py
/tests/conftest.py
/tests/integration/**/*.py
/uv.lock
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-integration-ec5d29ab03b66540-${{ hashFiles('pyproject.toml', 'pyproject.toml/**', 'src/**/*.py', 'tests/conftest.py', 'tests/conftest.py/**', 'tests/integration/**/*.py', 'uv.lock', 'uv.lock/**') }}
- name: "integration"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
uv sync --frozen && uv run pytest -q tests/integration/**/*.py
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
ghcr.io/astral-sh/uv:python3.13-bookworm-slim 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"
gpu:
name: "gpu"
runs-on: ["self-hosted", "gpu=true"]
steps:
- uses: actions/checkout@v4
with:
sparse-checkout-cone-mode: false
sparse-checkout: |
/pyproject.toml
/src/**/*.py
/tests/conftest.py
/tests/test_gpu.py
/uv.lock
- name: Has this already passed with these inputs?
id: passed
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/starci-passed
key: starci-passed-gpu-d8edba88006f9db3-${{ hashFiles('pyproject.toml', 'pyproject.toml/**', 'src/**/*.py', 'tests/conftest.py', 'tests/conftest.py/**', 'tests/test_gpu.py', 'tests/test_gpu.py/**', 'uv.lock', 'uv.lock/**') }}
- name: "gpu"
if: steps.passed.outputs.cache-hit != 'true'
env:
STARCI_RUN: |-
uv sync --frozen && uv run pytest -q tests/test_gpu.py
run: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
ghcr.io/astral-sh/uv:python3.13-bookworm-slim 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 gpu.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:
# - `worker`, `prefer` and `avoid` have no equivalent here and are dropped
# (integration, gpu): CircleCI chooses machines by resource class, not by
# label. Every job uses medium.
# - Passes are remembered in this project's CircleCI cache, which expires.
# starci's own store does not.
version: 2.1
jobs:
unit:
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 '/pyproject.toml' '/src/**/*.py' '/tests/conftest.py' '/tests/test_runs.py' '/tests/test_runs2.py' '/uv.lock'
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top,literal)pyproject.toml' ':(top,glob)src/**/*.py' ':(top,literal)tests/conftest.py' ':(top,literal)tests/test_runs.py' ':(top,literal)tests/test_runs2.py' ':(top,literal)uv.lock' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-unit-338d1cbc9fe12195-{{ 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
- run:
name: "unit"
environment:
STARCI_RUN: |-
uv sync --frozen && uv run pytest -q tests/test_runs.py tests/test_runs2.py
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
ghcr.io/astral-sh/uv:python3.13-bookworm-slim sh -c "$STARCI_RUN"
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-unit-338d1cbc9fe12195-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
integration:
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 '/pyproject.toml' '/src/**/*.py' '/tests/conftest.py' '/tests/integration/**/*.py' '/uv.lock'
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top,literal)pyproject.toml' ':(top,glob)src/**/*.py' ':(top,literal)tests/conftest.py' ':(top,glob)tests/integration/**/*.py' ':(top,literal)uv.lock' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-integration-ec5d29ab03b66540-{{ 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
- run:
name: "integration"
environment:
STARCI_RUN: |-
uv sync --frozen && uv run pytest -q tests/integration/**/*.py
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
ghcr.io/astral-sh/uv:python3.13-bookworm-slim sh -c "$STARCI_RUN"
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-integration-ec5d29ab03b66540-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
gpu:
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 '/pyproject.toml' '/src/**/*.py' '/tests/conftest.py' '/tests/test_gpu.py' '/uv.lock'
- run:
name: "Identify the inputs"
command: |
git ls-files -s -- ':(top,literal)pyproject.toml' ':(top,glob)src/**/*.py' ':(top,literal)tests/conftest.py' ':(top,literal)tests/test_gpu.py' ':(top,literal)uv.lock' > /tmp/starci-inputs
- restore_cache:
name: Has this already passed with these inputs?
keys:
- starci-passed-gpu-d8edba88006f9db3-{{ 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
- run:
name: "gpu"
environment:
STARCI_RUN: |-
uv sync --frozen && uv run pytest -q tests/test_gpu.py
command: |
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
ghcr.io/astral-sh/uv:python3.13-bookworm-slim sh -c "$STARCI_RUN"
- run:
name: "Remember this pass"
command: |
mkdir -p ~/starci-passed && date > ~/starci-passed/at
- save_cache:
key: starci-passed-gpu-d8edba88006f9db3-{{ checksum "/tmp/starci-inputs" }}
paths:
- ~/starci-passed
workflows:
ci:
jobs:
- unit
- integration
- gpu
Download: gpu.ci.star, GitHub Actions, CircleCI