From 27a782c4a5c058fffdd440c39210face5cbd1700 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Thu, 1 Oct 2026 10:07:11 +0100 Subject: [PATCH 1/5] ci: pin Helm unittest for the Helm 3 toolchain Newer plugin releases require the Helm 4 plugin schema. Keep the chart gate compatible with the pinned Helm 3 release and the tested plugin binary. Signed-off-by: Radostin Stoyanov --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: From e6ba133e1d456d28ca6ed28f18004ceb3848bb33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 09:27:18 +0000 Subject: [PATCH 2/5] build(deps): bump urllib3 from 2.7.0 to 2.8.0 in /e2e Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.8.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- e2e/uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/uv.lock b/e2e/uv.lock index fb7d0f598..fe2b4b948 100644 --- a/e2e/uv.lock +++ b/e2e/uv.lock @@ -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]] From 6632f97f6cecfccb87983746d6a3335cab2506ae Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Thu, 15 Oct 2026 16:18:59 +0100 Subject: [PATCH 3/5] ci: skip upstream artifact publishing in the fork The inherited publisher writes images, charts and build caches to the ai-dynamo registry. Skip its version gate outside the upstream repository so dependent publishing jobs cannot run with fork credentials. Doubleword releases are built by the separate dynamo-images pipeline. Signed-off-by: Radostin Stoyanov --- .github/workflows/push-artifacts.yaml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) 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 }} From 49d243f1d09965d5653cb9b93667d894daf1d3b5 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Thu, 15 Oct 2026 16:08:26 +0100 Subject: [PATCH 4/5] docs: update the fork stack for the latest upstream Use upstream cuInterpose and its peer-allocation fixes instead of the old vendor stack. Record the remaining fork patches and the runtime changes that downstream integration must account for before deployment. Signed-off-by: Radostin Stoyanov --- AGENTS.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) 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. From f399c5ea503ebbcc1cd0ea670357ef7d381b84f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:27:53 +0000 Subject: [PATCH 5/5] build(deps): bump urllib3 from 2.7.0 to 2.8.0 in /benchmarks Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.7.0...2.8.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.8.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- benchmarks/uv.lock | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/benchmarks/uv.lock b/benchmarks/uv.lock index 189e6107e..9dc8f959a 100644 --- a/benchmarks/uv.lock +++ b/benchmarks/uv.lock @@ -299,6 +299,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e6/c4/ebdf7837bc4ef6fd98cfb013c28855bb358467bf86c1af011bbc21e21df0/durationpy-0.11-py3-none-any.whl", hash = "sha256:a739fe2b8972c250ff72f8e2c488d18cf25f7b852f49ee76048775d5171df30c", size = 4133, upload-time = "2026-08-26T13:55:59.456Z" }, ] +[[package]] +name = "execnet" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, +] + [[package]] name = "google-auth" version = "2.57.1" @@ -434,6 +443,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, ] +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -554,24 +576,26 @@ dependencies = [ { name = "kubernetes" }, { name = "packaging" }, { name = "pytest" }, + { name = "pytest-xdist" }, { name = "pyyaml" }, ] [package.metadata] requires-dist = [ - { name = "kubernetes", specifier = ">=32.0.1,<33.0.0" }, + { name = "kubernetes", specifier = ">=32.0.1,<37.0.0" }, { name = "packaging", specifier = ">=24.2,<26" }, { name = "pytest", specifier = ">=8.4.0,<9" }, + { name = "pytest-xdist", specifier = ">=3.6.1,<4" }, { name = "pyyaml", specifier = ">=6.0.2,<7" }, ] [[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]]