feat: add runner conversion scripts and strengthen cutover automation
This commit is contained in:
115
runners-conversion/augur/check-contract-drift.sh
Executable file
115
runners-conversion/augur/check-contract-drift.sh
Executable file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
# check-contract-drift.sh — Enforce Constitution Principle V (contracts stay in lock-step).
|
||||
#
|
||||
# Fails when boundary-signature changes are detected under internal layers without
|
||||
# any update under contracts/*.md in the same diff range.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
log() {
|
||||
printf '[contract-drift] %s\n' "$*"
|
||||
}
|
||||
|
||||
err() {
|
||||
printf '[contract-drift] ERROR: %s\n' "$*" >&2
|
||||
}
|
||||
|
||||
resolve_range() {
|
||||
if [[ -n "${AUGUR_CONTRACT_DRIFT_RANGE:-}" ]]; then
|
||||
printf '%s' "$AUGUR_CONTRACT_DRIFT_RANGE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "${GITHUB_BASE_REF:-}" ]]; then
|
||||
git fetch --no-tags --depth=1 origin "$GITHUB_BASE_REF" >/dev/null 2>&1 || true
|
||||
printf 'origin/%s...HEAD' "$GITHUB_BASE_REF"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "${GITHUB_EVENT_BEFORE:-}" ]] && [[ -n "${GITHUB_SHA:-}" ]] && [[ "$GITHUB_EVENT_BEFORE" != "0000000000000000000000000000000000000000" ]]; then
|
||||
printf '%s...%s' "$GITHUB_EVENT_BEFORE" "$GITHUB_SHA"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if git rev-parse --verify HEAD~1 >/dev/null 2>&1; then
|
||||
printf 'HEAD~1...HEAD'
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf ''
|
||||
}
|
||||
|
||||
USE_WORKTREE="${AUGUR_CONTRACT_DRIFT_USE_WORKTREE:-0}"
|
||||
RANGE=""
|
||||
if [[ "$USE_WORKTREE" == "1" ]]; then
|
||||
log "Diff source: working tree (HEAD -> working tree)"
|
||||
changed_files="$(git diff --name-only)"
|
||||
else
|
||||
RANGE="$(resolve_range)"
|
||||
if [[ -z "$RANGE" ]]; then
|
||||
log "No diff range could be resolved; skipping contract drift check."
|
||||
exit 0
|
||||
fi
|
||||
log "Diff range: $RANGE"
|
||||
changed_files="$(git diff --name-only "$RANGE")"
|
||||
fi
|
||||
|
||||
if [[ -z "$changed_files" ]]; then
|
||||
log "No changed files in range; skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if printf '%s\n' "$changed_files" | grep -Eq '^contracts/.*\.md$'; then
|
||||
log "Contract files changed in range; check passed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Boundary-sensitive files that define cross-layer contracts.
|
||||
boundary_files="$(printf '%s\n' "$changed_files" | grep -E '^internal/(cli|service|provider|storage|sync|model)/.*\.go$' || true)"
|
||||
|
||||
if [[ -z "$boundary_files" ]]; then
|
||||
log "No boundary-sensitive Go files changed; check passed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
violations=()
|
||||
|
||||
while IFS= read -r file; do
|
||||
[[ -z "$file" ]] && continue
|
||||
|
||||
# Canonical model and provider interface are always contract-relevant.
|
||||
if [[ "$file" == "internal/model/conversation.go" ]] || [[ "$file" == "internal/provider/provider.go" ]]; then
|
||||
violations+=("$file")
|
||||
continue
|
||||
fi
|
||||
|
||||
# Heuristic: exported symbol signature/shape changes in boundary layers are contract-relevant.
|
||||
# Matches exported funcs, exported interfaces, and exported struct fields with JSON tags.
|
||||
diff_output=""
|
||||
if [[ "$USE_WORKTREE" == "1" ]]; then
|
||||
diff_output="$(git diff -U0 -- "$file")"
|
||||
else
|
||||
diff_output="$(git diff -U0 "$RANGE" -- "$file")"
|
||||
fi
|
||||
|
||||
if printf '%s\n' "$diff_output" | grep -Eq '^[+-](func (\([^)]*\) )?[A-Z][A-Za-z0-9_]*\(|type [A-Z][A-Za-z0-9_]* interface|[[:space:]]+[A-Z][A-Za-z0-9_]*[[:space:]].*`json:"[^"]+"`)'; then
|
||||
violations+=("$file")
|
||||
fi
|
||||
done <<< "$boundary_files"
|
||||
|
||||
if [[ "${#violations[@]}" -eq 0 ]]; then
|
||||
log "No contract-relevant signature drift detected; check passed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
err "Contract drift detected: contract-relevant files changed without contracts/*.md updates."
|
||||
err "Update the applicable contract file(s) in contracts/ in the same change."
|
||||
err "Impacted files:"
|
||||
for file in "${violations[@]}"; do
|
||||
err " - $file"
|
||||
done
|
||||
|
||||
exit 1
|
||||
Reference in New Issue
Block a user