138 lines
5.7 KiB
Bash
Executable File
138 lines
5.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Regression test for copyable installation examples and secret-path validation.
|
|
set -euo pipefail
|
|
|
|
root="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
output="$(mktemp "${TMPDIR:-/tmp}/thoth-install-docs-test.XXXXXX")"
|
|
verifier_functions="$(mktemp "${TMPDIR:-/tmp}/thoth-install-docs-functions.XXXXXX")"
|
|
negative_root="$(mktemp -d "${TMPDIR:-/tmp}/thoth-install-docs-negative.XXXXXX")"
|
|
trap 'rm -f "$output" "$verifier_functions"; rm -rf "$negative_root"' EXIT HUP INT TERM
|
|
|
|
"$root/scripts/verify-workspace-install-docs.sh" --fixtures-only >"$output"
|
|
|
|
for fixture in \
|
|
"local installation guide contract" \
|
|
"Windows line-ending recovery guide contract" \
|
|
"Pi management guide contract" \
|
|
"local installation example rendered from path with spaces" \
|
|
"local manual canonical base+override references" \
|
|
"server manual canonical base+override references" \
|
|
"canonical local base+override fixture" \
|
|
"canonical server base+override fixture" \
|
|
"relative secret-source fixture rejected" \
|
|
"CRLF recovery rewrites worktree bytes"; do
|
|
grep -Fqx "$fixture passed" "$output" >/dev/null || {
|
|
echo "missing fixture verification: $fixture" >&2
|
|
cat "$output" >&2
|
|
exit 1
|
|
}
|
|
done
|
|
|
|
for manual in \
|
|
"$root/docs/install/local-workspace-registry.md" \
|
|
"$root/docs/install/server-workspace-registry.md"; do
|
|
grep -Fq 'export THT_SOURCE_ROOT=/absolute/path/to/ThothII' "$manual" || {
|
|
echo "installation manual does not publish a self-contained THT_SOURCE_ROOT export: $manual" >&2
|
|
exit 1
|
|
}
|
|
grep -Fq 'export THT_WORKSPACE_BINDINGS_ENV_FILE=' "$manual" || {
|
|
echo "installation manual does not publish a self-contained bindings export: $manual" >&2
|
|
exit 1
|
|
}
|
|
if rg -n 'source[[:space:]]+\.env' "$manual"; then
|
|
echo "installation manual unsafely imports operator .env: $manual" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
if rg -n 'local-compose\.workspace-registry|server-compose\.workspace-registry|connector-secrets\.workspace-registry|docker compose' \
|
|
"$root/docs/install/local-workspace-registry.md" \
|
|
"$root/docs/install/server-workspace-registry.md"; then
|
|
echo "installation manuals still document a bypassed Compose or copied connector override path" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Load only the verifier's function definitions so each deliberately unsafe guide can be checked
|
|
# in isolation without invoking Docker-backed Compose fixtures.
|
|
sed '/^case "\$mode" in/,$d' "$root/scripts/verify-workspace-install-docs.sh" >"$verifier_functions"
|
|
# shellcheck source=/dev/null
|
|
source "$verifier_functions"
|
|
|
|
negative_failures=0
|
|
expect_guide_rejected() {
|
|
local label="$1" validator="$2" source_guide="$3" relative_path="$4"
|
|
local mutation="$5" expected_error="$6"
|
|
local fixture_root="$negative_root/${label// /-}"
|
|
local fixture_output="$fixture_root/output"
|
|
mkdir -p "$fixture_root/$(dirname "$relative_path")"
|
|
cp "$source_guide" "$fixture_root/$relative_path"
|
|
node - "$fixture_root/$relative_path" "$mutation" <<'NODE'
|
|
const fs = require("fs");
|
|
const [path, mutation] = process.argv.slice(2);
|
|
const original = fs.readFileSync(path, "utf8");
|
|
let changed = original;
|
|
switch (mutation) {
|
|
case "durable-selector":
|
|
changed = original.replaceAll("--source build", "--source stale-build");
|
|
break;
|
|
case "dangerous-volumes":
|
|
changed = original.replace("Do **not** run `docker compose down --volumes`", "Run `docker compose down --volumes`");
|
|
break;
|
|
case "incomplete-powershell":
|
|
changed = original.replaceAll("icacls.exe", "Write-Output");
|
|
break;
|
|
case "broken-crlf":
|
|
changed = original.replaceAll("git checkout-index --all --force --prefix=", "git add --renormalize . # ");
|
|
break;
|
|
case "raw-pi":
|
|
changed += "\n```sh\ndocker compose exec core pi --version\n```\n";
|
|
break;
|
|
default:
|
|
throw new Error(`unknown negative-fixture mutation: ${mutation}`);
|
|
}
|
|
if (changed === original) throw new Error(`negative-fixture mutation made no change: ${mutation}`);
|
|
fs.writeFileSync(path, changed);
|
|
NODE
|
|
set +e
|
|
(root="$fixture_root"; set -e; "$validator") >"$fixture_output" 2>&1
|
|
local status=$?
|
|
set -e
|
|
if [[ $status -eq 0 ]]; then
|
|
echo "negative fixture accepted: $label" >&2
|
|
cat "$fixture_output" >&2
|
|
negative_failures=$((negative_failures + 1))
|
|
elif ! grep -Fq -- "$expected_error" "$fixture_output"; then
|
|
echo "negative fixture failed for the wrong reason: $label" >&2
|
|
cat "$fixture_output" >&2
|
|
negative_failures=$((negative_failures + 1))
|
|
fi
|
|
}
|
|
|
|
expect_guide_rejected \
|
|
"durable selector keeps old core" verify_local_guide \
|
|
"$root/docs/install/local.md" docs/install/local.md durable-selector \
|
|
"installation-aware source update lacks structural token: --source build"
|
|
expect_guide_rejected \
|
|
"dangerous down volumes instruction" verify_local_guide \
|
|
"$root/docs/install/local.md" docs/install/local.md dangerous-volumes \
|
|
"docker compose down --volumes must appear only in an explicit prose prohibition"
|
|
expect_guide_rejected \
|
|
"incomplete native PowerShell path" verify_local_guide \
|
|
"$root/docs/install/local.md" docs/install/local.md incomplete-powershell \
|
|
"native PowerShell setup lacks structural token: icacls.exe"
|
|
expect_guide_rejected \
|
|
"renormalize leaves CRLF worktree bytes" verify_windows_line_endings_guide \
|
|
"$root/docs/install/windows-line-endings.md" docs/install/windows-line-endings.md broken-crlf \
|
|
"Windows line-ending guide lacks required instruction: git checkout-index --all --force"
|
|
expect_guide_rejected \
|
|
"raw non-installation-aware Pi access" verify_pi_management_guide \
|
|
"$root/docs/install/pi-management.md" docs/install/pi-management.md raw-pi \
|
|
"raw non-installation-aware Compose Pi access is forbidden"
|
|
|
|
if (( negative_failures != 0 )); then
|
|
echo "$negative_failures unsafe installation-document fixtures were accepted" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "unsafe installation-document fixtures rejected passed"
|