refactor: keep compiler source standalone
Signed-off-by: Cole Speelman <crspeelman@gmail.com>
This commit is contained in:
+2
-4
@@ -4,11 +4,9 @@
|
||||
|
||||
These scripts are intentionally understandable shell and PowerShell rather than a release framework with hidden defaults.
|
||||
|
||||
- `verify.sh` runs root and nested-module tests and vet, builds `himesan`, tests each example module, checks committed generated output, and proves two generation passes leave the same bytes and unchanged modification times. Set `HIMESAN_RACE=1` for race tests.
|
||||
- `verify.sh` runs root and nested-module tests and vet, builds `himesan`, checks the compiler-owned golden output, and proves two generation passes leave the same bytes and unchanged modification times. Set `HIMESAN_RACE=1` for race tests.
|
||||
- `verify.ps1` provides the equivalent native Windows lane; pass `-Race` to include the race detector.
|
||||
- `check-licenses.sh` enforces the AGPL compiler / Apache runtime / 0BSD example boundary and prevents generated application Go from inheriting an AGPL identifier.
|
||||
- `check-site.sh` verifies vanity metadata, no-script/local-asset policy, pre-release honesty, and baseline accessibility scaffolding for the static site.
|
||||
- `eql-integration.sh` is opt-in. Until a repository-owned `internal/integration/eql` test exists it exits successfully without inspecting EQL. Later it requires external `HIMESAN_EQL_ROOT` and `HIMESAN_EQL_DB` paths and passes a read-only-mode contract to that package. It never copies a database.
|
||||
- `check-licenses.sh` enforces the AGPL compiler / Apache runtime boundary and prevents generated application Go from inheriting an AGPL identifier.
|
||||
- `release-check.sh --version vX.Y.Z` is a clean-checkout technical preflight. Add `--public` and point `HIMESAN_RELEASE_EVIDENCE_DIR` at a human-reviewed evidence bundle for the public-launch gate. It never tags, pushes, publishes, or deploys.
|
||||
- `verify-public-install.sh --version vX.Y.Z` is a post-tag/publication check. It verifies exact `go-get=1` package routes and runs the documented compiler install and runtime get from fresh direct-fetch and public-proxy caches without interactive Git credentials.
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@ fail() {
|
||||
|
||||
expected_spdx() {
|
||||
case "$1" in
|
||||
examples/*)
|
||||
printf '0BSD\n'
|
||||
;;
|
||||
sando/*)
|
||||
printf 'Apache-2.0\n'
|
||||
;;
|
||||
@@ -77,7 +74,6 @@ list_project_files() {
|
||||
|
||||
[[ -f LICENSE ]] || fail 'root LICENSE is missing'
|
||||
[[ -f sando/LICENSE ]] || fail 'sando/LICENSE is missing'
|
||||
[[ -f examples/eql-shaped/LICENSE ]] || fail 'example LICENSE is missing'
|
||||
[[ -f DCO.txt ]] || fail 'DCO.txt is missing'
|
||||
|
||||
if [[ -f LICENSE ]]; then
|
||||
@@ -86,16 +82,11 @@ fi
|
||||
if [[ -f sando/LICENSE ]]; then
|
||||
check_sha256 sando/LICENSE c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4
|
||||
fi
|
||||
if [[ -f examples/eql-shaped/LICENSE ]]; then
|
||||
check_sha256 examples/eql-shaped/LICENSE 7e2406acc98391ec126b13d512c00b930bbc2c19f4d5b0fe52286ae41bfbc92d
|
||||
grep -Fq 'Copyright (c) 2025-2026 Cole Speelman' examples/eql-shaped/LICENSE || \
|
||||
fail 'example LICENSE must identify its original author'
|
||||
fi
|
||||
if [[ -f DCO.txt ]]; then
|
||||
check_sha256 DCO.txt f7ac75b443f4ca16b503241344b41aeff9503b0c30bedc2b119551d83cb0fa90
|
||||
fi
|
||||
|
||||
for required in COPYRIGHT OUTPUT_EXCEPTION.md sando/COPYRIGHT examples/eql-shaped/LICENSES.md; do
|
||||
for required in COPYRIGHT OUTPUT_EXCEPTION.md sando/COPYRIGHT; do
|
||||
[[ -f $required ]] || fail "$required is required for ownership/output licensing"
|
||||
done
|
||||
|
||||
@@ -126,7 +117,7 @@ while IFS= read -r -d '' path; do
|
||||
[[ -f $path ]] || continue
|
||||
|
||||
case "$path" in
|
||||
LICENSE | sando/LICENSE | examples/*/LICENSE | DCO.txt)
|
||||
LICENSE | sando/LICENSE | DCO.txt)
|
||||
# These are reviewed legal texts with their own notices.
|
||||
continue
|
||||
;;
|
||||
@@ -161,9 +152,7 @@ while IFS= read -r -d '' path; do
|
||||
continue
|
||||
;;
|
||||
*.json)
|
||||
if [[ $path != examples/eql-shaped/himesan.json ]]; then
|
||||
fail "$path cannot carry a comment and needs an explicit license-map entry"
|
||||
fi
|
||||
fail "$path cannot carry a comment and needs an explicit license-map entry"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
@@ -178,23 +167,6 @@ while IFS= read -r -d '' path; do
|
||||
fail "$path must carry exactly one SPDX identifier: $expected"
|
||||
done < <(list_project_files)
|
||||
|
||||
if [[ -f examples/eql-shaped/LICENSES.md ]]; then
|
||||
grep -Fq '`himesan.json`' examples/eql-shaped/LICENSES.md || \
|
||||
fail 'example license map must cover himesan.json'
|
||||
grep -Fq '`.sando.go`' examples/eql-shaped/LICENSES.md || \
|
||||
fail 'example license map must cover generated output'
|
||||
fi
|
||||
|
||||
if [[ -d examples ]] && find examples -type f -name go.mod -print -quit | grep -q .; then
|
||||
while IFS= read -r -d '' module_file; do
|
||||
module_dir=$(dirname -- "$module_file")
|
||||
license_file=$module_dir/LICENSE
|
||||
map_file=$module_dir/LICENSES.md
|
||||
[[ -f $license_file ]] || fail "example module $module_dir needs a local 0BSD LICENSE"
|
||||
[[ -f $map_file ]] || fail "example module $module_dir needs a local license map"
|
||||
done < <(find examples -type d \( -name .git -o -name vendor \) -prune -o -type f -name go.mod -print0)
|
||||
fi
|
||||
|
||||
if find sando -type f -name '*.go' -exec grep -En \
|
||||
'"gamertan\.com/sandwich-hime/(cmd|internal)(/|"|$)' {} + | grep -q .; then
|
||||
fail 'the Apache runtime imports AGPL compiler or CLI code'
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
repo_root=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
cd "$repo_root"
|
||||
|
||||
public_version=''
|
||||
if (( $# > 0 )); then
|
||||
if [[ "$1" != --public || $# -ne 2 ]]; then
|
||||
printf 'usage: scripts/check-site.sh [--public vX.Y.Z]\n' >&2
|
||||
exit 2
|
||||
fi
|
||||
public_version=$2
|
||||
fi
|
||||
|
||||
fail() {
|
||||
printf 'site error: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
for page in site/index.html site/sando/index.html; do
|
||||
[[ -f "$page" ]] || fail "missing $page"
|
||||
grep -Fq '<html lang="en">' "$page" || fail "$page needs a document language"
|
||||
grep -Fq '<meta name="viewport"' "$page" || fail "$page needs responsive viewport metadata"
|
||||
grep -Fq 'class="skip-link"' "$page" || fail "$page needs a keyboard skip link"
|
||||
grep -Fq '<main id="main">' "$page" || fail "$page needs the skip-link target"
|
||||
grep -Fq '<h1>' "$page" || grep -Fq '<h1 ' "$page" || fail "$page needs an h1"
|
||||
grep -Fq 'Content-Security-Policy' "$page" || fail "$page needs a preview CSP"
|
||||
grep -Fq '<meta name="himesan-release-status" content="' "$page" || \
|
||||
fail "$page needs machine-readable release status"
|
||||
done
|
||||
|
||||
grep -Fq '<meta name="go-import" content="gamertan.com/sandwich-hime git https://gitea.speelman.ca/gamertan/sandwich-hime.git">' \
|
||||
site/index.html || fail 'compiler vanity-import metadata is missing or changed'
|
||||
grep -Fq '<meta name="go-import" content="gamertan.com/sandwich-hime/sando git https://gitea.speelman.ca/gamertan/sandwich-hime.git sando">' \
|
||||
site/sando/index.html || fail 'nested runtime vanity-import metadata is missing or changed'
|
||||
|
||||
if find site -type f -name '*.html' -exec grep -Ein '<script([[:space:]>])' {} + | grep -q .; then
|
||||
fail 'the static project site must not contain JavaScript'
|
||||
fi
|
||||
if find site -type f -name '*.html' -exec grep -Ein \
|
||||
'(src|href)="https?://[^" ]+\.(js|css)([?"#])' {} + | grep -q .; then
|
||||
fail 'the static project site must not load remote JavaScript or CSS'
|
||||
fi
|
||||
if find site -type f -name '*.css' -exec grep -Ein \
|
||||
"(@import|url\\()[[:space:]\"']*https?://" {} + | grep -q .; then
|
||||
fail 'the static project site must not load remote CSS assets'
|
||||
fi
|
||||
|
||||
grep -Fq 'prefers-reduced-motion' site/assets/site.css || fail 'site CSS needs a reduced-motion preference'
|
||||
grep -Fq 'forced-colors' site/assets/site.css || fail 'site CSS needs a forced-colors fallback'
|
||||
grep -Fq 'class="wordmark" role="img"' site/index.html || \
|
||||
fail 'the ASCII wordmark needs an accessible semantic role'
|
||||
grep -Fq 'class="code" tabindex="0" role="region"' site/index.html || \
|
||||
fail 'the scrollable code example needs keyboard access and a region role'
|
||||
|
||||
if [[ -n "$public_version" ]]; then
|
||||
for page in site/index.html site/sando/index.html; do
|
||||
grep -Fq "<meta name=\"himesan-release-status\" content=\"$public_version\">" "$page" || \
|
||||
fail "$page release status does not match $public_version"
|
||||
done
|
||||
if grep -Eiq 'not a public release|not released yet|private pre-release|public pre-1\.0|unsupported pre-1\.0|no (supported )?public .*tag' \
|
||||
site/index.html site/sando/index.html; then
|
||||
fail 'public-release site still contains a pre-release warning'
|
||||
fi
|
||||
else
|
||||
if grep -Fq '<meta name="himesan-release-status" content="pre-release">' site/index.html; then
|
||||
grep -Eiq 'public pre-1\.0|unsupported pre-1\.0|not released yet' site/index.html || \
|
||||
fail 'the pre-release landing page must state its status in human-readable text'
|
||||
fi
|
||||
fi
|
||||
|
||||
printf 'Static site metadata, local-asset policy, and accessibility scaffolding are present.\n'
|
||||
@@ -64,7 +64,7 @@ case "$origin_url" in
|
||||
https://gitea.speelman.ca/gamertan/sandwich-hime.git)
|
||||
;;
|
||||
*)
|
||||
printf 'error: origin is not the canonical Gamertan Gitea repository: %s\n' "$origin_url" >&2
|
||||
printf 'error: origin is not the canonical Gitea repository: %s\n' "$origin_url" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -131,9 +131,6 @@ for target in \
|
||||
done
|
||||
|
||||
for required in \
|
||||
site/index.html \
|
||||
site/sando/index.html \
|
||||
site/README.md \
|
||||
scripts/verify-public-install.sh \
|
||||
RELEASE.md \
|
||||
SECURITY.md \
|
||||
@@ -142,11 +139,6 @@ for required in \
|
||||
[[ -f "$required" ]] || { printf 'error: required release file is missing: %s\n' "$required" >&2; exit 1; }
|
||||
done
|
||||
|
||||
if ! grep -Fq 'gamertan.com/sandwich-hime/sando git' site/sando/index.html; then
|
||||
printf 'error: nested runtime vanity-import metadata is missing\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (( public_release == 1 )); then
|
||||
evidence_dir=${HIMESAN_RELEASE_EVIDENCE_DIR:-}
|
||||
if [[ -z "$evidence_dir" || ! -d "$evidence_dir" ]]; then
|
||||
@@ -154,18 +146,18 @@ if (( public_release == 1 )); then
|
||||
exit 1
|
||||
fi
|
||||
for evidence in \
|
||||
counsel-review.md \
|
||||
legal-review.md \
|
||||
cross-platform.md \
|
||||
eql-production-soak.md \
|
||||
security-and-accessibility.md \
|
||||
security.md \
|
||||
development-supervisor.md \
|
||||
benchmark-methodology.md \
|
||||
vanity-and-mirror.md; do
|
||||
vanity-imports.md \
|
||||
signing-and-recovery.md; do
|
||||
if [[ ! -s "$evidence_dir/$evidence" ]]; then
|
||||
printf 'error: public release evidence is missing or empty: %s\n' "$evidence_dir/$evidence" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
./scripts/check-site.sh --public "$version"
|
||||
printf '\nHuman review is still required; evidence presence is not automatic approval.\n'
|
||||
else
|
||||
printf '\nTechnical preflight passed. Public launch remains blocked until --public evidence review passes.\n'
|
||||
|
||||
@@ -7,7 +7,7 @@ usage() {
|
||||
cat <<'EOF'
|
||||
Usage: scripts/verify-public-install.sh --version vX.Y.Z
|
||||
|
||||
Post-publication verification for Gamertan vanity metadata and the exact
|
||||
Post-publication verification for gamertan.com vanity metadata and the exact
|
||||
documented install commands. It uses fresh temporary Go caches and never writes
|
||||
to the repository. Signed compiler and sando tags must already be public.
|
||||
EOF
|
||||
|
||||
+7
-28
@@ -43,12 +43,11 @@ function Invoke-ModuleChecks {
|
||||
}
|
||||
|
||||
function Get-SandoSources {
|
||||
if (-not (Test-Path "examples" -PathType Container)) {
|
||||
if (-not (Test-Path "internal/compiler/testdata/golden" -PathType Container)) {
|
||||
return @()
|
||||
}
|
||||
|
||||
return @(Get-ChildItem "examples" -Recurse -File -Filter "*.sando" |
|
||||
Where-Object { $_.FullName -notmatch '[\\/](vendor|\.git)[\\/]' } |
|
||||
return @(Get-ChildItem "internal/compiler/testdata/golden" -File -Filter "*.sando" |
|
||||
Sort-Object FullName)
|
||||
}
|
||||
|
||||
@@ -80,29 +79,20 @@ try {
|
||||
}
|
||||
Invoke-ModuleChecks "sando" "sando runtime module"
|
||||
|
||||
if (Test-Path "examples" -PathType Container) {
|
||||
$ExampleModules = @(Get-ChildItem "examples" -Recurse -File -Filter "go.mod" |
|
||||
Where-Object { $_.FullName -notmatch '[\\/](vendor|\.git)[\\/]' } |
|
||||
Sort-Object FullName)
|
||||
}
|
||||
else {
|
||||
$ExampleModules = @()
|
||||
}
|
||||
|
||||
$Sources = @(Get-SandoSources)
|
||||
if ($Sources.Count -eq 0) {
|
||||
Write-Host "`n==> generation: no .sando examples exist yet; skipping deterministic-generation check"
|
||||
throw "compiler-owned golden .sando fixture is missing"
|
||||
}
|
||||
else {
|
||||
$SourcePaths = @($Sources | ForEach-Object { $_.FullName })
|
||||
$CheckArgs = @("run", "./cmd/himesan", "check") + $SourcePaths
|
||||
$GenerateArgs = @("run", "./cmd/himesan", "generate") + $SourcePaths
|
||||
Invoke-Checked "generation: read-only freshness check" {
|
||||
Invoke-Checked "golden generation: read-only freshness check" {
|
||||
& go $CheckArgs
|
||||
}
|
||||
$Before = Get-GeneratedManifest
|
||||
|
||||
Invoke-Checked "generation: first deterministic pass" {
|
||||
Invoke-Checked "golden generation: first deterministic pass" {
|
||||
& go $GenerateArgs
|
||||
}
|
||||
$First = Get-GeneratedManifest
|
||||
@@ -110,7 +100,7 @@ try {
|
||||
throw "generation changed committed output after check declared it fresh"
|
||||
}
|
||||
|
||||
Invoke-Checked "generation: second deterministic pass" {
|
||||
Invoke-Checked "golden generation: second deterministic pass" {
|
||||
& go $GenerateArgs
|
||||
}
|
||||
$Second = Get-GeneratedManifest
|
||||
@@ -118,22 +108,11 @@ try {
|
||||
throw "repeated generation changed output bytes or an unchanged timestamp"
|
||||
}
|
||||
|
||||
Invoke-Checked "generation: final freshness check" {
|
||||
Invoke-Checked "golden generation: final freshness check" {
|
||||
& go $CheckArgs
|
||||
}
|
||||
}
|
||||
|
||||
# Do not execute generated application code until check and both generation
|
||||
# passes prove that it is compiler-owned, current, and deterministic.
|
||||
if ($ExampleModules.Count -eq 0) {
|
||||
Write-Host "`n==> examples: no example module exists yet; skipping module tests"
|
||||
}
|
||||
else {
|
||||
foreach ($module in $ExampleModules) {
|
||||
Invoke-ModuleChecks $module.Directory.FullName "example module $($module.Directory.FullName)"
|
||||
}
|
||||
}
|
||||
|
||||
if ($Race) {
|
||||
Invoke-Checked "compiler module: race tests" { go test -race ./... }
|
||||
Push-Location "sando"
|
||||
|
||||
+9
-37
@@ -27,24 +27,11 @@ run_module_checks() {
|
||||
)
|
||||
}
|
||||
|
||||
example_sources() {
|
||||
if [[ ! -d examples ]]; then
|
||||
return 0
|
||||
fi
|
||||
find examples \
|
||||
-type d \( -name .git -o -name vendor \) -prune -o \
|
||||
golden_sources() {
|
||||
find internal/compiler/testdata/golden \
|
||||
-type f -name '*.sando' -print | LC_ALL=C sort
|
||||
}
|
||||
|
||||
example_modules() {
|
||||
if [[ ! -d examples ]]; then
|
||||
return 0
|
||||
fi
|
||||
find examples \
|
||||
-type d \( -name .git -o -name vendor \) -prune -o \
|
||||
-type f -name go.mod -print | LC_ALL=C sort
|
||||
}
|
||||
|
||||
generated_manifest() {
|
||||
local source output digest modified
|
||||
while IFS= read -r source; do
|
||||
@@ -68,7 +55,7 @@ generated_manifest() {
|
||||
modified=$(stat -f '%m' -- "$output")
|
||||
fi
|
||||
printf '%s %s %s\n' "$digest" "$modified" "$output"
|
||||
done < <(example_sources)
|
||||
done < <(golden_sources)
|
||||
}
|
||||
|
||||
log "repository scripts: shell syntax"
|
||||
@@ -92,18 +79,16 @@ if [[ ! -f sando/go.mod ]]; then
|
||||
fi
|
||||
run_module_checks sando "sando runtime module"
|
||||
|
||||
log "static project site"
|
||||
./scripts/check-site.sh
|
||||
|
||||
sources=()
|
||||
while IFS= read -r source; do
|
||||
[[ -n "$source" ]] || continue
|
||||
sources[${#sources[@]}]=$source
|
||||
done < <(example_sources)
|
||||
done < <(golden_sources)
|
||||
if (( ${#sources[@]} == 0 )); then
|
||||
log "generation: no .sando examples exist yet; skipping deterministic-generation check"
|
||||
printf 'error: compiler-owned golden .sando fixture is missing\n' >&2
|
||||
exit 1
|
||||
else
|
||||
log "generation: read-only freshness check"
|
||||
log "golden generation: read-only freshness check"
|
||||
go run ./cmd/himesan check "${sources[@]}"
|
||||
|
||||
manifest_before="$build_dir/generated-before.txt"
|
||||
@@ -111,7 +96,7 @@ else
|
||||
manifest_second="$build_dir/generated-second.txt"
|
||||
generated_manifest >"$manifest_before"
|
||||
|
||||
log "generation: first deterministic pass"
|
||||
log "golden generation: first deterministic pass"
|
||||
go run ./cmd/himesan generate "${sources[@]}"
|
||||
generated_manifest >"$manifest_first"
|
||||
if ! cmp -s "$manifest_before" "$manifest_first"; then
|
||||
@@ -120,7 +105,7 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "generation: second deterministic pass"
|
||||
log "golden generation: second deterministic pass"
|
||||
go run ./cmd/himesan generate "${sources[@]}"
|
||||
generated_manifest >"$manifest_second"
|
||||
if ! cmp -s "$manifest_first" "$manifest_second"; then
|
||||
@@ -132,19 +117,6 @@ else
|
||||
go run ./cmd/himesan check "${sources[@]}"
|
||||
fi
|
||||
|
||||
# Generated application code is not executed until the read-only freshness
|
||||
# check and both deterministic passes prove it is compiler-owned and current.
|
||||
module_count=0
|
||||
while IFS= read -r module_file; do
|
||||
[[ -n "$module_file" ]] || continue
|
||||
module_count=$((module_count + 1))
|
||||
module_dir=$(dirname -- "$module_file")
|
||||
run_module_checks "$module_dir" "example module $module_dir"
|
||||
done < <(example_modules)
|
||||
if (( module_count == 0 )); then
|
||||
log "examples: no example module exists yet; skipping module tests"
|
||||
fi
|
||||
|
||||
if [[ "${HIMESAN_RACE:-0}" == 1 ]]; then
|
||||
log "compiler module: race tests"
|
||||
go test -race ./...
|
||||
|
||||
Reference in New Issue
Block a user