fix(ci): project private runtime fixtures
This commit is contained in:
@@ -40,7 +40,7 @@ const reviewedExpandableBlocks = new Map([
|
|||||||
]],
|
]],
|
||||||
["scripts/unified-deployment-smoke.sh", [
|
["scripts/unified-deployment-smoke.sh", [
|
||||||
{ sha256: "ca0c17d9ff8dc0fbe018fc1c5510eb33bc667a936fbe44a9be2d311390576825", rationale: "Generates reviewed Task 13 runtime configuration." },
|
{ sha256: "ca0c17d9ff8dc0fbe018fc1c5510eb33bc667a936fbe44a9be2d311390576825", rationale: "Generates reviewed Task 13 runtime configuration." },
|
||||||
{ sha256: "714d44082040affc28114a6a462164e3165c5c9fb2eefcd27f764c8dac7e161e", rationale: "Generates the reviewed local Task 13 Compose override." },
|
{ sha256: "e457c2d0620fd2db22332285748fc2e0738de998860fa478ea1ff5b70a891f3a", rationale: "Generates the reviewed local Task 13 Compose override." },
|
||||||
{ sha256: "c556f7d910d0788e219b042957e6b307cb9925b43920c680535d0d3a6dcbdb25", rationale: "Generates the reviewed local Task 13 installation descriptor." },
|
{ sha256: "c556f7d910d0788e219b042957e6b307cb9925b43920c680535d0d3a6dcbdb25", rationale: "Generates the reviewed local Task 13 installation descriptor." },
|
||||||
{ sha256: "c0078c68bd42a8668fbcb849888531e5e56109579df1ff96140a9e91b1efea56", rationale: "Generates the reviewed server Task 13 Compose override." },
|
{ sha256: "c0078c68bd42a8668fbcb849888531e5e56109579df1ff96140a9e91b1efea56", rationale: "Generates the reviewed server Task 13 Compose override." },
|
||||||
{ sha256: "b34a2b4ffaa72e01efb64a7a28b13513527538d837b2f35b6ca5fb3dbdb2d5dc", rationale: "Generates the reviewed server Task 13 installation descriptor." },
|
{ sha256: "b34a2b4ffaa72e01efb64a7a28b13513527538d837b2f35b6ca5fb3dbdb2d5dc", rationale: "Generates the reviewed server Task 13 installation descriptor." },
|
||||||
|
|||||||
@@ -126,23 +126,47 @@ if (runtimePasswordMounts.length !== 1 || runtimePasswordMounts[0].type !== "bin
|
|||||||
throw new Error("runtime fixture lacks one readable, read-only password-file bind");
|
throw new Error("runtime fixture lacks one readable, read-only password-file bind");
|
||||||
}
|
}
|
||||||
accessSync(runtimePasswordMounts[0].source, constants.R_OK);
|
accessSync(runtimePasswordMounts[0].source, constants.R_OK);
|
||||||
for (const target of [
|
const piTargets = [
|
||||||
"/home/thoth/.pi/agent/auth.json",
|
"/home/thoth/.pi/agent/auth.json",
|
||||||
"/home/thoth/.pi/agent/models.json",
|
"/home/thoth/.pi/agent/models.json",
|
||||||
"/home/thoth/.pi/agent/settings.json",
|
"/home/thoth/.pi/agent/settings.json",
|
||||||
]) {
|
] as const;
|
||||||
|
const piParent = mounts.filter((mount: any) => mount.target === "/home/thoth/.pi");
|
||||||
|
if (piParent.length !== 1) throw new Error("core lacks exactly one Pi state mount");
|
||||||
|
for (const target of piTargets) {
|
||||||
const selected = mounts.filter((mount: any) => mount.target === target);
|
const selected = mounts.filter((mount: any) => mount.target === target);
|
||||||
if (selected.length !== 1 || selected[0].type !== "bind" || !selected[0].read_only) {
|
if (profile === "local") {
|
||||||
throw new Error(`Pi fixture mount is not one read-only bind: ${target}`);
|
if (piParent[0].type !== "volume" || selected.length !== 0) {
|
||||||
}
|
throw new Error(`local Pi fixture must come only from the projected state volume: ${target}`);
|
||||||
accessSync(selected[0].source, constants.R_OK);
|
}
|
||||||
if (profile === "server") {
|
} else {
|
||||||
const parent = mounts.find((mount: any) => mount.target === "/home/thoth/.pi");
|
if (selected.length !== 1 || selected[0].type !== "bind" || !selected[0].read_only) {
|
||||||
const hidden = join(parent.source, "agent", basename(target));
|
throw new Error(`Pi fixture mount is not one read-only bind: ${target}`);
|
||||||
|
}
|
||||||
|
accessSync(selected[0].source, constants.R_OK);
|
||||||
|
const hidden = join(piParent[0].source, "agent", basename(target));
|
||||||
if (!statSync(hidden).isFile()) throw new Error(`server parent root lacks ${hidden}`);
|
if (!statSync(hidden).isFile()) throw new Error(`server parent root lacks ${hidden}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const [target, localVolume] of [
|
||||||
|
["/run/thothii-auth", "auth-runtime"],
|
||||||
|
["/fixtures/remote.git", "registry-remote"],
|
||||||
|
] as const) {
|
||||||
|
const selected = mounts.filter((mount: any) => mount.target === target);
|
||||||
|
if (selected.length !== 1 || !selected[0].read_only) {
|
||||||
|
throw new Error(`core lacks exactly one read-only runtime mount: ${target}`);
|
||||||
|
}
|
||||||
|
if (profile === "local") {
|
||||||
|
if (selected[0].type !== "volume"
|
||||||
|
|| (selected[0].source !== localVolume && !selected[0].source.endsWith(`_${localVolume}`))) {
|
||||||
|
throw new Error(`local runtime fixture is not projected through ${localVolume}`);
|
||||||
|
}
|
||||||
|
} else if (selected[0].type !== "bind") {
|
||||||
|
throw new Error(`server runtime fixture is not one read-only bind: ${target}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const resolverEnvironment = { ...core.environment };
|
const resolverEnvironment = { ...core.environment };
|
||||||
const runtimePasswordSource = realpathSync(runtimePasswordMounts[0].source);
|
const runtimePasswordSource = realpathSync(runtimePasswordMounts[0].source);
|
||||||
resolverEnvironment.THT_WS_TASK13_SMOKE_DWH_PASSWORD_FILE = runtimePasswordSource;
|
resolverEnvironment.THT_WS_TASK13_SMOKE_DWH_PASSWORD_FILE = runtimePasswordSource;
|
||||||
|
|||||||
@@ -496,16 +496,13 @@ services:
|
|||||||
volumes: !override
|
volumes: !override
|
||||||
- settings:/data/settings
|
- settings:/data/settings
|
||||||
- pi-state:/home/thoth/.pi
|
- pi-state:/home/thoth/.pi
|
||||||
- $TASK13_PI_AUTH:/home/thoth/.pi/agent/auth.json:ro
|
|
||||||
- $TASK13_PI_MODELS:/home/thoth/.pi/agent/models.json:ro
|
|
||||||
- $TASK13_PI_SETTINGS:/home/thoth/.pi/agent/settings.json:ro
|
|
||||||
- workspace-registry:/data/workspace-registry
|
- workspace-registry:/data/workspace-registry
|
||||||
- workspace-secrets:/data/workspace-secrets
|
- workspace-secrets:/data/workspace-secrets
|
||||||
- sessions:/data/sessions
|
- sessions:/data/sessions
|
||||||
- auth-runtime:/run/thothii-auth:ro
|
- auth-runtime:/run/thothii-auth:ro
|
||||||
- auth-state:/data/auth
|
- auth-state:/data/auth
|
||||||
- $TASK13_SESSION_RUNTIME_PASSWORD:/run/secrets/task13-runtime-password:ro
|
- $TASK13_SESSION_RUNTIME_PASSWORD:/run/secrets/task13-runtime-password:ro
|
||||||
- $TASK13_REMOTE:/fixtures/remote.git:ro
|
- registry-remote:/fixtures/remote.git:ro
|
||||||
frontend:
|
frontend:
|
||||||
image: $TASK13_FRONTEND_IMAGE
|
image: $TASK13_FRONTEND_IMAGE
|
||||||
build:
|
build:
|
||||||
@@ -550,6 +547,9 @@ volumes:
|
|||||||
auth-runtime:
|
auth-runtime:
|
||||||
labels:
|
labels:
|
||||||
io.thothii.task13.run: "$TASK13_RUN_ID"
|
io.thothii.task13.run: "$TASK13_RUN_ID"
|
||||||
|
registry-remote:
|
||||||
|
labels:
|
||||||
|
io.thothii.task13.run: "$TASK13_RUN_ID"
|
||||||
qdrant-data:
|
qdrant-data:
|
||||||
labels:
|
labels:
|
||||||
io.thothii.task13.run: "$TASK13_RUN_ID"
|
io.thothii.task13.run: "$TASK13_RUN_ID"
|
||||||
@@ -834,7 +834,10 @@ task13_commit_registry_change() {
|
|||||||
task13_run_logged "$message" git -C "$TASK13_SEED" add -A
|
task13_run_logged "$message" git -C "$TASK13_SEED" add -A
|
||||||
task13_run_logged "$message" git -C "$TASK13_SEED" -c user.name='Task 13 Smoke' -c user.email='task13-smoke@example.invalid' commit -m "$message"
|
task13_run_logged "$message" git -C "$TASK13_SEED" -c user.name='Task 13 Smoke' -c user.email='task13-smoke@example.invalid' commit -m "$message"
|
||||||
task13_run_logged "$message" git -C "$TASK13_SEED" push "$TASK13_REMOTE" "HEAD:$TASK13_BRANCH"
|
task13_run_logged "$message" git -C "$TASK13_SEED" push "$TASK13_REMOTE" "HEAD:$TASK13_BRANCH"
|
||||||
chmod -R a+rX "$TASK13_REMOTE"
|
if [[ -n "${TASK13_REGISTRY_RUNTIME_VOLUME:-}" ]] \
|
||||||
|
&& docker volume inspect "$TASK13_REGISTRY_RUNTIME_VOLUME" >/dev/null 2>&1; then
|
||||||
|
task13_prepare_registry_remote
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
task13_seed_registry() {
|
task13_seed_registry() {
|
||||||
@@ -943,12 +946,69 @@ task13_prepare_local_auth_runtime() {
|
|||||||
'
|
'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task13_prepare_local_pi_runtime() {
|
||||||
|
local owner_label
|
||||||
|
owner_label="$(docker volume inspect --format '{{ index .Labels "io.thothii.task13.run" }}' \
|
||||||
|
"$TASK13_PI_RUNTIME_VOLUME")"
|
||||||
|
[[ "$owner_label" == "$TASK13_RUN_ID" ]] \
|
||||||
|
|| task13_fail "local Pi runtime volume lacks the Task 13 run label"
|
||||||
|
task13_run_logged "project local Pi configuration for the core runtime" docker run --rm \
|
||||||
|
--name "$TASK13_PI_PROJECTION_CONTAINER" \
|
||||||
|
--label "io.thothii.task13.run=$TASK13_RUN_ID" \
|
||||||
|
--user 0:0 \
|
||||||
|
--entrypoint sh \
|
||||||
|
--volume "$TASK13_PI_AUTH:/source/auth.json:ro" \
|
||||||
|
--volume "$TASK13_PI_MODELS:/source/models.json:ro" \
|
||||||
|
--volume "$TASK13_PI_SETTINGS:/source/settings.json:ro" \
|
||||||
|
--volume "$TASK13_PI_RUNTIME_VOLUME:/target" \
|
||||||
|
"$TASK13_CORE_IMAGE" -ceu '
|
||||||
|
test -f /source/auth.json && test ! -L /source/auth.json
|
||||||
|
test -f /source/models.json && test ! -L /source/models.json
|
||||||
|
test -f /source/settings.json && test ! -L /source/settings.json
|
||||||
|
test -d /target/agent && test ! -L /target/agent
|
||||||
|
test -z "$(find /target -mindepth 1 -maxdepth 1 ! -name agent -print -quit)"
|
||||||
|
test -z "$(find /target/agent -mindepth 1 -maxdepth 1 -print -quit)"
|
||||||
|
cp /source/auth.json /source/models.json /source/settings.json /target/agent/
|
||||||
|
chown -R 10001:10001 /target
|
||||||
|
chmod 0700 /target /target/agent
|
||||||
|
chmod 0600 /target/agent/auth.json /target/agent/models.json /target/agent/settings.json
|
||||||
|
test "$(stat -c "%u:%g:%a" /target/agent/auth.json)" = 10001:10001:600
|
||||||
|
test "$(stat -c "%u:%g:%a" /target/agent/models.json)" = 10001:10001:600
|
||||||
|
test "$(stat -c "%u:%g:%a" /target/agent/settings.json)" = 10001:10001:600
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
task13_prepare_registry_remote() {
|
||||||
|
local owner_label
|
||||||
|
owner_label="$(docker volume inspect --format '{{ index .Labels "io.thothii.task13.run" }}' \
|
||||||
|
"$TASK13_REGISTRY_RUNTIME_VOLUME")"
|
||||||
|
[[ "$owner_label" == "$TASK13_RUN_ID" ]] \
|
||||||
|
|| task13_fail "registry fixture runtime volume lacks the Task 13 run label"
|
||||||
|
task13_run_logged "project Git fixture for the core runtime" docker run --rm \
|
||||||
|
--name "$TASK13_REGISTRY_PROJECTION_CONTAINER" \
|
||||||
|
--label "io.thothii.task13.run=$TASK13_RUN_ID" \
|
||||||
|
--user 0:0 \
|
||||||
|
--entrypoint sh \
|
||||||
|
--volume "$TASK13_REMOTE:/source:ro" \
|
||||||
|
--volume "$TASK13_REGISTRY_RUNTIME_VOLUME:/target" \
|
||||||
|
"$TASK13_CORE_IMAGE" -ceu '
|
||||||
|
test -f /source/HEAD && test -d /source/objects && test -d /source/refs
|
||||||
|
cp -a /source/. /target/
|
||||||
|
chown -R 10001:10001 /target
|
||||||
|
chmod -R u=rwX,go= /target
|
||||||
|
test "$(stat -c "%u:%g:%a" /target)" = 10001:10001:700
|
||||||
|
test "$(stat -c "%u:%g" /target/HEAD)" = 10001:10001
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
task13_start_stack() {
|
task13_start_stack() {
|
||||||
printf '== Build and start isolated local Compose distribution ==\n'
|
printf '== Build and start isolated local Compose distribution ==\n'
|
||||||
task13_assert_rendered_contract
|
task13_assert_rendered_contract
|
||||||
task13_compose_logged "build local Compose images" build --pull
|
task13_compose_logged "build local Compose images" build --pull
|
||||||
task13_compose_logged "create local core authentication runtime" create core
|
task13_compose_logged "create local core authentication runtime" create core
|
||||||
task13_prepare_local_auth_runtime
|
task13_prepare_local_auth_runtime
|
||||||
|
task13_prepare_local_pi_runtime
|
||||||
|
task13_prepare_registry_remote
|
||||||
task13_compose_start_logged "start local Compose distribution" up --detach --wait --wait-timeout 120
|
task13_compose_start_logged "start local Compose distribution" up --detach --wait --wait-timeout 120
|
||||||
TASK13_NETWORK="$(docker network ls \
|
TASK13_NETWORK="$(docker network ls \
|
||||||
--filter "label=com.docker.compose.project=$TASK13_PROJECT" \
|
--filter "label=com.docker.compose.project=$TASK13_PROJECT" \
|
||||||
@@ -1795,6 +1855,8 @@ task13_cleanup() {
|
|||||||
fi
|
fi
|
||||||
task13_remove_labeled_container "${TASK13_BAD_CANDIDATE_CONTAINER:-}" || cleanup_rc=1
|
task13_remove_labeled_container "${TASK13_BAD_CANDIDATE_CONTAINER:-}" || cleanup_rc=1
|
||||||
task13_remove_labeled_container "${TASK13_AUTH_PROJECTION_CONTAINER:-}" || cleanup_rc=1
|
task13_remove_labeled_container "${TASK13_AUTH_PROJECTION_CONTAINER:-}" || cleanup_rc=1
|
||||||
|
task13_remove_labeled_container "${TASK13_PI_PROJECTION_CONTAINER:-}" || cleanup_rc=1
|
||||||
|
task13_remove_labeled_container "${TASK13_REGISTRY_PROJECTION_CONTAINER:-}" || cleanup_rc=1
|
||||||
task13_remove_labeled_container "${TASK13_LLM_CONTAINER:-}" || cleanup_rc=1
|
task13_remove_labeled_container "${TASK13_LLM_CONTAINER:-}" || cleanup_rc=1
|
||||||
task13_remove_labeled_container "${TASK13_OIDC_CONTAINER:-}" || cleanup_rc=1
|
task13_remove_labeled_container "${TASK13_OIDC_CONTAINER:-}" || cleanup_rc=1
|
||||||
if [[ -n "${TASK13_PROJECT:-}" && -n "${TASK13_ROOT:-}" && -f "${TASK13_OVERRIDE:-}" ]]; then
|
if [[ -n "${TASK13_PROJECT:-}" && -n "${TASK13_ROOT:-}" && -f "${TASK13_OVERRIDE:-}" ]]; then
|
||||||
@@ -2357,6 +2419,7 @@ task13_self_test_registry_fingerprint() {
|
|||||||
task13_self_test_source_contract() {
|
task13_self_test_source_contract() {
|
||||||
local root host_network push_command registry_function workflow uses_count pinned_uses_count
|
local root host_network push_command registry_function workflow uses_count pinned_uses_count
|
||||||
local auth_runtime_mount auth_root_mount auth_projection auth_runtime_owner
|
local auth_runtime_mount auth_root_mount auth_projection auth_runtime_owner
|
||||||
|
local pi_auth_bind pi_projection registry_runtime_mount registry_root_mount registry_projection
|
||||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||||
workflow="$root/.github/workflows/deployment.yml"
|
workflow="$root/.github/workflows/deployment.yml"
|
||||||
host_network='--network'' host'
|
host_network='--network'' host'
|
||||||
@@ -2366,6 +2429,11 @@ task13_self_test_source_contract() {
|
|||||||
auth_root_mount='$TASK13_AUTH_''ROOT:/run/thothii-auth:ro'
|
auth_root_mount='$TASK13_AUTH_''ROOT:/run/thothii-auth:ro'
|
||||||
auth_projection='task13_prepare_local_auth_''runtime'
|
auth_projection='task13_prepare_local_auth_''runtime'
|
||||||
auth_runtime_owner='chown 10001:''10001 /target'
|
auth_runtime_owner='chown 10001:''10001 /target'
|
||||||
|
pi_auth_bind='$TASK13_PI_''AUTH:/home/thoth/.pi/agent/auth.json:ro'
|
||||||
|
pi_projection='task13_prepare_local_pi_''runtime'
|
||||||
|
registry_runtime_mount='registry-remote:/fixtures/remote.git:''ro'
|
||||||
|
registry_root_mount='$TASK13_''REMOTE:/fixtures/remote.git:ro'
|
||||||
|
registry_projection='task13_prepare_registry_''remote'
|
||||||
if rg -n 'docker[[:space:]]+(system[[:space:]]+)?prune' \
|
if rg -n 'docker[[:space:]]+(system[[:space:]]+)?prune' \
|
||||||
"$root/scripts/unified-deployment-smoke.sh" \
|
"$root/scripts/unified-deployment-smoke.sh" \
|
||||||
"$root/scripts/tht-update-smoke.sh" \
|
"$root/scripts/tht-update-smoke.sh" \
|
||||||
@@ -2387,6 +2455,18 @@ task13_self_test_source_contract() {
|
|||||||
|| task13_fail "the local authentication runtime projection must be defined and invoked once"
|
|| task13_fail "the local authentication runtime projection must be defined and invoked once"
|
||||||
grep -Fq -- "$auth_runtime_owner" "$root/scripts/unified-deployment-smoke.sh" \
|
grep -Fq -- "$auth_runtime_owner" "$root/scripts/unified-deployment-smoke.sh" \
|
||||||
|| task13_fail "the local authentication runtime projection must enforce the core UID"
|
|| task13_fail "the local authentication runtime projection must enforce the core UID"
|
||||||
|
! grep -Fq -- "$pi_auth_bind" "$root/scripts/unified-deployment-smoke.sh" \
|
||||||
|
|| task13_fail "the local smoke must not bind host-owned Pi authentication into the core"
|
||||||
|
[[ "$(grep -Ec "^${pi_projection}\\(\\)|^[[:space:]]+${pi_projection}$" \
|
||||||
|
"$root/scripts/unified-deployment-smoke.sh")" -eq 2 ]] \
|
||||||
|
|| task13_fail "the local Pi runtime projection must be defined and invoked once"
|
||||||
|
grep -Fq -- "$registry_runtime_mount" "$root/scripts/unified-deployment-smoke.sh" \
|
||||||
|
|| task13_fail "the local smoke must mount a Compose-owned Git fixture volume"
|
||||||
|
! grep -Fq -- "$registry_root_mount" "$root/scripts/unified-deployment-smoke.sh" \
|
||||||
|
|| task13_fail "the local smoke must not bind the host-owned Git fixture into the core"
|
||||||
|
[[ "$(grep -Ec "^${registry_projection}\\(\\)|^[[:space:]]+${registry_projection}$" \
|
||||||
|
"$root/scripts/unified-deployment-smoke.sh")" -ge 3 ]] \
|
||||||
|
|| task13_fail "the Git fixture projection must cover bootstrap and subsequent pushes"
|
||||||
grep -Eq '^TASK13_BAD_CANDIDATE_IMAGE="[^"[:space:]]+@sha256:[0-9a-f]{64}"$' \
|
grep -Eq '^TASK13_BAD_CANDIDATE_IMAGE="[^"[:space:]]+@sha256:[0-9a-f]{64}"$' \
|
||||||
"$root/scripts/unified-deployment-smoke.sh" \
|
"$root/scripts/unified-deployment-smoke.sh" \
|
||||||
|| task13_fail "the bad rollback candidate must be an immutable digest reference"
|
|| task13_fail "the bad rollback candidate must be an immutable digest reference"
|
||||||
@@ -2540,6 +2620,10 @@ task13_initialize() {
|
|||||||
TASK13_AUTH_PASSWORD_FILE="$TASK13_TMP/local-auth-password"
|
TASK13_AUTH_PASSWORD_FILE="$TASK13_TMP/local-auth-password"
|
||||||
TASK13_AUTH_RUNTIME_VOLUME="${TASK13_PROJECT}_auth-runtime"
|
TASK13_AUTH_RUNTIME_VOLUME="${TASK13_PROJECT}_auth-runtime"
|
||||||
TASK13_AUTH_PROJECTION_CONTAINER="$TASK13_PROJECT-auth-projection"
|
TASK13_AUTH_PROJECTION_CONTAINER="$TASK13_PROJECT-auth-projection"
|
||||||
|
TASK13_PI_RUNTIME_VOLUME="${TASK13_PROJECT}_pi-state"
|
||||||
|
TASK13_PI_PROJECTION_CONTAINER="$TASK13_PROJECT-pi-projection"
|
||||||
|
TASK13_REGISTRY_RUNTIME_VOLUME="${TASK13_PROJECT}_registry-remote"
|
||||||
|
TASK13_REGISTRY_PROJECTION_CONTAINER="$TASK13_PROJECT-registry-projection"
|
||||||
TASK13_AUTH_ADMIN=task13-admin
|
TASK13_AUTH_ADMIN=task13-admin
|
||||||
TASK13_AUTH_PASSWORD="task13-auth-$TASK13_RUN_ID"
|
TASK13_AUTH_PASSWORD="task13-auth-$TASK13_RUN_ID"
|
||||||
TASK13_OIDC_CLIENT_SECRET="task13-oidc-client-$TASK13_RUN_ID"
|
TASK13_OIDC_CLIENT_SECRET="task13-oidc-client-$TASK13_RUN_ID"
|
||||||
|
|||||||
Reference in New Issue
Block a user