Repository navigation
feat(build-hosts): versioned build servers — the v/ and alias/ contract and retention - #7191
Conversation
…ct, one build-<v> per version, and a runner that claims by version P1 and P2 of Doc/Architecture/DeployTestSwitchLatest, built from that page's §3 key forms. Contract (init-only, additive): - BuildHostSetKeys: v/<version> and alias/<latest|candidate|previous>, version validation, and the DNS deployment name; - DeploymentContent.BuildHostAliasSet / BuildHostVersionSet; - an optional fifth set-token part, the mw-core-tests digest (a four-part token reads back unchanged); - BuildHostsBlock.MaxReplicasPerVersion and Retention (keep the alias targets, attempts and caps; tear down the rest). Chart: buildHosts.versions renders one build-<v> Deployment and ScaledObject per entry, with demand by version. The version-only selector and pod labels mean a switch restarts nothing, and the aliases label the Deployment. Duplicate aliases, repeated versions and malformed versions are refused. Runner: MW_BUILD_VERSION, used instead of MW_BUILD_CHANNEL, sends the version on every claim, event and token call. Tests: 14 contract cases; chart fixtures for 1 and 3 versions plus 3 refusals; runner self-test cases (a claim body put back on the channel turns them red). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e's chart is frozen) This PR keeps the contract, the runner's MW_BUILD_VERSION and the doc. The versioned chart rendering (build-<v> per version, a version-only selector, alias labels, demand by version, refusals and fixtures) re-opens against Systemorph/MeshWeaver.Deploy once that repo carries the build-host chart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ver.Deploy with the runner image All deploy logic moves to Systemorph/MeshWeaver.Deploy, the build-host runner included. This PR keeps the contract and the doc; the MW_BUILD_VERSION runner change is carried across with that move. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Accepted versions can generate colliding or invalid Kubernetes resources, and an explicit zero replica ceiling silently defaults to two.
5 open issues
What changed in this PR
Adds the contract and infrastructure support for versioned build servers, preparing the deploy → test → switch-latest flow without enabling it on live deployments.
Changes:
- Adds version and alias keys, retention helpers, and an optional core-test image digest.
- Renders per-version build hosts and scalers, with runner requests scoped by version.
- Adds contract tests, chart fixtures, runner self-tests, and documentation.
| File | Description |
|---|---|
test/MeshWeaver.Deployment.Contract.Test/BuildHostVersionsTest.cs |
Tests tokens, version keys, aliases, and retention. |
src/MeshWeaver.Documentation/Data/Architecture/BuildHosts.md |
Documents versioned build-server behavior. |
src/MeshWeaver.Deployment.Contract/DeploymentContent.cs |
Adds version and alias set resolution. |
src/MeshWeaver.Deployment.Contract/BuildHosts.cs |
Defines version keys, retention, and extended tokens. |
deploy/helm/values.yaml |
Adds the versioned-host configuration list. |
deploy/helm/templates/build-host/build-host.yaml |
Renders version-specific deployments and scalers. |
deploy/helm/templates/build-host/_build-hosts.tpl |
Validates and normalizes versioned-host entries. |
deploy/aks/scripts/testdata/values.build-hosts-versions.yaml |
Provides a three-version fixture. |
deploy/aks/scripts/testdata/values.build-hosts-version-twice.yaml |
Exercises duplicate-version refusal. |
deploy/aks/scripts/testdata/values.build-hosts-one-version.yaml |
Provides a single-version fixture. |
deploy/aks/scripts/testdata/values.build-hosts-bad-version.yaml |
Exercises malformed-version refusal. |
deploy/aks/scripts/testdata/values.build-hosts-alias-twice.yaml |
Exercises duplicate-alias refusal. |
deploy/aks/scripts/test-build-hosts.sh |
Checks versioned rendering and refusals. |
.github/scripts/build-run.py |
Adds version-scoped requests and preflight checks. |
Review effort: Balanced
…oyment names are named, the tests digest is hidden from editors (review of #7191) IsVersion refuses a pre-release ending in '.' or '-', because the Kubernetes name and labels would end in punctuation. DeploymentName is not injective (3.1.1-alpha.1 and 3.1.1-alpha-1), so NameCollision names the deployed version that already has the name, for whatever adds a version to refuse. CoreTestsDigest is Browsable(false), like the other CD-owned set values. The doc link to DeployTestSwitchLatest becomes text until that page lands (#7182). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Test Results 12 files 12 suites 29m 16s ⏱️ Results for commit 5354178. ♻️ This comment has been updated with latest results. |
|
|
||
| /// <summary>The replica ceiling of every VERSIONED deployment (<see cref="BuildHostSetKeys.Version"/>); | ||
| /// it must cover the core shards plus the dependents' gates a candidate runs (Doc/Architecture/DeployTestSwitchLatest §9).</summary> | ||
| [Description("The most replicas each versioned build server scales to")] |
There was a problem hiding this comment.
Not changed in this PR; here's why. This isn't specific to these four fields: the whole MeshWeaver.Deployment.Contract is English-only by construction. None of its existing [Description] captions (Enabled, Channels, every DeploymentContent and VolumeClaim field) carries a [Translation]. The contract's only reference is Microsoft.Extensions.Configuration.Abstractions, and TranslationAttribute lives in MeshWeaver.Messaging.Contract. German captions for four fields would therefore either add the dependency you'd like kept out, or start a member-keyed translation table in the editor for this one contract. Both are decisions for the whole contract, so I've filed it into bug triage as a contract-wide item (rbuergi/Feedback/20261025-deployment-contract-captions-english-only). The new settings keep the contract's existing convention until that's decided.


This is P1 (contract half) of Deploy, Test the Deploy, Switch Latest (#7182), implementing §3's key forms as written. It changes nothing live: no record writes
v/entries yet. That is P3, the Plugins receiver.Contract (
MeshWeaver.Deployment.Contract, init-only and additive):BuildHostSetKeys:v/<version>maps to a set token, andalias/<latest|candidate|previous>maps to a VERSION (one leaf). It also does version validation and builds the DNS namebuild-<v>.DeploymentContent.BuildHostAliasSet(alias)andBuildHostVersionSet(version).CoreTestsDigest(D3). A four-part token reads back byte-identically.BuildHostsBlock.MaxReplicasPerVersionandRetention:KeepPreviousLatest(D4) andMaxVersions.Keep(sets, attemptVersions, capVersions)/Teardownimplement §6 rules 1–5. Cap versions come fromHosting/BuildCaps/<package>, as agreed with the cap side.Chart: not in this PR. Core's chart is frozen, so chart edits go to Systemorph/MeshWeaver.Deploy. The versioned rendering is written and tested, and re-opens there once Deploy carries the build-host chart. It renders
build-<v>per entry with demand from/queue?version=<v>, a version-only selector and pod labels, and aliases as Deployment labels, so a switch restarts nothing. Its refusals are a doubly named alias, a repeated version and a malformed version.Runner: not in this PR either. All deploy logic moves to Systemorph/MeshWeaver.Deploy, the build-host runner included. The
MW_BUILD_VERSIONchange is written and self-tested, and goes across with that move. With it, a versioned host claims, posts events and requests its token byversion; it needs exactly one ofMW_BUILD_CHANNEL/MW_BUILD_VERSION; andMW_BUILD_PLATFORM_VERSIONmust equal the version.Tests:
BuildHostVersionsTest: 14 cases. Token compatibility, version forms, key forms, alias resolution (including a stale alias), retention and teardown.Owed after this: P3 (Plugins: version-keyed claim and queue,
/queue?version=,GET /api/builds/hosts, and BuildHostDeploy, BuildHostSwitch and BuildHostTeardown) and P4 (main-cd).🤖 Generated with Claude Code