diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ffbce3b0..991cc08ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,7 +138,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - run: helm plugin install https://github.com/helm-unittest/helm-unittest + - run: helm plugin install https://github.com/helm-unittest/helm-unittest --version v1.0.3 - run: helm unittest charts/snapshot/ pagebroker-image: diff --git a/.github/workflows/push-artifacts.yaml b/.github/workflows/push-artifacts.yaml index 0f5d26236..ab13cb062 100644 --- a/.github/workflows/push-artifacts.yaml +++ b/.github/workflows/push-artifacts.yaml @@ -49,12 +49,17 @@ jobs: version: name: Compute version runs-on: ubuntu-latest + # Fork releases are built by Doubleword/dynamo-images. These jobs publish + # to the upstream registry and must never run with a fork's credentials. if: > - github.event_name != 'workflow_run' || + github.repository == 'ai-dynamo/snapshot' && ( - github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.event == 'push' && - github.event.workflow_run.head_repository.full_name == github.repository + github.event_name != 'workflow_run' || + ( + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'push' && + github.event.workflow_run.head_repository.full_name == github.repository + ) ) outputs: version: ${{ steps.compute.outputs.version }} diff --git a/AGENTS.md b/AGENTS.md index 2c9bf4322..7634e4f7c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -226,3 +226,99 @@ and document the variable name — never the value. - [docs/reference](docs/reference) — API reference - [docs/operations](docs/operations) — install, storage, and operational guides - [e2e/README.md](e2e/README.md) — running the end-to-end suite + + +--- + +# doublewordai/snapshot fork layout + +Integration fork of ai-dynamo/snapshot. The fleet's Snapshot operator and +node agent images are built from a commit of this repo's `main`. + +## Branches + +- `upstream-base`: exactly the upstream revision the fork is based on. + Currently `0b6d7d98e48aa6a4a852af548d76852ccf1b4cd8` (2026-10-15 + upstream `main`). Never carries our commits. +- `main`: `upstream-base` plus every patch branch below, merged with + `--no-ff` in stack order. `git log --merges upstream-base..main` is the + patch list. +- `upstream-pr/`: a change we intend to land upstream, based on + `upstream-base`. +- `vendor/`: a Doubleword-only change, based on `upstream-base`. +- `archive/*` and other branches are history and are not part of any image. + Old vendor branches not listed in the current stack are inactive. + +## Rules + +- No backports. Do not cherry-pick upstream commits onto `main`; a fix in a + newer release arrives by moving `upstream-base`. +- One branch per patch, atomic, with the reason in the commit message. +- Moving to a new base: save backup refs, point `upstream-base` at the + reviewed revision, rebase each patch still needed, drop patches the new + base contains, rebuild `main` with merges, and update the stack list. +- Prepare changes locally. Publication and image builds are separate human + operations; do not push or trigger remote jobs from an agent session. + +## Current stack + +- `vendor/fork-layout`: this section. +- `vendor/helm-unittest`: pin v1.0.3 for the Helm 3 test toolchain. +- `vendor/fork-publishing`: skip the upstream artifact publisher in this fork; + Doubleword releases use the separate `doublewordai/dynamo-images` pipeline. +- `vendor/urllib3`: preserve the fork's merged urllib3 2.8.0 lockfile update + while upstream still pins 2.7.0. + +The old `vendor/cuinterpose` patch is no longer carried: upstream includes +its protocol, preload frontend, VMM/IPC tracking, multicast, coordinator, +launcher and opt-in agent/operator integration, plus newer peer-allocation +fixes. Use upstream's implementation rather than replaying the old stack. +cuInterpose remains opt-in via `nvidia.com/cuda-shared-memory-support: "enabled"` on +capture Pod templates. Single-node multi-GPU qualification is still required +for each target model, engine, GPU topology and driver; an upstream merge or +CPU test pass does not establish GLM-5.3 or Kimi-K3 restore support. Multi-node +workloads remain outside Snapshot's current supported scope. + +Dynamo's Snapshot API replacement and Snapshot image source pin must move +together with this fork. This upstream base makes PageBroker mandatory, +adds PVC store identity/content storage binding, and requires NRI v0.10 or +newer (containerd 2.2 or newer) for its PID-1 restore proxy. Update downstream +integration and check provider compatibility before deploying these images. + +`upstream-pr/runtime-storage-path` remains dropped: upstream provides +`runtime.storageDir`; migrate old `runtime.storagePath` values. + + +## Release and upgrade requirements + +Pushing this fork updates source and runs CI. It does not publish Doubleword +images: `.github/workflows/push-artifacts.yaml` is gated to +`ai-dynamo/snapshot`, whose registry and cache it writes. All jobs that publish +images, charts or caches depend on that gate. + +Doubleword's publisher is `doublewordai/dynamo-images`, workflow +`.github/workflows/build-images.yml`. After the Snapshot source is published, +update that repository's immutable Snapshot source pin and the Dynamo +Snapshot API dependency together. Before releasing this upstream base, the +builder needs a Snapshot PageBroker target and published image, and its +`scripts/point-snapshot-chart.sh` must also rewrite the PageBroker repository. +The current builder only publishes the Snapshot agent and operator and only +rewrites those two chart repositories. Agent and PageBroker must come from +the same Snapshot revision and use the matching image tag expected by the +chart. A green source CI run does not establish a complete Doubleword release. + +For workloads migrating from the old vendor cuInterpose stack: + +- Replace `nvidia.com/cuinterpose-enabled: "true"` on capture Pod templates + with `nvidia.com/cuda-shared-memory-support: "enabled"`. The old key is no + longer read; the new key accepts `enabled` or `disabled`, not booleans. +- Create fresh captures with the new agent/operator bundle. Old cuInterpose + manifests use `frontendSHA256` and `coreSHA256`; this base requires the + `libraries` map and an explicit `pids` list, so it rejects those old captures. + Do not rewrite existing manifests to bypass validation. New captures have + new snapshot/content identities and must replace the selected restore source. +- Keep old artifacts and their matching software until rollback and active + consumers have been checked. Test a restore from the new capture before + switching production workloads to it. +- Install the compatible agent, PageBroker, operator and CRDs together and + verify NRI v0.10+ on the provider runtime before attempting restore. diff --git a/e2e/uv.lock b/e2e/uv.lock index fb7d0f598..03dbef166 100644 --- a/e2e/uv.lock +++ b/e2e/uv.lock @@ -502,11 +502,11 @@ wheels = [ [[package]] name = "oauthlib" -version = "3.3.1" +version = "4.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0b/5f/19930f824ffeb0ad4372da4812c50edbd1434f678c90c2733e1188edfc63/oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", size = 185918, upload-time = "2025-06-19T22:48:08.269Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7a/d8/a1bcc8ba112a627f8ffbdc212a78ce18d3ac07e91a5ca65d27918eee25a1/oauthlib-4.0.0.tar.gz", hash = "sha256:efb274799819440f95b4ab3b818869f1ce9ae26c5beacba0201d1a1b76b54f86", size = 187232, upload-time = "2026-09-28T06:01:18.77Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1", size = 160065, upload-time = "2025-06-19T22:48:06.508Z" }, + { url = "https://files.pythonhosted.org/packages/d9/f4/78229a1066068ca14fc60fb26cf7381cabe4382261392b90e5f9552722d4/oauthlib-4.0.0-py3-none-any.whl", hash = "sha256:624c28c13a0a59cabf9747dfa52af63be3e512a7f2714df16e91b5b3a145e6cd", size = 159715, upload-time = "2026-09-28T06:01:17.008Z" }, ] [[package]] @@ -786,11 +786,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.7.0" +version = "2.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz", hash = "sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63", size = 458972, upload-time = "2026-09-15T19:29:36.253Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, + { url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl", hash = "sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3", size = 135717, upload-time = "2026-09-15T19:29:34.577Z" }, ] [[package]]