ci/woodpecker/push/publish Pipeline was successful
Co-authored-by: marcie <[email protected]>
177 lines
5.6 KiB
Bash
Executable File
177 lines
5.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Hermetic structural check for the explicit dogfood Compose overlay.
|
|
set -euo pipefail
|
|
|
|
repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
tmp=$(mktemp -d)
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
mkdir -p "$tmp/worktree" "$tmp/common.git" "$tmp/seat/secrets"
|
|
|
|
base_config_json=$(
|
|
cd "$repo_root"
|
|
BETTER_AUTH_SECRET=test-only-not-a-credential \
|
|
docker compose --profile stack config --format json
|
|
)
|
|
|
|
BASE_CONFIG_JSON="$base_config_json" python3 <<'PY'
|
|
import json
|
|
import os
|
|
|
|
config = json.loads(os.environ["BASE_CONFIG_JSON"])
|
|
gateway = config["services"]["gateway"]
|
|
env = gateway["environment"]
|
|
for key in (
|
|
"MOSAIC_AGENT_NAME",
|
|
"MOSAIC_GIT_IDENTITY",
|
|
"MOSAIC_BRAIN_HOME",
|
|
"AGENT_FILE_SANDBOX_DIR",
|
|
"AGENT_USER_TOOLS",
|
|
"AGENT_SHELL_ENABLED",
|
|
"AGENT_DELIVERY_ENABLED",
|
|
"MOSAIC_GIT_TOOLS_DIR",
|
|
"MOSAIC_INTEGRATION_TRUNK",
|
|
):
|
|
assert key not in env, f"base compose unexpectedly sets dogfood variable {key}"
|
|
|
|
targets = {mount["target"] for mount in gateway["volumes"]}
|
|
assert "/workspace/stack" not in targets
|
|
assert not any(target.startswith("/opt/mosaic/brain/") for target in targets)
|
|
PY
|
|
|
|
config_json=$(
|
|
cd "$repo_root"
|
|
BETTER_AUTH_SECRET=test-only-not-a-credential \
|
|
MOSAIC_DOGFOOD_WORKTREE="$tmp/worktree" \
|
|
MOSAIC_DOGFOOD_COMMON_GIT_DIR="$tmp/common.git" \
|
|
MOSAIC_DOGFOOD_SEAT_HOME="$tmp/seat" \
|
|
docker compose \
|
|
-f docker-compose.yml \
|
|
-f docker-compose.dogfood.yml \
|
|
--profile stack \
|
|
config --format json
|
|
)
|
|
|
|
CONFIG_JSON="$config_json" EXPECT_WORKTREE="$tmp/worktree" EXPECT_COMMON_GIT="$tmp/common.git" EXPECT_SEAT="$tmp/seat" python3 <<'PY'
|
|
import json
|
|
import os
|
|
|
|
config = json.loads(os.environ["CONFIG_JSON"])
|
|
gateway = config["services"]["gateway"]
|
|
assert gateway.get("init") is True, "gateway must run below an init process for R4 lineage"
|
|
env = gateway["environment"]
|
|
|
|
expected_env = {
|
|
"MOSAIC_AGENT_NAME": "stack-dogfood",
|
|
"MOSAIC_GIT_IDENTITY": "stack-dogfood",
|
|
"MOSAIC_BRAIN_HOME": "/opt/mosaic/brain",
|
|
"AGENT_FILE_SANDBOX_DIR": "/workspace/stack",
|
|
"AGENT_SHELL_ENABLED": "false",
|
|
"AGENT_DELIVERY_ENABLED": "true",
|
|
"MOSAIC_GIT_TOOLS_DIR": "/opt/mosaic/tools/git",
|
|
"MOSAIC_INTEGRATION_TRUNK": "next",
|
|
}
|
|
for key, value in expected_env.items():
|
|
assert env.get(key) == value, f"{key}: expected {value!r}, got {env.get(key)!r}"
|
|
|
|
allowed = set(env["AGENT_USER_TOOLS"].split(","))
|
|
assert allowed == {
|
|
"fs_read_file",
|
|
"fs_write_file",
|
|
"fs_list_directory",
|
|
"fs_edit_file",
|
|
"git_status",
|
|
"git_log",
|
|
"git_diff",
|
|
"git_publish_branch",
|
|
"git_open_pull_request",
|
|
}, f"unexpected dogfood tool set: {sorted(allowed)}"
|
|
assert "shell_exec" not in allowed
|
|
|
|
mounts = {mount["target"]: mount for mount in gateway["volumes"]}
|
|
worktree = mounts["/workspace/stack"]
|
|
assert worktree["type"] == "bind"
|
|
assert worktree["source"] == os.environ["EXPECT_WORKTREE"]
|
|
assert not worktree.get("read_only", False), "dogfood worktree must be writable"
|
|
|
|
common_git = mounts[os.environ["EXPECT_COMMON_GIT"]]
|
|
assert common_git["type"] == "bind"
|
|
assert common_git["source"] == os.environ["EXPECT_COMMON_GIT"]
|
|
assert not common_git.get("read_only", False), "common Git directory must accept branch updates"
|
|
|
|
seat = mounts["/opt/mosaic/brain/fleet/agents/stack-dogfood"]
|
|
assert seat["type"] == "bind"
|
|
assert seat["source"] == os.environ["EXPECT_SEAT"]
|
|
assert seat.get("read_only") is True, "seat credential slot must be read-only"
|
|
|
|
other_seat_mounts = [
|
|
target
|
|
for target in mounts
|
|
if target.startswith("/opt/mosaic/brain/fleet/agents/")
|
|
and target != "/opt/mosaic/brain/fleet/agents/stack-dogfood"
|
|
]
|
|
assert other_seat_mounts == [], f"other seat mounts leaked: {other_seat_mounts}"
|
|
PY
|
|
|
|
# Each required path must fail closed rather than falling back to the current checkout.
|
|
expect_missing_path() {
|
|
local missing=$1 output rc
|
|
set +e
|
|
case "$missing" in
|
|
MOSAIC_DOGFOOD_WORKTREE)
|
|
output=$(
|
|
cd "$repo_root"
|
|
env -u MOSAIC_DOGFOOD_WORKTREE \
|
|
BETTER_AUTH_SECRET=test-only-not-a-credential \
|
|
MOSAIC_DOGFOOD_COMMON_GIT_DIR="$tmp/common.git" \
|
|
MOSAIC_DOGFOOD_SEAT_HOME="$tmp/seat" \
|
|
docker compose -f docker-compose.yml -f docker-compose.dogfood.yml \
|
|
--profile stack config 2>&1
|
|
)
|
|
rc=$?
|
|
;;
|
|
MOSAIC_DOGFOOD_COMMON_GIT_DIR)
|
|
output=$(
|
|
cd "$repo_root"
|
|
env -u MOSAIC_DOGFOOD_COMMON_GIT_DIR \
|
|
BETTER_AUTH_SECRET=test-only-not-a-credential \
|
|
MOSAIC_DOGFOOD_WORKTREE="$tmp/worktree" \
|
|
MOSAIC_DOGFOOD_SEAT_HOME="$tmp/seat" \
|
|
docker compose -f docker-compose.yml -f docker-compose.dogfood.yml \
|
|
--profile stack config 2>&1
|
|
)
|
|
rc=$?
|
|
;;
|
|
MOSAIC_DOGFOOD_SEAT_HOME)
|
|
output=$(
|
|
cd "$repo_root"
|
|
env -u MOSAIC_DOGFOOD_SEAT_HOME \
|
|
BETTER_AUTH_SECRET=test-only-not-a-credential \
|
|
MOSAIC_DOGFOOD_WORKTREE="$tmp/worktree" \
|
|
MOSAIC_DOGFOOD_COMMON_GIT_DIR="$tmp/common.git" \
|
|
docker compose -f docker-compose.yml -f docker-compose.dogfood.yml \
|
|
--profile stack config 2>&1
|
|
)
|
|
rc=$?
|
|
;;
|
|
*)
|
|
echo "FAIL: test requested unknown path variable $missing" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
set -e
|
|
if [[ $rc -eq 0 ]]; then
|
|
echo "FAIL: dogfood compose accepted missing $missing" >&2
|
|
exit 1
|
|
fi
|
|
if [[ "$output" != *"$missing"* ]]; then
|
|
echo "FAIL: missing-path failure did not name $missing" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
expect_missing_path MOSAIC_DOGFOOD_WORKTREE
|
|
expect_missing_path MOSAIC_DOGFOOD_COMMON_GIT_DIR
|
|
expect_missing_path MOSAIC_DOGFOOD_SEAT_HOME
|
|
|
|
printf 'dogfood compose verification passed\n'
|