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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/bin/sh
# install-main — local CICD: make the installed `yog` equal to main's tip.
#
# Compiles `main`, installs the `yog` binary into $PATH and `make reload`s a
# running window, so a landed merge takes effect without a manual restart (a
# no-op if yog wasn't running). This is the LOCAL half of delivery;
# `scripts/bl-push-main` (a balls `close.post` plugin) is the remote half.
#
# It is a CONVERGENCE, not an event handler: it asks "is main's tip what is
# installed?" and acts only if the answer is no. That is what lets its trigger
# be the FACT rather than a verb — `.githooks/reference-transaction` runs it
# whenever `refs/heads/main` moves, by any route (bl-6ff1). It was previously
# registered as a balls `close.post` plugin, which fired on `bl close` alone
# and so missed a pull, a received push and a hand repair; that registration is
# retired, and this script is no longer a plugin (no protocol handshake — a
# second path to one outcome is exactly the double build we removed).
# Running it by hand at any time is safe and cheap.
#
# Why an ephemeral worktree, not the repo root: a delivery moves main by
# plumbing and never refreshes the root working tree, so after a landing the
# root is stale and may hold uncommitted work. The `main` REF is the single
# source of truth for "what landed", so we build a throwaway
# `git worktree --detach main` and tear it down. It shares the repo's target/
# (CARGO_TARGET_DIR) so the release build stays incremental.
#
# Contract:
# * ALWAYS exits 0 on dispatch. Its caller is a git hook, and a hook that
# fails aborts the very ref update it was told about; a build or install
# failure lands in the log only.
# * IDEMPOTENT and cheap when nothing changed: main's tip is compared against
# the commit `make install` stamps beside the binary (`make
# print-install-stamp` names the file) BEFORE anything is built, so a ref
# write that installs nothing new costs one `rev-parse` and a string
# compare, never a release build.
# * DETACHES the build (setsid) so whatever moved main returns at once; the
# outcome lands in <repo>/target/cicd-install.log.
# * SCRUBS the ambient git environment first. git exports GIT_DIR and
# GIT_WORK_TREE into a hook run from a linked worktree, and they OUTRANK
# `-C <repo>`, so an unscrubbed `git worktree add` here would aim at that
# worktree instead of the repo. The list is src/git_env.rs's `INHERITED`,
# the crate's one vocabulary for this hazard.
# * acts on THIS project's repo, resolved from the script's own on-disk home
# (<repo>/scripts/install-main -> <repo>), right regardless of cwd.
self=""
# Internal worker mode: build main's tip and install. Detached by dispatch;
# runs synchronously when invoked directly (`install-main __build <repo>`),
# which is how it is tested.
if [; then
root=""
wt="" ||
status=1
if ; then
if CARGO_TARGET_DIR="/target" ; then
status=0
fi
else
fi
fi
root="" ||
# The idempotence gate. `make print-install-stamp` is the ONE definition of
# where "the commit the installed binary was built from" is recorded — the
# Makefile owns both the install and the stamp, so there is no second copy of
# the path here.
want="" ||
stamp=""
if [ && [; then
fi
||
log="/target/cicd-install.log"
# setsid reparents the build into a new session so it survives its caller; nohup
# is the fallback where setsid is absent.
if ; then
&
else
&
fi