Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -643,11 +643,14 @@ jobs:
with:
ref: main

- name: Tool versions (hack/ci-tools.env)
run: grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"

- name: Move the pins to the newest compatible releases
id: bump
run: |
python3 -m venv "$RUNNER_TEMP/venv"
"$RUNNER_TEMP/venv/bin/pip" install --disable-pip-version-check packaging==26.3
"$RUNNER_TEMP/venv/bin/pip" install --disable-pip-version-check "packaging==${PACKAGING_VERSION}"
"$RUNNER_TEMP/venv/bin/python" hack/bump-convert-pins | tee "$RUNNER_TEMP/bump.txt"
# The moved set must resolve together: pip's resolver, no install.
mapfile -t pins < <(jq -r '.pins | to_entries[] | "\(.key)==\(.value)"' console/convert-pins.json)
Expand Down
67 changes: 52 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Tool versions (hack/ci-tools.env)
run: grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"
- uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # 2.0.0
with:
scandir: .
severity: warning
version: v0.11.0
version: ${{ env.SHELLCHECK_VERSION }}

actionlint:
name: Workflow lint
Expand Down Expand Up @@ -84,13 +86,10 @@ jobs:
telemetry-tests:
name: Telemetry manifests
runs-on: ubuntu-latest
env:
PROMETHEUS_VERSION: 3.15.1
PROMETHEUS_SHA256: 6a726885328ad9efebbf36e876ce2fb6225468a71fd1e7ce3ba666d5f4d97a84
# ghcr.io/yannh/kubeconform:v0.8.0
KUBECONFORM_IMAGE: ghcr.io/yannh/kubeconform@sha256:faffaf43f95aa6425306e1ab8d6fcad72acb9049158f38e574c085ea1ec0f64e
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Tool versions (hack/ci-tools.env)
run: grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"
- name: Install promtool
run: |
tgz="prometheus-${PROMETHEUS_VERSION}.linux-amd64.tar.gz"
Expand Down Expand Up @@ -132,8 +131,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Tool versions (hack/ci-tools.env)
run: grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"
- name: Install jsonschema for the schema cross-check (pinned)
run: python3 -m venv /tmp/jsonschema && /tmp/jsonschema/bin/pip install --disable-pip-version-check jsonschema==4.26.0
run: python3 -m venv /tmp/jsonschema && /tmp/jsonschema/bin/pip install --disable-pip-version-check "jsonschema==${JSONSCHEMA_VERSION}"
- env:
CONSOLE_JSONSCHEMA_PYTHON: /tmp/jsonschema/bin/python
run: tests/console_test.sh
Expand Down Expand Up @@ -162,10 +163,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Tool versions (hack/ci-tools.env)
run: grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"
- id: chrome
uses: browser-actions/setup-chrome@48ad923757ca74d66703209fe939badbdf80f2f4 # v2.2.0
with:
chrome-version: 156.0.8078.73
chrome-version: ${{ env.CHROME_VERSION }}
# The headless load runs Chrome in a network namespace (unshare -rn);
# Ubuntu's AppArmor blocks unprivileged user namespaces by default.
- run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
Expand Down Expand Up @@ -292,11 +295,10 @@ jobs:
chat-ui-manifest:
name: Chat UI manifest (static + kubeconform)
runs-on: ubuntu-latest
env:
KUBECONFORM_VERSION: v0.8.0
KUBECONFORM_SHA256: 9bc2bffbf71f261128533edaf912153948b7ff238f9a531ae6d34466ec287883
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Tool versions (hack/ci-tools.env)
run: grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"
- name: Install kubeconform
run: |
curl -fsSL -o kubeconform.tar.gz \
Expand Down Expand Up @@ -448,14 +450,13 @@ jobs:
kserve-example:
name: KServe example (stub install + kubeconform 1.34/1.35)
runs-on: ubuntu-latest
env:
KUBECONFORM_VERSION: v0.8.0
KUBECONFORM_SHA256: 9bc2bffbf71f261128533edaf912153948b7ff238f9a531ae6d34466ec287883
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Tool versions (hack/ci-tools.env)
run: grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
with:
version: v4.3.1
version: ${{ env.HELM4_VERSION }}
- name: Install kubeconform and PyYAML
run: |
curl -fsSL -o kubeconform.tar.gz \
Expand Down Expand Up @@ -484,3 +485,39 @@ jobs:
- run: python3 tests/known_issues_test.py
- run: python3 tests/ledger_freshness_test.py
- run: hack/known-issues check

# ---- Pin classes (pins/classes) ----
# A finished run's record is never edited; a PENDING ledger row's pin moves only
# with a dated amendment in the same diff; an autobump branch touches neither
# .github/ nor the ledger (hack/pin-guard). Every pin-bearing file under bench/ and
# oracle/ is classified (hack/pin-classes coverage). A pull request is checked from
# the commit it forked at to its head (HEAD^2 of the merge ref).
pin-guard:
name: Pin classes (ledger and historical pins)
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- run: python3 tests/pin_classes_test.py
- run: tests/pin_guard_test.sh
- name: hack/pin-classes coverage
run: hack/pin-classes coverage
- name: hack/pin-guard
env:
EVENT: ${{ github.event_name }}
BASE_REF: ${{ github.base_ref }}
BRANCH: ${{ github.head_ref || github.ref_name }}
run: |
case "${EVENT}" in
pull_request) base="origin/${BASE_REF}" head=HEAD^2 ;;
push) base=HEAD^1 head=HEAD ;;
*) base=origin/main head=HEAD ;;
esac
args=(--base "${base}" --head "${head}" --branch "${BRANCH}")
if [[ "${BRANCH}" == autobump/* ]]; then args+=(--autobump); fi
hack/pin-guard "${args[@]}"
39 changes: 26 additions & 13 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,32 @@ Include relevant details:
(`tests/console/audit/default`), diffed against `tests/console/audit/*.golden`
(`tests/audit_test.sh --update` rewrites those).
- Changed an image in `share/`, the Dockerfile or an image pin in `scripts/k3d-gpu`?
Run `scripts/images-lock update` (it reads the registries) and commit
`images.lock`; CI's `scripts/images-lock check` fails until you do.
- Every image reference in the repo is pinned `name:tag@sha256:<digest>`. Write
the tag, run `scripts/images-lock repin <file>` (it reads the registries) to add
the digest; `tests/image_pins_test.sh` (`scripts/images-lock pins`) fails on a
tag-only or `:latest` reference that `images.unpinned` does not list with a
reason. A rendered component's image pins live in its `component.conf`
(`IMAGE_PINS`). The nightly `repin-images` job opens a PR when a registry moves
a digest under an unchanged tag. Its token cannot push `.github/workflows/`, so
it runs `repin --exclude '.github/workflows/*'` and a workflow keeps no
`name:tag@sha256` of its own: it reads the pin from the Dockerfile,
`docs-build/Dockerfile` or `hack/ci-images.env` (`tests/image_pins_test.sh`
fails on a pin written in a workflow).
Run `scripts/images-lock update --only <the files you changed>` (it reads the
registries; without `--only` it checks every pinned digest and a digest a registry
moved elsewhere fails it) and commit `images.lock`; CI's `scripts/images-lock
check` fails until you do. `scripts/images-lock drift` lists the pins whose tag a
registry has moved, and writes nothing.
- Every image reference in the repo is pinned `name:tag@sha256:<digest>`, the tag
naming the version. Write the tag, run `scripts/images-lock repin <file>` (it
reads the registries) to add the digest; `tests/image_pins_test.sh`
(`scripts/images-lock pins`) fails on a tag-only, `:latest` or digest-only
reference that `images.unpinned` does not list with a reason. A rendered
component's image pins live in its `component.conf` (`IMAGE_PINS`). The nightly
`repin-images` job opens a PR when a registry moves a digest under an unchanged
tag. Its token cannot push `.github/workflows/`, so it runs `repin --exclude
'.github/workflows/*'` and a workflow keeps no version of its own: it reads image
pins from the Dockerfile, `docs-build/Dockerfile` or `hack/ci-images.env`, and
tool versions from `hack/ci-tools.env` (`tests/image_pins_test.sh` and
`tests/ci_wiring_test.sh` fail on a pin or version written in a workflow).
- `pins/classes` says who may move each pin. `ours` (the default) is k3d-gpu's own
and tracks the newest stable release; `eat-stock` tracks Intel EAT's newest
release; a `ledger` path is a ledger row's runner: while a listed row is PENDING
its pins move only with a dated amendment in the same PR, and once every listed
row has a verdict it is `historical`, a finished run's record that is never edited.
`repin` never touches ledger or historical paths. CI's `pin-guard` job runs
`hack/pin-guard` on every PR (`tests/pin_guard_test.sh` shows each rule) and
`hack/pin-classes coverage`, which fails on a pin-bearing file under `bench/` or
`oracle/` that no line classifies: add one for a new bench directory.
- `tests/console_mcp_test.sh` checks that the MCP tools `hardware` and
`plan_launch` return the CLI `facts --json` and `plan --json` bytes on every
fixture, and that the MCP `apply` tool writes nothing without a plan hash the
Expand Down
11 changes: 10 additions & 1 deletion console/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ def check_overrides(overrides):
return out


def image_id(ref):
"""name@sha256:<digest> for a ref that carries a digest, its tag dropped (the digest
is the image, so name:tag@sha256:X and name@sha256:X are one pin); else ref."""
name, at, digest = ref.partition("@")
if at and ":" in name.rsplit("/", 1)[-1]:
name = name.rsplit(":", 1)[0]
return name + at + digest


def cell_status(row, pins):
"""("green" | "amber" | "grey", reasons)."""
if row["source"] == "community":
Expand All @@ -116,7 +125,7 @@ def cell_status(row, pins):
pin = pins.get(row["engine"]["name"])
if pin is None:
reasons.append("this release pins no %s image" % row["engine"]["name"])
elif pin != row["engine"]["image"]:
elif image_id(pin) != image_id(row["engine"]["image"]):
reasons.append("engine pin moved since the measurement (cell %s, release %s)" % (row["engine"]["image"], pin))
return ("grey" if reasons else "green"), reasons

Expand Down
34 changes: 34 additions & 0 deletions hack/ci-tools.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Tool versions the CI and release workflows install, one KEY=value per line. They
# live here, outside .github/workflows/, so a bump is a change to this file: a token
# without the `workflows` permission can push it, and pins/classes classes it ours.
# A job loads them in its first step after checkout:
# grep -E '^[A-Z0-9_]+=' hack/ci-tools.env >> "$GITHUB_ENV"
# and reads them as ${{ env.KEY }} (action inputs) or $KEY (run steps).
# tests/ci_wiring_test.sh fails on a version literal left in a workflow.

# prometheus/prometheus: promtool checks the telemetry rules (ci.yml telemetry-tests).
PROMETHEUS_VERSION=3.15.1
PROMETHEUS_SHA256=6a726885328ad9efebbf36e876ce2fb6225468a71fd1e7ce3ba666d5f4d97a84

# yannh/kubeconform: the release binary (chat-ui-manifest, kserve-example) and the
# image (telemetry-tests and tests/kubeconform.sh, agent_kubeconform.sh,
# share_kubeconform.sh), the same release.
KUBECONFORM_VERSION=v0.8.0
KUBECONFORM_SHA256=9bc2bffbf71f261128533edaf912153948b7ff238f9a531ae6d34466ec287883
KUBECONFORM_IMAGE=ghcr.io/yannh/kubeconform:v0.8.0@sha256:faffaf43f95aa6425306e1ab8d6fcad72acb9049158f38e574c085ea1ec0f64e

# Chrome for Testing: report.html's offline load (report-html).
CHROME_VERSION=156.0.8078.73

# python-jsonschema: the facts/v1 schema cross-check (console-tests).
JSONSCHEMA_VERSION=4.26.0

# helm v4 for the KServe example's install path (kserve-example). Rendering share/
# uses the v3 line in hack/tools.env.
HELM4_VERSION=v4.3.1

# koalaman/shellcheck, run by ludeeus/action-shellcheck (shellcheck).
SHELLCHECK_VERSION=v0.11.0

# pypa/packaging for hack/bump-convert-pins (build-and-push.yml bump-convert-pins).
PACKAGING_VERSION=26.3
Loading
Loading