Skip to content
Closed
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
43 changes: 43 additions & 0 deletions .github/workflows/validate-aimanager-manifests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Validate AIManager Manifests
on: pull_request

permissions: {}

jobs:
validate-aimanager-manifests:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install CUE
shell: bash
run: |
set -euo pipefail
archive="$RUNNER_TEMP/cue.tar.gz"
install_dir="$RUNNER_TEMP/cue"
curl -fsSL --retry 3 https://github.com/cue-lang/cue/releases/download/v0.15.4/cue_v0.15.4_linux_amd64.tar.gz -o "$archive"
echo "4709f0d3e9988b82192a205953fefdbb3637317a1cef63d84fe65b7b92ef95a3 $archive" | sha256sum -c -
mkdir -p "$install_dir"
tar -xzf "$archive" -C "$install_dir" cue
echo "$install_dir" >> "$GITHUB_PATH"
- name: Validate AIManager manifests
shell: bash
run: |
set -euo pipefail
mapfile -t manifests < <(find ./vhdbuilder/release-notes/AKSAIManager -name manifest.json -type f | sort)
[ "${#manifests[@]}" -gt 0 ] || { echo "no manifests found"; exit 1; }
for manifest in "${manifests[@]}"; do
cue vet -c ./schemas/aimanager.cue "$manifest"
slug="$(jq -r .model.slug "$manifest")"
Comment thread
zhehli688 marked this conversation as resolved.
directory="$(basename "$(dirname "$manifest")")"
[ "$slug" = "$directory" ] || { echo "$manifest: model.slug '$slug' != directory '$directory'"; exit 1; }
duplicate_variants="$(jq -r '[.variants | group_by([.gpuSku, .osSku])[] | select(length > 1) | .[0] | "\(.gpuSku)/\(.osSku)"] | join(", ")' "$manifest")"
Comment thread
zhehli688 marked this conversation as resolved.
[ -z "$duplicate_variants" ] || { echo "$manifest: duplicate variants: $duplicate_variants"; exit 1; }
duplicate_dependencies="$(jq -r '[.variants[].dependencies | group_by(.name)[] | select(length > 1) | .[0].name] | unique | join(", ")' "$manifest")"
Comment thread
zhehli688 marked this conversation as resolved.
[ -z "$duplicate_dependencies" ] || { echo "$manifest: duplicate dependencies: $duplicate_dependencies"; exit 1; }
duplicate_bake_paths="$(jq -r '[.variants[].dependencies | group_by(.bakePath)[] | select(length > 1) | .[0].bakePath] | unique | join(", ")' "$manifest")"
[ -z "$duplicate_bake_paths" ] || { echo "$manifest: duplicate dependency bakePaths: $duplicate_bake_paths"; exit 1; }
done
4 changes: 4 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ e2e/localdns/validate-localdns-exporter-metrics.sh @saewoni @yewmsft

parts/windows/ @timmy-wright @r2k1 @benjamin-brady @djsly @awesomenix @cameronmeissner
staging/cse/windows/ @timmy-wright @r2k1 @benjamin-brady @djsly @awesomenix @cameronmeissner

# Code owners for AIManager managed VHD manifest schema and release notes
schemas/aimanager.cue @zhehli688 @yewmsft @YaoC
vhdbuilder/release-notes/AKSAIManager/ @zhehli688 @yewmsft @YaoC
61 changes: 61 additions & 0 deletions schemas/aimanager.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package aimanager

import "strings"

// Schema for the AKS AIManager custom-VHD content manifests under
// vhdbuilder/release-notes/AKSAIManager/<model-slug>/manifest.json
//
// One file per model. Each file declares every (gpu, os) variant
// of the custom VHD to build for that model. The internal KAITO custom-VHD capture
// pipeline consumes these files and bakes the content into Azure Compute Gallery
// image versions.
//
// Validate with:
// cue vet -c ./schemas/aimanager.cue ./vhdbuilder/release-notes/AKSAIManager/<model>/manifest.json
Comment thread
zhehli688 marked this conversation as resolved.
Comment thread
zhehli688 marked this conversation as resolved.

// Model-level facts shared by every variant (the weights are identical across GPU/OS).
#Model: {
slug: string // short model id
Comment thread
zhehli688 marked this conversation as resolved.
hfRepo: string // HuggingFace repo, e.g. "deepseek-ai/DeepSeek-V4-Flash"
hfRevision: string & =~"^[0-9a-f]{40}$" // pinned commit SHA for durable/releasable images
gated: bool // if true, the model needs a HF_TOKEN to pull from HuggingFace
"_comment"?: string // optional context for maintainers; ignored by consumers
bakePath!: "/opt/kaito/models/" + strings.Replace(strings.ToLower(hfRepo), "/", "-", -1) // path inside the VHD where the model weights are baked
}

// A build-time dependency baked into the VHD for a variant. The list may be empty
// for models that need nothing beyond their weights (e.g. mxfp4 models with no CUDA toolkit).
#Dependency: {
name: string // OS package name, e.g. "cuda-toolkit-12-9"
version: string // exact package version pin, e.g. "12.9.2-1"
"_comment"?: string // optional context for maintainers; ignored by consumers
repoKeyringUrl?: string & =~"^https://" // repo keyring .deb URL to enable the package's apt source
repoKeyringSha256?: string & =~"^[0-9a-f]{64}$" // SHA-256 that consumers should verify before installing the downloaded keyring
bakePath: string & =~"^/" // absolute path inside the VHD where the package is baked for KAITO
if repoKeyringUrl != _|_ {
repoKeyringSha256!: string & =~"^[0-9a-f]{64}$"
}
if repoKeyringSha256 != _|_ {
repoKeyringUrl!: string
}
}

#BaseImage: {
Ubuntu2404: {offer: "AKSUbuntu", sku: "2404gen2containerd"}
"AzureLinux3.0": {offer: "azure-linux-3", sku: "V3gen2"}
}

#Variant: {
Comment thread
zhehli688 marked this conversation as resolved.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

half-retraction on my last comment here: adding "_comment"? fixed the symptom i showed you, but the phantom osSku line isn't about _comment at all — it's the disjunction, and it fires on any failure inside a variant. your own new https rule demonstrates it. a dependency with http:// gives:

variants.0: 2 errors in empty disjunction:
variants.0.osSku: conflicting values "AzureLinux3.0" and "Ubuntu2404"
variants.0.dependencies.0.repoKeyringUrl: invalid value "http://..." (out of bound =~"^https://")

the osSku line is still noise, and it's still the one printed first.

a lookup keyed on osSku keeps the pairing and drops the disjunction:

#BaseImage: {
	Ubuntu2404:      {offer: "AKSUbuntu",     sku: "2404gen2containerd"}
	"AzureLinux3.0": {offer: "azure-linux-3", sku: "V3gen2"}
}

#Variant: {
	gpuSku:       "A100" | "H100"
	osSku:        "Ubuntu2404" | "AzureLinux3.0"
	"_comment"?:  string
	dependencies: [...#Dependency]
	baseImage:    #BaseImage[osSku]
}

i ran this before suggesting it: both real manifests still pass, an AzureLinux baseImage on a Ubuntu2404 variant still fails — now as baseImage.offer: conflicting values "AKSUbuntu" and "azure-linux-3", which points at the actual mistake — and the http:// case above reports its one real error and nothing else.

nit, take it or leave it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Thanks for flagging this!

gpuSku: "A100" | "H100"
osSku: "Ubuntu2404" | "AzureLinux3.0"
"_comment"?: string // optional context for maintainers; ignored by consumers
dependencies: [...#Dependency]
baseImage: #BaseImage[osSku]
}

#Manifest: {
model: #Model
variants: [#Variant, ...#Variant]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[#Variant, ...#Variant] gets you "at least one" but not "at most one per (gpuSku, osSku)". two entries with the same gpu+os pass cue vet and give the capture pipeline two builds for the same gallery image version.

a map keyed on the tuple makes it unrepresentable:

variants: [=~"^(A100|H100)-(Ubuntu2404|AzureLinux3\\.0)$"]: #Variant

if you'd rather keep the list shape, a jq uniqueness check next to the slug check in the workflow is fine too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I added a uniqueness check to the CI workflow.

}

#Manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"model": {
"slug": "deepseekv4flash",
"hfRepo": "deepseek-ai/DeepSeek-V4-Flash-0731",
"hfRevision": "7872f01b1d1fe23eabc4c98b48bffcef5a386062",
"gated": false,
"bakePath": "/opt/kaito/models/deepseek-ai-deepseek-v4-flash-0731"
},
"variants": [
{
"gpuSku": "H100",
"osSku": "Ubuntu2404",
"baseImage": {
"offer": "AKSUbuntu",
"sku": "2404gen2containerd"
},
"dependencies": [
{
"name": "cuda-toolkit-12-9",
"version": "12.9.2-1",
"repoKeyringUrl": "https://developer.download.nvidia.com/compute/cuda/repos/debian12/x86_64/cuda-keyring_1.1-1_all.deb",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the debian12 keyring but the variant is osSku Ubuntu2404 / offer AKSUbuntu. should be the ubuntu2404 repo:

https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb

if debian12 is deliberate, it needs a comment saying why we are pointing an ubuntu VHD at a debian apt source.

@zhehli688 zhehli688 Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using debian12 is deliberate to be compatible with KAITO's Python runtime image. Comment added.

Comment thread
zhehli688 marked this conversation as resolved.
"repoKeyringSha256": "e7f219eab6fe4819cdb5c15b98233dc3420302d9c00883219cd3d896857cf48d",
"bakePath": "/opt/kaito/cuda/129",
"_comment": "Use the Debian 12 keyring to be compatible with KAITO's Python runtime image - python:3.12-slim-bookworm."
}
]
}
]
}
21 changes: 21 additions & 0 deletions vhdbuilder/release-notes/AKSAIManager/gptoss120b/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"model": {
"slug": "gptoss120b",
"hfRepo": "openai/gpt-oss-120b",
"hfRevision": "b5c939de8f754692c1647ca79fbf85e8c1e70f8a",
"gated": false,
"bakePath": "/opt/kaito/models/openai-gpt-oss-120b",
"_comment": "This model doesn't need other dependencies than the ones provided by KAITO's base image."
},
"variants": [
{
"gpuSku": "A100",
"osSku": "Ubuntu2404",
"baseImage": {
"offer": "AKSUbuntu",
"sku": "2404gen2containerd"
},
"dependencies": []
Comment thread
zhehli688 marked this conversation as resolved.
}
]
}
Loading