From 650d1ce624707780823b48a1a2051074ef333f09 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:06:06 -0800 Subject: [PATCH 01/15] wip --- .github/workflows/ci-image.yml | 74 ++++++++++++++++++++++++++++++++++ .github/workflows/python.yml | 32 +++++++++++++++ .github/workflows/rust.yml | 34 ++++++++++++++++ build/docker.toml | 40 ++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 .github/workflows/ci-image.yml create mode 100644 .github/workflows/python.yml create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/ci-image.yml b/.github/workflows/ci-image.yml new file mode 100644 index 00000000..d53ed651 --- /dev/null +++ b/.github/workflows/ci-image.yml @@ -0,0 +1,74 @@ +name: CI Image + +on: + push: + branches: [main] + paths: + - 'deploy/docker/Dockerfile.ci' + - 'mise.toml' + - 'build/**' + - '.github/workflows/ci-image.yml' + pull_request: + branches: [main] + paths: + - 'deploy/docker/Dockerfile.ci' + - 'mise.toml' + - 'build/**' + - '.github/workflows/ci-image.yml' + +env: + REGISTRY: ghcr.io + CI_IMAGE: ghcr.io/${{ github.repository }}/ci + +permissions: + contents: read + packages: write + +jobs: + build-ci-image: + name: Build CI Image + runs-on: build-amd64 + steps: + - uses: actions/checkout@v4 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Install mise + uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 + with: + install: false + + - name: Set up Docker Buildx + run: mise run docker:buildx:setup + env: + MISE_AUTO_INSTALL: "0" + MISE_TASK_RUN_AUTO_INSTALL: "0" + MISE_NOT_FOUND_AUTO_INSTALL: "0" + + - name: Build CI image + if: github.ref != 'refs/heads/main' + run: | + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --cache-from type=registry,ref=${{ env.CI_IMAGE }}:buildcache \ + -t ${{ env.CI_IMAGE }}:${{ github.sha }} \ + -f deploy/docker/Dockerfile.ci \ + . + + - name: Build and push CI image + if: github.ref == 'refs/heads/main' + run: | + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --cache-from type=registry,ref=${{ env.CI_IMAGE }}:buildcache \ + --cache-to type=registry,ref=${{ env.CI_IMAGE }}:buildcache,mode=max \ + --push \ + -t ${{ env.CI_IMAGE }}:${{ github.sha }} \ + -t ${{ env.CI_IMAGE }}:latest \ + -f deploy/docker/Dockerfile.ci \ + . diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 00000000..eaa986af --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,32 @@ +name: Python + +on: + pull_request: + +env: + REGISTRY: ghcr.io + +permissions: + contents: read + packages: read + +jobs: + python: + name: Python + runs-on: build-amd64 + container: + image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: uv sync --frozen + + - name: Lint + run: mise run python:lint + + - name: Test + run: mise run test:python diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 00000000..7e638e4b --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,34 @@ +name: Rust + +on: + pull_request: + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: "0" + REGISTRY: ghcr.io + +permissions: + contents: read + packages: read + +jobs: + rust: + name: Rust + runs-on: build-amd64 + container: + image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - name: Check formatting + run: mise run fmt:check + + - name: Clippy + run: mise run clippy + + - name: Test + run: mise run test:rust diff --git a/build/docker.toml b/build/docker.toml index 1c9ca451..8c597074 100644 --- a/build/docker.toml +++ b/build/docker.toml @@ -1,5 +1,45 @@ # Docker image build tasks +["docker:buildx:setup"] +description = "Create a multi-arch buildx builder with remote BuildKit nodes" +usage = """ +flag "--amd64 " default="tcp://buildkit-amd64.buildkit:1234" help="BuildKit endpoint for linux/amd64" +flag "--arm64 " default="tcp://buildkit-arm64.buildkit:1234" help="BuildKit endpoint for linux/arm64" +flag "--name " default="navigator" help="Builder instance name" +""" +run = """ +#!/usr/bin/env bash +set -euo pipefail + +BUILDER="${usage_name}" +AMD64="${usage_amd64}" +ARM64="${usage_arm64}" + +# Remove existing builder if present so we get a clean config +if docker buildx inspect "${BUILDER}" >/dev/null 2>&1; then + echo "Removing existing builder: ${BUILDER}" + docker buildx rm "${BUILDER}" +fi + +echo "Creating builder: ${BUILDER}" +docker buildx create \ + --name "${BUILDER}" \ + --driver remote \ + --platform linux/amd64 \ + "${AMD64}" + +docker buildx create \ + --name "${BUILDER}" \ + --append \ + --driver remote \ + --platform linux/arm64 \ + "${ARM64}" + +docker buildx use "${BUILDER}" +echo "Builder '${BUILDER}' is now active:" +docker buildx inspect "${BUILDER}" +""" + ["docker:build"] description = "Build all Docker images" depends = [ From 4f482afa70d4ef17ae4995799ded1b97b1302ccb Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:13:10 -0800 Subject: [PATCH 02/15] wip --- .github/workflows/ci-image.yml | 2 +- .github/workflows/python.yml | 5 +---- .github/workflows/rust.yml | 9 ++++----- CONTRIBUTING.md | 8 ++++---- build/ci.toml | 4 ++-- build/python.toml | 2 +- build/rust.toml | 8 ++++---- 7 files changed, 17 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci-image.yml b/.github/workflows/ci-image.yml index d53ed651..8e59adbe 100644 --- a/.github/workflows/ci-image.yml +++ b/.github/workflows/ci-image.yml @@ -18,7 +18,7 @@ on: env: REGISTRY: ghcr.io - CI_IMAGE: ghcr.io/${{ github.repository }}/ci + CI_IMAGE: ghcr.io/nvidia/nv-agent-env/ci permissions: contents: read diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index eaa986af..069aa65d 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -3,9 +3,6 @@ name: Python on: pull_request: -env: - REGISTRY: ghcr.io - permissions: contents: read packages: read @@ -15,7 +12,7 @@ jobs: name: Python runs-on: build-amd64 container: - image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + image: ghcr.io/nvidia/nv-agent-env/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7e638e4b..393c4614 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -6,7 +6,6 @@ on: env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: "0" - REGISTRY: ghcr.io permissions: contents: read @@ -17,7 +16,7 @@ jobs: name: Rust runs-on: build-amd64 container: - image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + image: ghcr.io/nvidia/nv-agent-env/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} @@ -25,10 +24,10 @@ jobs: - uses: actions/checkout@v4 - name: Check formatting - run: mise run fmt:check + run: mise run rust:format:check - - name: Clippy - run: mise run clippy + - name: Lint + run: mise run rust:lint - name: Test run: mise run test:rust diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e45063e2..7168f457 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -154,12 +154,12 @@ mise run test:e2e:sandbox # Sandbox Python e2e tests ```bash # Rust -mise run fmt # Format code -mise run fmt:check # Check formatting -mise run clippy # Run Clippy lints +mise run rust:format # Format code +mise run rust:format:check # Check formatting +mise run rust:lint # Lint with Clippy # Python -mise run python:fmt # Format with ruff +mise run python:format # Format with ruff mise run python:lint # Lint with ruff mise run python:typecheck # Type check with ty diff --git a/build/ci.toml b/build/ci.toml index fb90abc8..d8feace5 100644 --- a/build/ci.toml +++ b/build/ci.toml @@ -1,8 +1,8 @@ # CI, pre-commit, and sandbox runner tasks [lint] -description = "Run all linters (fmt, clippy, ruff)" -depends = ["fmt:check", "clippy", "python:lint"] +description = "Run all linters and format checks" +depends = ["rust:format:check", "rust:lint", "python:lint"] [all] description = "Build, lint, and test everything" diff --git a/build/python.toml b/build/python.toml index bdcf4930..be308759 100644 --- a/build/python.toml +++ b/build/python.toml @@ -112,7 +112,7 @@ depends = ["python:proto"] env = { UV_NO_SYNC = "1" } run = "uv run ruff check {{vars.python_paths}}" -["python:fmt"] +["python:format"] description = "Format Python code with ruff" run = "uv run ruff format {{vars.python_paths}}" diff --git a/build/rust.toml b/build/rust.toml index b5b568e5..f3771f6b 100644 --- a/build/rust.toml +++ b/build/rust.toml @@ -12,15 +12,15 @@ run = "cargo build --workspace --release" description = "Check all Rust crates for errors" run = "cargo check --workspace" -[clippy] -description = "Run Clippy lints" +["rust:lint"] +description = "Lint Rust code with Clippy" run = "cargo clippy --workspace --all-targets" -[fmt] +["rust:format"] description = "Format Rust code" run = "cargo fmt --all" -["fmt:check"] +["rust:format:check"] description = "Check Rust formatting" run = "cargo fmt --all -- --check" From 598bf9044532874dc9d22bf44134cb252def6d9e Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:14:18 -0800 Subject: [PATCH 03/15] wip --- .github/workflows/python.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 069aa65d..13c7238f 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -9,7 +9,6 @@ permissions: jobs: python: - name: Python runs-on: build-amd64 container: image: ghcr.io/nvidia/nv-agent-env/ci:latest From 08ffe3409d02fed3ac7f9bfb5cd7def2aceb0847 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:20:12 -0800 Subject: [PATCH 04/15] ci: consolidate rust and python workflows into single checks workflow --- .github/workflows/checks.yml | 62 ++++++++++++++++++++++++++++++++++++ .github/workflows/python.yml | 28 ---------------- .github/workflows/rust.yml | 33 ------------------- 3 files changed, 62 insertions(+), 61 deletions(-) create mode 100644 .github/workflows/checks.yml delete mode 100644 .github/workflows/python.yml delete mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 00000000..39e7f5d7 --- /dev/null +++ b/.github/workflows/checks.yml @@ -0,0 +1,62 @@ +name: Checks + +on: + push: + branches: [main] + pull_request: + +env: + CARGO_TERM_COLOR: always + CARGO_INCREMENTAL: "0" + REGISTRY: ghcr.io + +permissions: + contents: read + packages: read + +jobs: + rust: + name: Rust + runs-on: build-amd64 + container: + image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - name: Install tools + run: mise install + + - name: Format + run: mise run rust:format:check + + - name: Lint + run: mise run rust:lint + + - name: Test + run: mise run test:rust + + python: + name: Python + runs-on: build-amd64 + container: + image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + credentials: + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - name: Install tools + run: mise install + + - name: Install dependencies + run: uv sync --frozen + + - name: Lint + run: mise run python:lint + + - name: Test + run: mise run test:python diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml deleted file mode 100644 index 13c7238f..00000000 --- a/.github/workflows/python.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Python - -on: - pull_request: - -permissions: - contents: read - packages: read - -jobs: - python: - runs-on: build-amd64 - container: - image: ghcr.io/nvidia/nv-agent-env/ci:latest - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - name: Install dependencies - run: uv sync --frozen - - - name: Lint - run: mise run python:lint - - - name: Test - run: mise run test:python diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml deleted file mode 100644 index 393c4614..00000000 --- a/.github/workflows/rust.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Rust - -on: - pull_request: - -env: - CARGO_TERM_COLOR: always - CARGO_INCREMENTAL: "0" - -permissions: - contents: read - packages: read - -jobs: - rust: - name: Rust - runs-on: build-amd64 - container: - image: ghcr.io/nvidia/nv-agent-env/ci:latest - credentials: - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - steps: - - uses: actions/checkout@v4 - - - name: Check formatting - run: mise run rust:format:check - - - name: Lint - run: mise run rust:lint - - - name: Test - run: mise run test:rust From 915f2da94dcffccbaae99c0cc4762404af006a31 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:21:03 -0800 Subject: [PATCH 05/15] ci: fix container image reference in checks workflow --- .github/workflows/checks.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 39e7f5d7..f261b588 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -8,7 +8,6 @@ on: env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: "0" - REGISTRY: ghcr.io permissions: contents: read @@ -19,7 +18,7 @@ jobs: name: Rust runs-on: build-amd64 container: - image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + image: ghcr.io/${{ github.repository }}/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} @@ -42,7 +41,7 @@ jobs: name: Python runs-on: build-amd64 container: - image: ${{ env.REGISTRY }}/${{ github.repository }}/ci:latest + image: ghcr.io/${{ github.repository }}/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} From a15ad57f32896da04958ccf61a9dfb6e0bb35df9 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:22:40 -0800 Subject: [PATCH 06/15] ci: use hardcoded lowercase image ref for GHCR compatibility --- .github/workflows/checks.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index f261b588..18bb98ac 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -18,7 +18,7 @@ jobs: name: Rust runs-on: build-amd64 container: - image: ghcr.io/${{ github.repository }}/ci:latest + image: ghcr.io/nvidia/nv-agent-env/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} @@ -41,7 +41,7 @@ jobs: name: Python runs-on: build-amd64 container: - image: ghcr.io/${{ github.repository }}/ci:latest + image: ghcr.io/nvidia/nv-agent-env/ci:latest credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} From 3c794de7190202fff9148a938c3cd1b24dcdb9f4 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:26:50 -0800 Subject: [PATCH 07/15] ci: add mise reshim to regenerate shims after install --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 18bb98ac..c0816682 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v4 - name: Install tools - run: mise install + run: mise install && mise reshim - name: Format run: mise run rust:format:check From 978bc8ad46a58439eeaca2ec970f0eca68a13bd7 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:29:22 -0800 Subject: [PATCH 08/15] ci: add cargo bin to PATH in CI image and remove unnecessary mise install steps --- .github/workflows/checks.yml | 6 ------ deploy/docker/Dockerfile.ci | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index c0816682..09c28ab9 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -25,9 +25,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install tools - run: mise install && mise reshim - - name: Format run: mise run rust:format:check @@ -48,9 +45,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install tools - run: mise install - - name: Install dependencies run: uv sync --frozen diff --git a/deploy/docker/Dockerfile.ci b/deploy/docker/Dockerfile.ci index 6dacbdd5..173732bb 100644 --- a/deploy/docker/Dockerfile.ci +++ b/deploy/docker/Dockerfile.ci @@ -15,7 +15,7 @@ ARG SCCACHE_VERSION=v0.14.0 ENV DEBIAN_FRONTEND=noninteractive ENV MISE_DATA_DIR=/opt/mise ENV MISE_CACHE_DIR=/opt/mise/cache -ENV PATH="/opt/mise/shims:/root/.local/bin:$PATH" +ENV PATH="/opt/mise/shims:/root/.cargo/bin:/root/.local/bin:$PATH" # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ From dd1cfdbebc26d09fb3989c90fb759c40ae99955f Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:29:44 -0800 Subject: [PATCH 09/15] ci: add cargo bin to GITHUB_PATH for rust job --- .github/workflows/checks.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 09c28ab9..48073665 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -25,6 +25,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Setup Rust PATH + run: echo "/root/.cargo/bin" >> "$GITHUB_PATH" + - name: Format run: mise run rust:format:check From eea2d57024b02e0138324e91ffc0ce05004222f3 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:38:54 -0800 Subject: [PATCH 10/15] ci: allow manual CI image build+push via workflow_dispatch --- .github/workflows/ci-image.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-image.yml b/.github/workflows/ci-image.yml index 8e59adbe..6a7b8a18 100644 --- a/.github/workflows/ci-image.yml +++ b/.github/workflows/ci-image.yml @@ -15,6 +15,7 @@ on: - 'mise.toml' - 'build/**' - '.github/workflows/ci-image.yml' + workflow_dispatch: env: REGISTRY: ghcr.io @@ -26,7 +27,7 @@ permissions: jobs: build-ci-image: - name: Build CI Image + name: Build runs-on: build-amd64 steps: - uses: actions/checkout@v4 @@ -51,7 +52,7 @@ jobs: MISE_NOT_FOUND_AUTO_INSTALL: "0" - name: Build CI image - if: github.ref != 'refs/heads/main' + if: github.event_name == 'pull_request' run: | docker buildx build \ --platform linux/amd64,linux/arm64 \ @@ -61,7 +62,7 @@ jobs: . - name: Build and push CI image - if: github.ref == 'refs/heads/main' + if: github.event_name != 'pull_request' run: | docker buildx build \ --platform linux/amd64,linux/arm64 \ From 82f3e12554b9e9b9bdb720087a5d06ad6edb281d Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 08:42:14 -0800 Subject: [PATCH 11/15] ci: simplify ci-image triggers and remove rust PATH workaround --- .github/workflows/checks.yml | 3 --- .github/workflows/ci-image.yml | 18 ------------------ 2 files changed, 21 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 48073665..09c28ab9 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -25,9 +25,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Setup Rust PATH - run: echo "/root/.cargo/bin" >> "$GITHUB_PATH" - - name: Format run: mise run rust:format:check diff --git a/.github/workflows/ci-image.yml b/.github/workflows/ci-image.yml index 6a7b8a18..95b832a7 100644 --- a/.github/workflows/ci-image.yml +++ b/.github/workflows/ci-image.yml @@ -8,13 +8,6 @@ on: - 'mise.toml' - 'build/**' - '.github/workflows/ci-image.yml' - pull_request: - branches: [main] - paths: - - 'deploy/docker/Dockerfile.ci' - - 'mise.toml' - - 'build/**' - - '.github/workflows/ci-image.yml' workflow_dispatch: env: @@ -51,18 +44,7 @@ jobs: MISE_TASK_RUN_AUTO_INSTALL: "0" MISE_NOT_FOUND_AUTO_INSTALL: "0" - - name: Build CI image - if: github.event_name == 'pull_request' - run: | - docker buildx build \ - --platform linux/amd64,linux/arm64 \ - --cache-from type=registry,ref=${{ env.CI_IMAGE }}:buildcache \ - -t ${{ env.CI_IMAGE }}:${{ github.sha }} \ - -f deploy/docker/Dockerfile.ci \ - . - - name: Build and push CI image - if: github.event_name != 'pull_request' run: | docker buildx build \ --platform linux/amd64,linux/arm64 \ From 616bc6c7d65e91d4824e650632f86f0025a655f5 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 09:19:55 -0800 Subject: [PATCH 12/15] ci: install all tools via mise in CI image to prevent re-downloads --- .github/workflows/checks.yml | 3 +++ deploy/docker/Dockerfile.ci | 42 ++---------------------------------- 2 files changed, 5 insertions(+), 40 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 09c28ab9..ee57b136 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -8,6 +8,9 @@ on: env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: "0" + MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MISE_AUTO_INSTALL: "0" + MISE_NOT_FOUND_AUTO_INSTALL: "0" permissions: contents: read diff --git a/deploy/docker/Dockerfile.ci b/deploy/docker/Dockerfile.ci index 173732bb..64e887b6 100644 --- a/deploy/docker/Dockerfile.ci +++ b/deploy/docker/Dockerfile.ci @@ -7,10 +7,6 @@ FROM ubuntu:24.04 ARG DOCKER_VERSION=27.5.1 ARG BUILDX_VERSION=v0.21.1 ARG TARGETARCH -ARG KUBECTL_VERSION=v1.35.1 -ARG HELM_VERSION=v4.1.1 -ARG PROTOC_VERSION=29.6 -ARG SCCACHE_VERSION=v0.14.0 ENV DEBIAN_FRONTEND=noninteractive ENV MISE_DATA_DIR=/opt/mise @@ -28,7 +24,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3 \ python3-venv \ cmake \ - protobuf-compiler \ socat \ unzip \ xz-utils \ @@ -58,50 +53,17 @@ RUN case "$TARGETARCH" in \ && /tmp/aws/install \ && rm -rf /tmp/aws /tmp/awscliv2.zip -# Install kubectl, helm, and protoc without GitHub API lookups -RUN case "$TARGETARCH" in \ - amd64) karch=amd64; helm_arch=amd64; protoc_arch=x86_64 ;; \ - arm64) karch=arm64; helm_arch=arm64; protoc_arch=aarch_64 ;; \ - *) echo "Unsupported TARGETARCH: $TARGETARCH"; exit 1 ;; \ - esac \ - && curl -fsSL "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${karch}/kubectl" -o /usr/local/bin/kubectl \ - && chmod +x /usr/local/bin/kubectl \ - && curl -fsSL "https://get.helm.sh/helm-${HELM_VERSION}-linux-${helm_arch}.tar.gz" -o /tmp/helm.tgz \ - && tar -xzf /tmp/helm.tgz -C /tmp \ - && mv "/tmp/linux-${helm_arch}/helm" /usr/local/bin/helm \ - && chmod +x /usr/local/bin/helm \ - && rm -rf /tmp/helm.tgz "/tmp/linux-${helm_arch}" \ - && curl -fsSL "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${protoc_arch}.zip" -o /tmp/protoc.zip \ - && unzip -q /tmp/protoc.zip -d /tmp/protoc \ - && mv /tmp/protoc/bin/protoc /usr/local/bin/protoc \ - && chmod +x /usr/local/bin/protoc \ - && rm -rf /tmp/protoc /tmp/protoc.zip - -# Install sccache directly on amd64 (mise/aqua plugin is arch-limited) -RUN if [ "$TARGETARCH" = "amd64" ]; then \ - curl -fsSL "https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz" -o /tmp/sccache.tgz \ - && tar -xzf /tmp/sccache.tgz -C /tmp \ - && mv "/tmp/sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl/sccache" /usr/local/bin/sccache \ - && chmod +x /usr/local/bin/sccache \ - && rm -rf /tmp/sccache.tgz "/tmp/sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl"; \ - else \ - echo "Skipping sccache install on $TARGETARCH"; \ - fi - # Install mise RUN curl https://mise.run | sh -# Copy mise.toml and build task includes, then install core tools +# Copy mise.toml and build task includes, then install all tools via mise COPY mise.toml /opt/mise/mise.toml COPY build/ /opt/mise/build/ WORKDIR /opt/mise RUN mise trust /opt/mise/mise.toml && \ - env -u RUSTC_WRAPPER mise install python rust 'cargo:cargo-edit' && \ + env -u RUSTC_WRAPPER mise install && \ /root/.cargo/bin/rustup component remove rust-docs || true && \ rm -rf /root/.rustup/toolchains/*/share/doc /root/.rustup/toolchains/*/share/man -# Install uv directly to avoid GitHub API rate limits in CI image builds -RUN curl -LsSf https://astral.sh/uv/0.10.2/install.sh | sh - # Set working directory for CI jobs WORKDIR /builds From 2d0df738a8555ae347714b6bed1266ed5d7dd699 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 09:44:17 -0800 Subject: [PATCH 13/15] wip --- .github/workflows/checks.yml | 2 -- .github/workflows/ci-image.yml | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index ee57b136..48b93cfa 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -9,8 +9,6 @@ env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: "0" MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - MISE_AUTO_INSTALL: "0" - MISE_NOT_FOUND_AUTO_INSTALL: "0" permissions: contents: read diff --git a/.github/workflows/ci-image.yml b/.github/workflows/ci-image.yml index 95b832a7..ed5f98ef 100644 --- a/.github/workflows/ci-image.yml +++ b/.github/workflows/ci-image.yml @@ -39,10 +39,6 @@ jobs: - name: Set up Docker Buildx run: mise run docker:buildx:setup - env: - MISE_AUTO_INSTALL: "0" - MISE_TASK_RUN_AUTO_INSTALL: "0" - MISE_NOT_FOUND_AUTO_INSTALL: "0" - name: Build and push CI image run: | @@ -50,6 +46,7 @@ jobs: --platform linux/amd64,linux/arm64 \ --cache-from type=registry,ref=${{ env.CI_IMAGE }}:buildcache \ --cache-to type=registry,ref=${{ env.CI_IMAGE }}:buildcache,mode=max \ + --build-arg MISE_GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} \ --push \ -t ${{ env.CI_IMAGE }}:${{ github.sha }} \ -t ${{ env.CI_IMAGE }}:latest \ From 8ecc083681db59065bcf9857174e5a11f927f21e Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 09:50:42 -0800 Subject: [PATCH 14/15] ci: replace docker:buildx:setup mise task with reusable setup-buildx action Use docker/setup-buildx-action@v3 wrapped in a local composite action to create the multi-arch remote BuildKit builder. This ensures automatic cleanup of builder nodes when the job finishes, preventing leaked BuildKit instances on self-hosted runners. --- .github/actions/setup-buildx/action.yml | 30 +++++++++++++++++++ .github/workflows/ci-image.yml | 7 +---- build/docker.toml | 40 ------------------------- 3 files changed, 31 insertions(+), 46 deletions(-) create mode 100644 .github/actions/setup-buildx/action.yml diff --git a/.github/actions/setup-buildx/action.yml b/.github/actions/setup-buildx/action.yml new file mode 100644 index 00000000..6d5627e8 --- /dev/null +++ b/.github/actions/setup-buildx/action.yml @@ -0,0 +1,30 @@ +name: Setup Docker Buildx +description: > + Create a multi-arch Docker Buildx builder using remote BuildKit nodes. + The builder is automatically removed when the job finishes (cleanup is + enabled by default in docker/setup-buildx-action). + +inputs: + amd64-endpoint: + description: BuildKit endpoint for linux/amd64 + default: tcp://buildkit-amd64.buildkit:1234 + arm64-endpoint: + description: BuildKit endpoint for linux/arm64 + default: tcp://buildkit-arm64.buildkit:1234 + name: + description: Builder instance name + default: navigator + +runs: + using: composite + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + name: ${{ inputs.name }} + driver: remote + endpoint: ${{ inputs.amd64-endpoint }} + platforms: linux/amd64 + append: | + - endpoint: ${{ inputs.arm64-endpoint }} + platforms: linux/arm64 diff --git a/.github/workflows/ci-image.yml b/.github/workflows/ci-image.yml index ed5f98ef..8410fdd5 100644 --- a/.github/workflows/ci-image.yml +++ b/.github/workflows/ci-image.yml @@ -32,13 +32,8 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Install mise - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 - with: - install: false - - name: Set up Docker Buildx - run: mise run docker:buildx:setup + uses: ./.github/actions/setup-buildx - name: Build and push CI image run: | diff --git a/build/docker.toml b/build/docker.toml index 8c597074..1c9ca451 100644 --- a/build/docker.toml +++ b/build/docker.toml @@ -1,45 +1,5 @@ # Docker image build tasks -["docker:buildx:setup"] -description = "Create a multi-arch buildx builder with remote BuildKit nodes" -usage = """ -flag "--amd64 " default="tcp://buildkit-amd64.buildkit:1234" help="BuildKit endpoint for linux/amd64" -flag "--arm64 " default="tcp://buildkit-arm64.buildkit:1234" help="BuildKit endpoint for linux/arm64" -flag "--name " default="navigator" help="Builder instance name" -""" -run = """ -#!/usr/bin/env bash -set -euo pipefail - -BUILDER="${usage_name}" -AMD64="${usage_amd64}" -ARM64="${usage_arm64}" - -# Remove existing builder if present so we get a clean config -if docker buildx inspect "${BUILDER}" >/dev/null 2>&1; then - echo "Removing existing builder: ${BUILDER}" - docker buildx rm "${BUILDER}" -fi - -echo "Creating builder: ${BUILDER}" -docker buildx create \ - --name "${BUILDER}" \ - --driver remote \ - --platform linux/amd64 \ - "${AMD64}" - -docker buildx create \ - --name "${BUILDER}" \ - --append \ - --driver remote \ - --platform linux/arm64 \ - "${ARM64}" - -docker buildx use "${BUILDER}" -echo "Builder '${BUILDER}' is now active:" -docker buildx inspect "${BUILDER}" -""" - ["docker:build"] description = "Build all Docker images" depends = [ From 2a69e320a7cd8ce494e27d7eedebdb5916176441 Mon Sep 17 00:00:00 2001 From: Drew Newberry Date: Fri, 27 Feb 2026 09:50:59 -0800 Subject: [PATCH 15/15] ci: pass MISE_GITHUB_TOKEN as build arg in CI Dockerfile Declare the ARG before mise install so authenticated GitHub API requests avoid rate limits when fetching tool versions. --- deploy/docker/Dockerfile.ci | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/docker/Dockerfile.ci b/deploy/docker/Dockerfile.ci index 64e887b6..0afb4a48 100644 --- a/deploy/docker/Dockerfile.ci +++ b/deploy/docker/Dockerfile.ci @@ -60,6 +60,7 @@ RUN curl https://mise.run | sh COPY mise.toml /opt/mise/mise.toml COPY build/ /opt/mise/build/ WORKDIR /opt/mise +ARG MISE_GITHUB_TOKEN RUN mise trust /opt/mise/mise.toml && \ env -u RUSTC_WRAPPER mise install && \ /root/.cargo/bin/rustup component remove rust-docs || true && \