Slim pre-push guard to CLI/Phoenix-only checks.

fa10bf7fa15e · AtlantisPleb · · parent 45221e515076

Slim pre-push guard to CLI/Phoenix-only checks.

The pre-push hook now runs:
- whitespace checks
- vp lint --quiet
- cargo check/test -p coder-lite when Rust CLI files change
- mix compile in apps/openagents.com when Phoenix files change

It no longer runs the full shared fast profile (all-work-contract,
agent-client-protocol, codex-app-server-protocol, STE, assure-repo,
api-worker routing tests, QA gates, etc.) on every push to main.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By
Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified .githooks/pre-push

Diff

1 file changed, +19 -84

.githooks/pre-push modified +19 -84

@@ -1,11 +1,6 @@

1 1
#!/usr/bin/env bash
2
# Pre-push guard — fast by default so local iteration stays moving.
3
# Policy: NO GitHub Actions. Direct pushes to main get cheap local policy checks;
4
# run the full deploy gate explicitly, or opt in with OPENAGENTS_PRE_PUSH_FULL_GATE=1.
5
#
6
# Enable in any checkout with:  git config core.hooksPath .githooks
7
#
8
# Guards only pushes whose remote ref is main. Other branches push freely.
2
# Pre-push guard — fast, relevant checks only.
3
# Runs: whitespace, vp lint, and targeted cargo/mix for the CLI or Phoenix backend.
9 4
set -uo pipefail
10 5
11 6
gate=0

@@ -23,114 +18,54 @@ done

23 18
24 19
[ "$gate" = 1 ] || exit 0
25 20
26
# Resolve the repo root explicitly with `-c core.bare=false`: this checkout may
27
# share a shared worktree-hub `.git` whose common config has core.bare=true (a
28
# pattern used for concurrent `git worktree` checkouts). That shared flag has
29
# no bearing on this invocation -- a pre-push hook only ever runs inside a real
30
# working tree -- but leaving it unoverridden risks `git rev-parse` mis-resolving
31
# root-relative state for this worktree. Fail loudly instead of silently
32
# operating from an empty/wrong root if resolution ever comes back empty.
33 21
root="$(git -c core.bare=false rev-parse --path-format=absolute --show-toplevel 2>/dev/null)"
34 22
if [ -z "$root" ] || [ ! -d "$root" ]; then
35
  echo "[pre-push guard] BLOCKED: could not resolve the repository root via 'git rev-parse --show-toplevel' (got '$root')." >&2
36
  echo "[pre-push guard] This can happen when a shared worktree-hub .git/config has core.bare=true or a stale worktree registration. Run 'git worktree list' and 'git rev-parse --show-toplevel' from this directory to diagnose." >&2
23
  echo "[pre-push guard] BLOCKED: could not resolve the repository root." >&2
37 24
  exit 1
38 25
fi
39 26
40 27
zero_sha="0000000000000000000000000000000000000000"
41
guard_head_before="$(git rev-parse HEAD)"
42
guard_readme_before="$(git hash-object "$root/README.md")"
43
44
verify_repository_stability() {
45
  if [ "$(git rev-parse HEAD)" != "$guard_head_before" ]; then
46
    echo "[pre-push guard] BLOCKED: a verification command mutated repository HEAD." >&2
47
    return 1
48
  fi
49
  if [ "$(git hash-object "$root/README.md")" != "$guard_readme_before" ]; then
50
    echo "[pre-push guard] BLOCKED: a verification command mutated the root README." >&2
51
    return 1
52
  fi
53
  if [ "$(sed -n '1p' "$root/README.md")" != "# OpenAgents" ] || [ "$(wc -l < "$root/README.md")" -lt 100 ]; then
54
    echo "[pre-push guard] BLOCKED: root README integrity check failed." >&2
55
    return 1
56
  fi
57
}
58
59
is_enabled() {
60
  case "${1:-}" in
61
    1|true|TRUE|yes|YES|on|ON) return 0 ;;
62
    *) return 1 ;;
63
  esac
64
}
65 28
66 29
if [ "$main_local_sha" = "$zero_sha" ]; then
67 30
  echo "[pre-push guard] BLOCKED: refusing to delete main." >&2
68 31
  exit 1
69 32
fi
70 33
71
verify_repository_stability || exit 1
72
73
echo "[pre-push guard] push to main -> running fast policy checks..." >&2
74
75 34
if [ -n "$main_local_sha" ] && [ "$main_remote_sha" != "$zero_sha" ]; then
76 35
  if ! ( cd "$root" && git diff --check "$main_remote_sha..$main_local_sha" ) >&2; then
77 36
    echo "[pre-push guard] BLOCKED: whitespace errors in pushed diff." >&2
78 37
    exit 1
79 38
  fi
39
  changed_files=$(cd "$root" && git diff --name-only "$main_remote_sha..$main_local_sha")
80 40
elif [ -n "$main_local_sha" ]; then
81 41
  if ! ( cd "$root" && git diff-tree --check --no-commit-id -r "$main_local_sha" ) >&2; then
82 42
    echo "[pre-push guard] BLOCKED: whitespace errors in pushed commit." >&2
83 43
    exit 1
84 44
  fi
45
  changed_files=$(cd "$root" && git diff-tree --no-commit-id --name-only -r "$main_local_sha")
85 46
fi
86 47
87
if ! ( cd "$root" && pnpm run check:fast ) >&2; then
88
  echo "[pre-push guard] BLOCKED: shared fast check profile failed." >&2
89
  exit 1
90
fi
48
echo "[pre-push guard] push to main -> running fast, targeted checks..." >&2
91 49
92
if [ -n "$main_local_sha" ] && [ "$main_remote_sha" != "$zero_sha" ]; then
93
  openagents_mobile_changed="$(cd "$root" && git diff --name-only "$main_remote_sha..$main_local_sha" -- apps/openagents-mobile apps/oa-updates packages/effect-native-* | sed -n '1p')"
94
else
95
  openagents_mobile_changed=""
96
fi
97
98
if [ -n "$openagents_mobile_changed" ]; then
99
  echo "[pre-push guard] OpenAgents mobile changes detected -> running typecheck + tests..." >&2
100
  if ! ( cd "$root/apps/openagents-mobile" && pnpm run typecheck && pnpm run test ) >&2; then
101
    echo "[pre-push guard] BLOCKED: OpenAgents mobile gate failed." >&2
102
    exit 1
103
  fi
104
  echo "[pre-push guard] OpenAgents mobile gate GREEN." >&2
105
else
106
  echo "[pre-push guard] OpenAgents mobile gate skipped; no supported mobile changes in pushed range." >&2
50
if ! ( cd "$root" && pnpm exec vp lint --quiet ) >&2; then
51
  echo "[pre-push guard] BLOCKED: vp lint failed." >&2
52
  exit 1
107 53
fi
108 54
109
if is_enabled "${OPENAGENTS_PRE_PUSH_FULL_GATE:-}" || is_enabled "${OPENAGENTS_PRE_PUSH_CHECK_DEPLOY:-}"; then
110
  echo "[pre-push guard] OPENAGENTS_PRE_PUSH_FULL_GATE enabled -> running check:deploy..." >&2
111
  if ! ( cd "$root/apps/openagents.com" && pnpm run check:deploy ) >&2; then
112
    echo "[pre-push guard] BLOCKED: check:deploy failed. Fix it before pushing to main." >&2
113
    exit 1
114
  fi
115
  echo "[pre-push guard] check:deploy GREEN." >&2
116
else
117
  echo "[pre-push guard] full check:deploy skipped; run it directly or set OPENAGENTS_PRE_PUSH_FULL_GATE=1 when needed." >&2
118
fi
55
# Targeted checks for the CLI and Phoenix backend.
56
cli_changed=$(echo "$changed_files" | grep -E '^crates/(coder-lite|openagents-cli)/' | sed -n '1p')
57
phoenix_changed=$(echo "$changed_files" | grep -E '^apps/openagents\.com/' | sed -n '1p')
119 58
120
if is_enabled "${OPENAGENTS_PRE_PUSH_QA:-}" || is_enabled "${OPENAGENTS_PRE_PUSH_QA_SMOKE:-}"; then
121
  echo "[pre-push guard] running warning-only Tier 1 QA smoke..." >&2
122
  if ! ( cd "$root" && node --import tsx scripts/qa-pre-push-smoke.ts ) >&2; then
123
    echo "[pre-push guard] WARNING: Tier 1 QA smoke did not pass or did not finish. Push remains allowed; Tier 2 async QA is authoritative." >&2
124
  fi
59
if [ -n "$cli_changed" ]; then
60
  echo "[pre-push guard] Rust CLI changes -> running cargo checks..." >&2
61
  ( cd "$root" && cargo check -p coder-lite ) || { echo "[pre-push guard] BLOCKED: cargo check -p coder-lite failed." >&2; exit 1; }
62
  ( cd "$root" && cargo test -p coder-lite ) || { echo "[pre-push guard] BLOCKED: cargo test -p coder-lite failed." >&2; exit 1; }
125 63
fi
126 64
127
if is_enabled "${OPENAGENTS_PRE_PUSH_QA:-}" || is_enabled "${OPENAGENTS_PRE_PUSH_ASYNC_QA:-}"; then
128
  echo "[pre-push guard] launching warning-only Tier 2 async QA on OpenAgents GCE..." >&2
129
  if ! ( cd "$root" && node --import tsx scripts/qa-async-gce-trigger.ts ) >&2; then
130
    echo "[pre-push guard] WARNING: Tier 2 async QA trigger failed. Push remains allowed; inspect oa-codex-control / GCE runner health." >&2
131
  fi
65
if [ -n "$phoenix_changed" ]; then
66
  echo "[pre-push guard] Phoenix changes -> running mix compile..." >&2
67
  ( cd "$root/apps/openagents.com" && mix compile ) || { echo "[pre-push guard] BLOCKED: mix compile failed." >&2; exit 1; }
132 68
fi
133 69
134
verify_repository_stability || exit 1
135 70
echo "[pre-push guard] fast main guard green — push allowed." >&2
136 71
exit 0

This page updates live while a promote is in flight · changelog