Skip to content

feat: k5s-stack-namespaces hook - #7

Merged
blairham merged 2 commits into
mainfrom
feat/k5s-stack-namespaces
Aug 18, 2026
Merged

feat: k5s-stack-namespaces hook#7
blairham merged 2 commits into
mainfrom
feat/k5s-stack-namespaces

Conversation

@blairham

Copy link
Copy Markdown
Contributor

Adds a k5s-stack-namespaces hook: two sibling k5s lane overlays that declare the same namespace: are rejected.

Why

The failure is silent. A new lane starts as a copy of an existing one, and if its namespace: isn't changed with everything else, k5s up server-side-applies over the old lane's objects. Nothing errors — the pods go Ready and the rig runs a blend of two lanes' configuration. For a perf rig that means every number it reports was measured against a universe nobody described.

Design choices

  • Uniqueness only, never a naming convention. A repo's lane names are its own business; pinning something like perf-rig-<lane> would be one repo's convention wearing an org hook's clothes.
  • Files are read as written, not through k5s's extends: resolution. Two lanes that both restate a shared namespace is the collision; resolving first would hide it. An overlay declaring no namespace inherits the base stack's — the normal shape for a lane that only adjusts load — and is skipped.
  • Compares every stack in the changed files' directories, not just the changed set. A collision is a property of the whole set, and the lane that already owned the namespace is usually not in the commit that collides with it. Comparing only staged files would pass every time the older file is untouched, i.e. always.
  • A runtime namespaceSuffix: user does not remove the need for this — it separates people, but two lanes declaring the same base still collide for any one engineer.

Install guard

The hook-install CI job exists because service-yaml-check shipped uninstallable for months. A new language: python hook added outside that guard reintroduces exactly the gap it was built to close, so this wires the new hook into both steps and grows the fixture with sibling overlays carrying distinct namespaces — otherwise the try-repo run would pass on an empty file set without exercising the grouping path.

Release

Second commit bumps pyproject.toml to 0.5.0 (new hook = minor) and moves the four consumer-facing rev: examples plus the "Current release" line together. The version was also behind independently — it read 0.3.0 against a repo already tagged v0.4.0, the exact drift the Releasing section warns about, so this closes that on the way past. The worked example under Releasing stays at v0.4.0; it illustrates the procedure rather than pinning a release.

Verification

  • 33 unit tests pass (7 new), including the collision-when-only-the-new-file-is-staged case and malformed-YAML-is-fatal.
  • pip install of the package exposes k5s-stack-namespaces as a console script reporting 0.5.0, and it exits 0 on the CI fixture and 1 with a named-both-files error on a real collision.
  • pre-commit try-repo could not be exercised locally — the Homebrew Caskroom pre-commit 4.6.2 build fails to resolve console scripts for the pre-existing service-yaml-check hook identically, so that path is left to CI, which installs upstream pre-commit via pip.

Two sibling k5s lane overlays that declare the same `namespace:` fail
silently: `k5s up` on one server-side-applies over the other's objects, no
error is raised, the pods go Ready, and the rig runs a blend of two lanes'
configuration. On a perf rig that means every number it reports was measured
against a universe nobody described. The mistake has one shape — a new lane
starts as a copy of an existing one and its namespace is not changed with
everything else.

- Assert uniqueness only, never a naming convention. A repo's lane names are
  its own business; pinning `perf-rig-<lane>` would be one repo's convention
  wearing an org hook's clothes.
- Read files as written rather than through k5s's `extends:` resolution. Two
  lanes that both restate a shared namespace is the collision; resolving first
  would hide it. An overlay declaring no namespace inherits the base stack's —
  the normal shape for a lane that only adjusts load — and is skipped.
- Compare every stack in the changed files' directories, not just the changed
  set. A collision is a property of the whole set, and the lane that already
  owned the namespace is usually not in the commit that collides with it.

Wire it into the `hook-install` CI job as well: that job exists because
`service-yaml-check` shipped for months uninstallable, and a new
`language: python` hook added outside the guard reintroduces exactly the gap
the guard was built to close. The fixture grows sibling overlays with distinct
namespaces so the try-repo run exercises the grouping path instead of passing
on an empty file set.
Adding a hook is a minor bump, and the Releasing section requires the
`pyproject.toml` version to move in the same PR as the hook change: under
`language: python` that version is what consumers actually pip-install, so a
tag cut without it ships a package whose self-reported version disagrees with
the `rev:` it came from.

The version was also behind independently — it read 0.3.0 against a repo
already tagged v0.4.0, i.e. the exact drift that section warns about, so this
closes that gap on the way past rather than carrying it forward.

Move the four consumer-facing `rev:` examples and the single "Current release"
line to v0.5.0 together, matching the convention set when the stale pins were
last fixed. The worked example under Releasing stays at v0.4.0 — it
illustrates the procedure rather than pinning a release.
@blairham
blairham merged commit a65badd into main Aug 18, 2026
3 checks passed
@blairham
blairham deleted the feat/k5s-stack-namespaces branch August 18, 2026 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant