Skip to content

Commit e13295b

Browse files
committed
Add pinned-image live smoke for generic installs
1 parent 0dab426 commit e13295b

8 files changed

Lines changed: 283 additions & 58 deletions

File tree

.github/workflows/ci.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
name: ci
22

3+
permissions:
4+
contents: read
5+
packages: read
6+
37
on:
48
pull_request:
59
push:
@@ -30,6 +34,12 @@ jobs:
3034
- name: Adapter end-to-end contracts
3135
run: make e2e-adapters
3236

37+
- name: Generic live smoke with pinned GHCR images
38+
env:
39+
GITHUB_ACTOR: ${{ github.actor }}
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41+
run: make k8s-smoke-generic-pinned
42+
3343
- name: Package chart
3444
run: make chart-package
3545

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ __pycache__/
55
*.pyc
66
.pytest_cache/
77
.mb3r/
8+
.tmp/
89
*.tgz

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
PYTHON ?= python
22

3-
.PHONY: lint validate smoke-generic e2e-generic k8s-smoke-generic e2e-adapters smoke-otel-demo e2e-otel-demo package-assets chart-package release-dry-run stack-manifest
3+
.PHONY: lint validate smoke-generic e2e-generic k8s-smoke-generic k8s-smoke-generic-pinned e2e-adapters smoke-otel-demo e2e-otel-demo package-assets chart-package release-dry-run stack-manifest
44

55
lint:
66
$(PYTHON) scripts/tasks.py lint
@@ -17,6 +17,9 @@ e2e-generic:
1717
k8s-smoke-generic:
1818
$(PYTHON) scripts/tasks.py k8s-smoke-generic
1919

20+
k8s-smoke-generic-pinned:
21+
$(PYTHON) scripts/tasks.py k8s-smoke-generic-pinned
22+
2023
e2e-adapters:
2124
$(PYTHON) scripts/tasks.py e2e-adapters
2225

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ make validate
6666
make smoke-generic
6767
make e2e-generic
6868
make k8s-smoke-generic
69+
make k8s-smoke-generic-pinned
6970
make e2e-adapters
7071
make smoke-otel-demo
7172
make e2e-otel-demo
@@ -80,10 +81,13 @@ Direct Python equivalents are also available:
8081
```bash
8182
python scripts/tasks.py validate
8283
python scripts/tasks.py e2e-generic
84+
python scripts/tasks.py k8s-smoke-generic-pinned
8385
python scripts/tasks.py e2e-adapters
8486
python scripts/tasks.py release-dry-run
8587
```
8688

89+
`make k8s-smoke-generic` verifies the live generic runtime contract with locally rebuilt images from the pinned release binaries. `make k8s-smoke-generic-pinned` verifies the clean-cluster startup path for the chart's default pinned `ghcr.io/mb3r-lab/bering` and `ghcr.io/mb3r-lab/sheaft` images, using anonymous pull by default and a temporary `imagePullSecret` when `MB3R_GHCR_USERNAME` and `MB3R_GHCR_TOKEN` are set. Repository CI wires that pinned-image smoke through `GITHUB_TOKEN` with `packages:read` so pull/auth regressions fail on push.
90+
8791
## Compatibility Notes
8892

8993
The compatibility files in `compat/` are the source of truth for stack-level assertions. The current `0.2.0` bundle is recorded as a `candidate` integration statement backed by upstream release manifests, live generic smoke evidence, and Sheaft's published compatibility manifest, not as a broader verified operations guarantee. OpenTelemetry Demo remains one example profile and one acceptance scenario, not the design center of the core bundle.

docs/verification/generic-e2e.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ This is the required non-OTel acceptance path for the repository.
55
```bash
66
make e2e-generic
77
make k8s-smoke-generic
8+
make k8s-smoke-generic-pinned
89
```
910

1011
What it checks:
@@ -14,6 +15,10 @@ What it checks:
1415
- stable artifact emission from Bering
1516
- Sheaft batch and serve consumption of that artifact
1617
- report generation and persisted history output
17-
- optional live-cluster install smoke through `kind` with the same generic synthetic profile
18+
- live-cluster install smoke through `kind` with locally rebuilt images from the pinned release binaries
19+
- clean-cluster startup of the chart's default pinned `ghcr.io/mb3r-lab/bering` and `ghcr.io/mb3r-lab/sheaft` images
20+
- anonymous pull by default for pinned-image smoke, with an optional temporary `imagePullSecret` from `MB3R_GHCR_USERNAME` and `MB3R_GHCR_TOKEN`
21+
- pinned-image smoke wired into repository CI through `GITHUB_TOKEN` with `packages:read`
22+
- explicit failure attribution when Kubernetes reports image-pull or auth errors instead of letting them collapse into a generic timeout
1823

1924
If this path fails, generic stack readiness is not proven even if the OTel Demo profile still passes.

scripts/acceptance_common.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,34 @@ def ensure_kind() -> Path:
186186
return binary_path
187187

188188

189+
def ensure_kubectl() -> Path:
190+
explicit = os_environ().get("KUBECTL_BIN")
191+
if explicit:
192+
kubectl = Path(explicit)
193+
check(kubectl.exists(), f"KUBECTL_BIN does not exist: {kubectl}")
194+
return kubectl
195+
196+
found = shutil.which("kubectl")
197+
if found:
198+
return Path(found)
199+
200+
os_name, arch = current_platform()
201+
binary_name = "kubectl.exe" if os_name == "windows" else "kubectl"
202+
destination_dir = TOOLS_DIR / f"kubectl-{os_name}-{arch}"
203+
binary_path = destination_dir / binary_name
204+
if binary_path.exists():
205+
return binary_path
206+
207+
destination_dir.mkdir(parents=True, exist_ok=True)
208+
print("[download] kubectl stable", flush=True)
209+
stable_version = urllib.request.urlopen("https://dl.k8s.io/release/stable.txt").read().decode("utf-8").strip()
210+
download(f"https://dl.k8s.io/release/{stable_version}/bin/{os_name}/{arch}/{binary_name}", binary_path)
211+
if os_name != "windows":
212+
binary_path.chmod(0o755)
213+
check(binary_path.exists(), f"kubectl binary not found after download: {binary_path}")
214+
return binary_path
215+
216+
189217
def helm_env(helm_root: Path) -> dict[str, str]:
190218
env = os_environ()
191219
repo_dir = helm_root.parent / "helm-repo"

0 commit comments

Comments
 (0)