test(10.2-02): add nested-layout hygiene gate
- Refuse root package directories, old imports, missing READMEs, and stale status text\n- Validate Go vet and tests across framework and Fonoteka
This commit is contained in:
161
scripts/check-phase10.2.sh
Executable file
161
scripts/check-phase10.2.sh
Executable file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env bash
|
||||
# Phase 10.2 fail-closed gate for the nested framework layout and onboarding.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
APP="$(cd "$ROOT/../fonoteka.go" && pwd)"
|
||||
NAMES=(backpack boardwalk bonfire bouncer cabana compass festival fetchguard lagoon pact party phrasebook postcard surf tide towel wire wristband)
|
||||
IMPORT_PREFIX='git.golem15.com/golem15/summercms/'
|
||||
STALE_STATUS='Pre-alpha. Planning and research. Nothing runs yet.'
|
||||
|
||||
usage() {
|
||||
cat >&2 <<'EOF'
|
||||
usage:
|
||||
check-phase10.2.sh --self-test
|
||||
check-phase10.2.sh --layout
|
||||
check-phase10.2.sh --imports
|
||||
check-phase10.2.sh --readmes
|
||||
check-phase10.2.sh --status
|
||||
check-phase10.2.sh --go
|
||||
check-phase10.2.sh --all
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
refuse() {
|
||||
echo "refuse: $*" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
tracked_source_files() {
|
||||
local repo="$1"
|
||||
if git -C "$repo" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
git -C "$repo" ls-files -z -- '*.go' '*.tmpl' '*.sh'
|
||||
return
|
||||
fi
|
||||
(
|
||||
cd "$repo"
|
||||
find . -path './.planning' -prune -o -type f \( -name '*.go' -o -name '*.tmpl' -o -name '*.sh' \) -print0
|
||||
)
|
||||
}
|
||||
|
||||
check_layout() {
|
||||
local root="$1" name
|
||||
for name in "${NAMES[@]}"; do
|
||||
if [[ -d "$root/$name" ]]; then
|
||||
refuse "leftover root dir: $name"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_imports_in() {
|
||||
local repo="$1" file name
|
||||
while IFS= read -r -d '' file; do
|
||||
[[ "$file" != 'scripts/check-phase10.2.sh' ]] || continue
|
||||
for name in "${NAMES[@]}"; do
|
||||
if grep -Fq "${IMPORT_PREFIX}${name}" "$repo/$file"; then
|
||||
refuse "old import: $repo/$file uses ${name} outside modules"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
done < <(tracked_source_files "$repo")
|
||||
}
|
||||
|
||||
check_imports() {
|
||||
check_imports_in "$1" || return 1
|
||||
check_imports_in "$2"
|
||||
}
|
||||
|
||||
check_readmes() {
|
||||
local root="$1" name
|
||||
for name in "${NAMES[@]}"; do
|
||||
if [[ ! -f "$root/modules/$name/README.md" ]]; then
|
||||
refuse "missing README: modules/$name/README.md"
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
check_status() {
|
||||
local root="$1"
|
||||
if grep -Fq "$STALE_STATUS" "$root/README.md"; then
|
||||
refuse "stale Status: README still claims nothing runs"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_hygiene() {
|
||||
local root="$1" app="$2"
|
||||
check_layout "$root" || return 1
|
||||
check_imports "$root" "$app" || return 1
|
||||
check_readmes "$root" || return 1
|
||||
check_status "$root" || return 1
|
||||
}
|
||||
|
||||
run_go() {
|
||||
(cd "$ROOT" && go vet ./...)
|
||||
(cd "$ROOT" && go test ./...)
|
||||
(cd "$APP" && go vet ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/...)
|
||||
(cd "$APP" && go test ./... ./plugins/golem15/fonoteka/... ./plugins/golem15/user/...)
|
||||
echo "phase10.2 go passed"
|
||||
}
|
||||
|
||||
expect_refusal() {
|
||||
local name="$1" want="$2" root="$3" app="$4" output
|
||||
if output="$(check_hygiene "$root" "$app" 2>&1)"; then
|
||||
echo "refuse: self-test accepted planted $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -Fq "$want" <<<"$output"; then
|
||||
echo "refuse: self-test $name failed for the wrong rule: $output" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
run_self_test() {
|
||||
bash -n "${BASH_SOURCE[0]}"
|
||||
local scratch app name
|
||||
scratch="$(mktemp -d)"
|
||||
app="$(mktemp -d)"
|
||||
trap 'rm -rf "$scratch" "$app"' RETURN
|
||||
cp "$ROOT/README.md" "$scratch/README.md"
|
||||
for name in "${NAMES[@]}"; do
|
||||
mkdir -p "$scratch/modules/$name"
|
||||
cp "$ROOT/modules/$name/README.md" "$scratch/modules/$name/README.md"
|
||||
done
|
||||
|
||||
check_hygiene "$scratch" "$app"
|
||||
|
||||
mkdir "$scratch/backpack"
|
||||
expect_refusal 'leftover root dir' 'leftover root dir' "$scratch" "$app"
|
||||
rmdir "$scratch/backpack"
|
||||
|
||||
printf '%s%s\n' "$IMPORT_PREFIX" backpack >"$scratch/old_import.go"
|
||||
expect_refusal 'old import' 'old import' "$scratch" "$app"
|
||||
rm "$scratch/old_import.go"
|
||||
|
||||
mv "$scratch/modules/backpack/README.md" "$scratch/modules/backpack/README.saved"
|
||||
expect_refusal 'missing README' 'missing README' "$scratch" "$app"
|
||||
mv "$scratch/modules/backpack/README.saved" "$scratch/modules/backpack/README.md"
|
||||
|
||||
printf '\n%s\n' "$STALE_STATUS" >>"$scratch/README.md"
|
||||
expect_refusal 'stale Status' 'stale Status' "$scratch" "$app"
|
||||
|
||||
echo "phase10.2 self-test passed"
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
--self-test) run_self_test ;;
|
||||
--layout) check_layout "$ROOT" ;;
|
||||
--imports) check_imports "$ROOT" "$APP" ;;
|
||||
--readmes) check_readmes "$ROOT" ;;
|
||||
--status) check_status "$ROOT" ;;
|
||||
--go) run_go ;;
|
||||
--all)
|
||||
check_hygiene "$ROOT" "$APP"
|
||||
run_go
|
||||
echo "phase10.2 check passed"
|
||||
;;
|
||||
*) usage ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user