-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsession-start-build-ci.sh
More file actions
executable file
·64 lines (60 loc) · 3.35 KB
/
Copy pathsession-start-build-ci.sh
File metadata and controls
executable file
·64 lines (60 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env bash
# SessionStart hook: best-effort pre-build of the ci-cli binary.
#
# CORRECTION (2026-07-02): the previous version of this comment claimed a
# synchronous build here "fixes it for the rest of the session" — that is
# false, confirmed against code.claude.com/docs/en/mcp and
# .../claude-code-on-the-web. SessionStart hooks and MCP server connection
# attempts are NOT ordered: MCP startup is "non-blocking by default" and
# dials configured servers concurrently with hooks, not after them. A cold
# `cargo build -p ci-cli` (~59s measured: tree-sitter grammars + stack-graphs
# + bundled SQLite) can easily still be running when the "ci" server's
# initial connection attempt times out — which gets at most 3 quick retries
# (~7s total backoff, v2.1.121+) before Claude Code marks the server failed
# for the rest of the session, with no further retry. This hook can *win*
# that race, but cannot *guarantee* winning it — see
# docs/cloud-environment-setup.md for why the real fix is a Cloud
# environment Setup Script (runs once, before Claude Code launches at all,
# cached across sessions), not anything that runs from SessionStart.
#
# This hook is still worth keeping for two reasons: (1) it's the only
# mechanism available for local/non-cloud Claude Code, where there is no
# environment Setup Script concept at all; (2) unlike
# `ci-mcp-entrypoint.sh` (.mcp.json's actual entrypoint, which only builds
# when the binary is *missing*), this always runs `cargo build`, so it also
# catches the binary being *stale* — e.g. mid-session edits to ci's own
# source in a prior session. Kept synchronous so that when it does win the
# race, the win is real (no async handoff for the MCP dial to slip past).
set -uo pipefail
if ! command -v cargo >/dev/null 2>&1; then
exit 0
fi
# Resolve any unresolved Git LFS pointer stubs (assets/potion-code-16m/* —
# the vendored embedding model — and .ci-bin/**/ci) BEFORE building. Real
# incident this guards against: a checkout without git-lfs installed leaves
# ~130-byte pointer text in place of real file content; `cargo build` still
# succeeds (it just bakes that pointer text into the binary via
# `include_bytes!`), and the failure only surfaces later, silently, as
# `embeddings_status: "failed"` at runtime — not a build error, so nothing
# here would have caught it otherwise. Every step is best-effort and
# non-fatal (`|| true`) — this hook must degrade, not break the session, and
# `Embedder::load`'s own runtime fallback (network download) plus
# `embeddings_status: "offline_unavailable"` messaging are the safety net if
# this doesn't fully resolve it (e.g. no apt, no network, git-lfs install
# blocked). See docs/cloud-environment-setup.md for the full picture.
if command -v git >/dev/null 2>&1 && grep -q 'filter=lfs' .gitattributes 2>/dev/null; then
if ! git lfs version >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then
apt-get install -y git-lfs >/dev/null 2>&1 || true
fi
if git lfs version >/dev/null 2>&1; then
git lfs pull >/dev/null 2>&1 || true
fi
fi
build_output=$(cargo build --quiet -p ci-cli 2>&1)
build_status=$?
if [ "$build_status" -ne 0 ]; then
jq -n --arg msg "ci-cli pre-build failed (exit $build_status) — the ci MCP server will likely fail to connect. Build output:
$build_output" \
'{hookSpecificOutput: {hookEventName: "SessionStart", additionalContext: $msg}}'
fi
exit 0