Add container smoke acceptance

This commit is contained in:
2026-05-15 14:46:21 +02:00
parent d8dbf4950e
commit 61b31e4ebf
6 changed files with 109 additions and 7 deletions

View File

@@ -1,17 +1,16 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — guide-board
**Domain:** markitect
**Last synced:** 2026-05-15 12:41 UTC
**Domain:** markitect
**Last synced:** 2026-05-15 12:43 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
### Assessment Operations Baseline
Progress: 4/6 done | workstream_id: `fc5b1573-91b2-4a19-b6a9-dd4d17057d9b`
Progress: 5/6 done | workstream_id: `fc5b1573-91b2-4a19-b6a9-dd4d17057d9b`
**Open tasks:**
- ► D2.5 - Container Smoke Acceptance `9e2e7fa7`
- · D2.6 - External Extension Acceptance Path `65fbf1df`
---

View File

@@ -4,6 +4,7 @@ LABEL org.opencontainers.image.title="guide-board-core"
LABEL org.opencontainers.image.description="Guide Board certification and compliance preparation CLI core."
ENV PYTHONUNBUFFERED=1
ENV GUIDE_BOARD_SCHEMA_DIR=/opt/guide-board/docs/schemas
WORKDIR /opt/guide-board

View File

@@ -48,6 +48,35 @@ podman run --rm \
The run output remains on the host under `runs/sample-noop`.
## Smoke Check
Run the reproducible smoke check from the repository root:
```sh
scripts/container_smoke.sh
```
The script:
- detects `podman` or `docker`,
- builds `guide-board-core:smoke`,
- mounts a host output directory at `/runs`,
- runs the bundled sample assessment,
- verifies that the expected run artifacts are present on the host.
Override the runtime, image name, or output directory when needed:
```sh
CONTAINER_RUNTIME=docker \
GUIDE_BOARD_SMOKE_IMAGE=guide-board-core:local \
GUIDE_BOARD_SMOKE_RUNS_DIR=/tmp/guide-board-container-smoke \
scripts/container_smoke.sh
```
The smoke check uses only bundled sample profiles and the dependency-light core
image. Restricted harness material and extension-specific runtime dependencies
must stay in extension-specific images or explicit mounts.
## External Profiles
Mount project-specific profiles read-only:

52
scripts/container_smoke.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env sh
set -eu
ROOT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
IMAGE="${GUIDE_BOARD_SMOKE_IMAGE:-guide-board-core:smoke}"
RUNS_DIR="${GUIDE_BOARD_SMOKE_RUNS_DIR:-${TMPDIR:-/tmp}/guide-board-container-smoke-$$}"
RUNTIME="${CONTAINER_RUNTIME:-}"
if [ -z "$RUNTIME" ]; then
if command -v podman >/dev/null 2>&1; then
RUNTIME=podman
elif command -v docker >/dev/null 2>&1; then
RUNTIME=docker
else
echo "ERROR: podman or docker is required for the container smoke check." >&2
exit 127
fi
fi
mkdir -p "$RUNS_DIR"
echo "==> Building $IMAGE with $RUNTIME"
"$RUNTIME" build -t "$IMAGE" -f "$ROOT_DIR/Containerfile" "$ROOT_DIR"
echo "==> Running bundled sample assessment"
"$RUNTIME" run --rm \
-v "$RUNS_DIR:/runs" \
"$IMAGE" \
--root /opt/guide-board run \
--target /opt/guide-board/profiles/targets/sample-repository.json \
--assessment /opt/guide-board/profiles/assessments/sample-noop.json \
--output-dir /runs/sample-noop
echo "==> Verifying mounted run artifacts"
for path in \
"$RUNS_DIR/sample-noop/run.json" \
"$RUNS_DIR/sample-noop/plan.json" \
"$RUNS_DIR/sample-noop/retention-summary.json" \
"$RUNS_DIR/sample-noop/normalized/evidence.json" \
"$RUNS_DIR/sample-noop/normalized/findings.json" \
"$RUNS_DIR/sample-noop/normalized/mappings.json" \
"$RUNS_DIR/sample-noop/reports/assessment-package.json" \
"$RUNS_DIR/sample-noop/reports/report.md"
do
if [ ! -f "$path" ]; then
echo "ERROR: expected artifact missing: $path" >&2
exit 1
fi
done
echo "Container smoke check passed."
echo "Run artifacts: $RUNS_DIR/sample-noop"

View File

@@ -7,6 +7,7 @@ project's own draft contracts.
from __future__ import annotations
import os
from pathlib import Path
from typing import Any
@@ -14,11 +15,23 @@ from guide_board.errors import ValidationError
from guide_board.io import load_json
SCHEMA_DIR = Path(__file__).resolve().parents[2] / "docs" / "schemas"
SOURCE_SCHEMA_DIR = Path(__file__).resolve().parents[2] / "docs" / "schemas"
def load_schema(schema_name: str) -> dict[str, Any]:
return load_json(SCHEMA_DIR / f"{schema_name}.schema.json")
return load_json(_schema_dir() / f"{schema_name}.schema.json")
def _schema_dir() -> Path:
env_dir = os.environ.get("GUIDE_BOARD_SCHEMA_DIR")
candidates = []
if env_dir:
candidates.append(Path(env_dir).expanduser())
candidates.extend([SOURCE_SCHEMA_DIR, Path.cwd() / "docs" / "schemas"])
for candidate in candidates:
if (candidate / "target-profile.schema.json").is_file():
return candidate
return candidates[0]
def validate_document(document: Any, schema: dict[str, Any], path: str = "$") -> list[str]:

View File

@@ -150,7 +150,7 @@ Progress:
```task
id: GUIDE-BOARD-WP-0002-T005
status: todo
status: done
priority: medium
state_hub_task_id: "9e2e7fa7-8a97-4f07-9925-e637e0366003"
```
@@ -162,6 +162,14 @@ Acceptance:
- Verify mounted output directories receive run artifacts.
- Keep restricted or extension-specific harness assets outside the core image.
Progress:
- Added `scripts/container_smoke.sh`.
- Documented the smoke check in `docs/CONTAINER.md`.
- Verified the smoke check with Docker; mounted outputs received run metadata,
normalized evidence, mappings, findings, assessment package, and Markdown
report.
## D2.6 - External Extension Acceptance Path
```task