@biffo/cli 0.249.3 → 0.249.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -35,11 +35,22 @@ fi
|
|
|
35
35
|
root=$(git rev-parse --show-toplevel) || exit 0
|
|
36
36
|
cd "$root" || exit 0
|
|
37
37
|
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
38
|
+
# git puts the ref list (<local ref> <local sha> <remote ref> <remote sha>, one
|
|
39
|
+
# line per ref) on this process's stdin, ONCE. Two things below need it --
|
|
40
|
+
# rewrite-scope-check and the pg-test block gate -- and a pipe can only be read
|
|
41
|
+
# once, so it is captured to a file here and each consumer is fed from that
|
|
42
|
+
# file instead of the real stdin. Falling back to no capture (each reader gets
|
|
43
|
+
# whatever is left of the real stdin, i.e. nothing for the second one) rather
|
|
44
|
+
# than failing the push if a temp file cannot be created: this hook's job is to
|
|
45
|
+
# run checks, not to invent a new way to block a push that has nothing to do
|
|
46
|
+
# with any of them.
|
|
47
|
+
REFS_FILE=$(mktemp) || REFS_FILE=""
|
|
48
|
+
if [ -n "$REFS_FILE" ]; then
|
|
49
|
+
cat >"$REFS_FILE"
|
|
50
|
+
trap 'rm -f "$REFS_FILE"' EXIT HUP INT TERM
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# The rewrite-scope guard runs FIRST.
|
|
43
54
|
#
|
|
44
55
|
# Why it exists: a force-push can quietly add a file to a branch's change set
|
|
45
56
|
# and record a stale copy of somebody else's merged work as your own change.
|
|
@@ -51,7 +62,11 @@ cd "$root" || exit 0
|
|
|
51
62
|
# the file was the one where nothing checked. There is no absent case now --
|
|
52
63
|
# the bridge resolves the script from the package -- and if the bridge itself
|
|
53
64
|
# cannot run, that is a reason to stop, not to wave the push through.
|
|
54
|
-
|
|
65
|
+
if [ -n "$REFS_FILE" ]; then
|
|
66
|
+
sh scripts/biffo.sh rewrite-scope-check <"$REFS_FILE" || exit 1
|
|
67
|
+
else
|
|
68
|
+
sh scripts/biffo.sh rewrite-scope-check || exit 1
|
|
69
|
+
fi
|
|
55
70
|
|
|
56
71
|
# --- Claim guard (#1231 instance 2) -------------------------------------------
|
|
57
72
|
#
|
|
@@ -94,6 +109,42 @@ if [ -n "$branch" ]; then
|
|
|
94
109
|
# exit 1 instead, if you would rather block than guess.
|
|
95
110
|
fi
|
|
96
111
|
|
|
112
|
+
# --- pg-test block gate (#656) -------------------------------------------
|
|
113
|
+
#
|
|
114
|
+
# verify.sh already reports `pg-test` as `APPLICABLE BUT NOT RUN` when the repo
|
|
115
|
+
# has Postgres-dependent tests and no DSN reached it, and tries to provision one
|
|
116
|
+
# itself via `scripts/biffo.sh pg-test-db` before giving up. That is honest and
|
|
117
|
+
# often self-healing -- but it surfaced on a push that was ENTIRELY RLS policy
|
|
118
|
+
# DDL, where the lane still did not run and the push still went through amber.
|
|
119
|
+
# A wall of green `OK` lines does not make a person weight one amber line
|
|
120
|
+
# correctly at 5pm, and CI treats this lane as required, so a local pass that
|
|
121
|
+
# quietly skipped it is not the thing it looks like.
|
|
122
|
+
#
|
|
123
|
+
# So: if this push touches `db/imports/**` or a `*_pg.py` module -- the
|
|
124
|
+
# convention `scripts/pg-test-db.sh` and verify.sh's own module discovery both
|
|
125
|
+
# use -- and verify.sh still cannot run the lane, block rather than warn.
|
|
126
|
+
# `BIFFO_PGTEST_DIFF_RELEVANT=1` is how that intent reaches verify.sh; it makes
|
|
127
|
+
# no decision itself, `scripts/pgtest-diff-check.sh` (through the same bridge
|
|
128
|
+
# as rewrite-scope-check) does, from the same ref list captured above.
|
|
129
|
+
#
|
|
130
|
+
# Deliberately narrow: an ordinary frontend push touches none of those paths,
|
|
131
|
+
# so `pgtest-diff-check` exits 1 and nothing here changes. A repo whose
|
|
132
|
+
# integration branch cannot be resolved, or that got no ref list at all, exits
|
|
133
|
+
# 2 -- "could not tell" -- and this does NOT block on that, the same posture
|
|
134
|
+
# `rewrite-scope-check` and `claim.sh --guard` take on their own blind spots: a
|
|
135
|
+
# coordination-shaped check that fails closed on not knowing teaches people to
|
|
136
|
+
# route around it, which is the opposite of what a gate is for.
|
|
137
|
+
#
|
|
138
|
+
# `BIFFO_SKIP_PGTEST=1`, checked here rather than only inside verify.sh, is the
|
|
139
|
+
# deliberate escape hatch AGENTS.md section 7 requires for loosening a gate --
|
|
140
|
+
# in the open, not by reaching for `--no-verify` and skipping every other check
|
|
141
|
+
# too.
|
|
142
|
+
if [ -z "${BIFFO_SKIP_PGTEST:-}" ] && [ -n "$REFS_FILE" ]; then
|
|
143
|
+
if sh scripts/biffo.sh pgtest-diff-check <"$REFS_FILE"; then
|
|
144
|
+
export BIFFO_PGTEST_DIFF_RELEVANT=1
|
|
145
|
+
fi
|
|
146
|
+
fi
|
|
147
|
+
|
|
97
148
|
# Through the version-pinned CLI since #1109, so a repo cannot run a gate two
|
|
98
149
|
# versions old -- eight of them did, and tabsii-crm checked ONE thing in eight
|
|
99
150
|
# on a 700-line change and printed `verify passed` (#855). There is one copy of
|
|
@@ -35,11 +35,22 @@ fi
|
|
|
35
35
|
root=$(git rev-parse --show-toplevel) || exit 0
|
|
36
36
|
cd "$root" || exit 0
|
|
37
37
|
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
38
|
+
# git puts the ref list (<local ref> <local sha> <remote ref> <remote sha>, one
|
|
39
|
+
# line per ref) on this process's stdin, ONCE. Two things below need it --
|
|
40
|
+
# rewrite-scope-check and the pg-test block gate -- and a pipe can only be read
|
|
41
|
+
# once, so it is captured to a file here and each consumer is fed from that
|
|
42
|
+
# file instead of the real stdin. Falling back to no capture (each reader gets
|
|
43
|
+
# whatever is left of the real stdin, i.e. nothing for the second one) rather
|
|
44
|
+
# than failing the push if a temp file cannot be created: this hook's job is to
|
|
45
|
+
# run checks, not to invent a new way to block a push that has nothing to do
|
|
46
|
+
# with any of them.
|
|
47
|
+
REFS_FILE=$(mktemp) || REFS_FILE=""
|
|
48
|
+
if [ -n "$REFS_FILE" ]; then
|
|
49
|
+
cat >"$REFS_FILE"
|
|
50
|
+
trap 'rm -f "$REFS_FILE"' EXIT HUP INT TERM
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# The rewrite-scope guard runs FIRST.
|
|
43
54
|
#
|
|
44
55
|
# Why it exists: a force-push can quietly add a file to a branch's change set
|
|
45
56
|
# and record a stale copy of somebody else's merged work as your own change.
|
|
@@ -51,7 +62,11 @@ cd "$root" || exit 0
|
|
|
51
62
|
# the file was the one where nothing checked. There is no absent case now --
|
|
52
63
|
# the bridge resolves the script from the package -- and if the bridge itself
|
|
53
64
|
# cannot run, that is a reason to stop, not to wave the push through.
|
|
54
|
-
|
|
65
|
+
if [ -n "$REFS_FILE" ]; then
|
|
66
|
+
sh scripts/biffo.sh rewrite-scope-check <"$REFS_FILE" || exit 1
|
|
67
|
+
else
|
|
68
|
+
sh scripts/biffo.sh rewrite-scope-check || exit 1
|
|
69
|
+
fi
|
|
55
70
|
|
|
56
71
|
# --- Claim guard (#1231 instance 2) -------------------------------------------
|
|
57
72
|
#
|
|
@@ -94,6 +109,42 @@ if [ -n "$branch" ]; then
|
|
|
94
109
|
# exit 1 instead, if you would rather block than guess.
|
|
95
110
|
fi
|
|
96
111
|
|
|
112
|
+
# --- pg-test block gate (#656) -------------------------------------------
|
|
113
|
+
#
|
|
114
|
+
# verify.sh already reports `pg-test` as `APPLICABLE BUT NOT RUN` when the repo
|
|
115
|
+
# has Postgres-dependent tests and no DSN reached it, and tries to provision one
|
|
116
|
+
# itself via `scripts/biffo.sh pg-test-db` before giving up. That is honest and
|
|
117
|
+
# often self-healing -- but it surfaced on a push that was ENTIRELY RLS policy
|
|
118
|
+
# DDL, where the lane still did not run and the push still went through amber.
|
|
119
|
+
# A wall of green `OK` lines does not make a person weight one amber line
|
|
120
|
+
# correctly at 5pm, and CI treats this lane as required, so a local pass that
|
|
121
|
+
# quietly skipped it is not the thing it looks like.
|
|
122
|
+
#
|
|
123
|
+
# So: if this push touches `db/imports/**` or a `*_pg.py` module -- the
|
|
124
|
+
# convention `scripts/pg-test-db.sh` and verify.sh's own module discovery both
|
|
125
|
+
# use -- and verify.sh still cannot run the lane, block rather than warn.
|
|
126
|
+
# `BIFFO_PGTEST_DIFF_RELEVANT=1` is how that intent reaches verify.sh; it makes
|
|
127
|
+
# no decision itself, `scripts/pgtest-diff-check.sh` (through the same bridge
|
|
128
|
+
# as rewrite-scope-check) does, from the same ref list captured above.
|
|
129
|
+
#
|
|
130
|
+
# Deliberately narrow: an ordinary frontend push touches none of those paths,
|
|
131
|
+
# so `pgtest-diff-check` exits 1 and nothing here changes. A repo whose
|
|
132
|
+
# integration branch cannot be resolved, or that got no ref list at all, exits
|
|
133
|
+
# 2 -- "could not tell" -- and this does NOT block on that, the same posture
|
|
134
|
+
# `rewrite-scope-check` and `claim.sh --guard` take on their own blind spots: a
|
|
135
|
+
# coordination-shaped check that fails closed on not knowing teaches people to
|
|
136
|
+
# route around it, which is the opposite of what a gate is for.
|
|
137
|
+
#
|
|
138
|
+
# `BIFFO_SKIP_PGTEST=1`, checked here rather than only inside verify.sh, is the
|
|
139
|
+
# deliberate escape hatch AGENTS.md section 7 requires for loosening a gate --
|
|
140
|
+
# in the open, not by reaching for `--no-verify` and skipping every other check
|
|
141
|
+
# too.
|
|
142
|
+
if [ -z "${BIFFO_SKIP_PGTEST:-}" ] && [ -n "$REFS_FILE" ]; then
|
|
143
|
+
if sh scripts/biffo.sh pgtest-diff-check <"$REFS_FILE"; then
|
|
144
|
+
export BIFFO_PGTEST_DIFF_RELEVANT=1
|
|
145
|
+
fi
|
|
146
|
+
fi
|
|
147
|
+
|
|
97
148
|
# Through the version-pinned CLI since #1109, so a repo cannot run a gate two
|
|
98
149
|
# versions old -- eight of them did, and tabsii-crm checked ONE thing in eight
|
|
99
150
|
# on a 700-line change and printed `verify passed` (#855). There is one copy of
|
package/dist/index.js
CHANGED
|
@@ -10849,6 +10849,13 @@ var pgTestDbCommand = packagedScriptCommand({
|
|
|
10849
10849
|
description: "Provision the local Postgres test database and print its DSN"
|
|
10850
10850
|
});
|
|
10851
10851
|
|
|
10852
|
+
// src/commands/pgtest-diff-check.ts
|
|
10853
|
+
var pgtestDiffCheckCommand = packagedScriptCommand({
|
|
10854
|
+
name: "pgtest-diff-check",
|
|
10855
|
+
script: "scripts/pgtest-diff-check.sh",
|
|
10856
|
+
description: "Report whether the push touches db/imports/** or a *_pg.py module"
|
|
10857
|
+
});
|
|
10858
|
+
|
|
10852
10859
|
// src/commands/rewrite-scope-check.ts
|
|
10853
10860
|
var rewriteScopeCheckCommand = packagedScriptCommand({
|
|
10854
10861
|
name: "rewrite-scope-check",
|
|
@@ -10921,6 +10928,7 @@ program.addCommand(gateCoverageCommand);
|
|
|
10921
10928
|
program.addCommand(runnerDropForensicsCommand);
|
|
10922
10929
|
program.addCommand(hookAuditCommand);
|
|
10923
10930
|
program.addCommand(pgTestDbCommand);
|
|
10931
|
+
program.addCommand(pgtestDiffCheckCommand);
|
|
10924
10932
|
program.addCommand(rewriteScopeCheckCommand);
|
|
10925
10933
|
program.addCommand(pluginCommand);
|
|
10926
10934
|
program.addCommand(dataCommand);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@biffo/cli",
|
|
3
|
-
"version": "0.249.
|
|
3
|
+
"version": "0.249.4",
|
|
4
4
|
"description": "Biffo project scaffolding CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"scripts/hook-audit.sh",
|
|
31
31
|
"scripts/pg-test-db.sh",
|
|
32
32
|
"scripts/rewrite-scope-check.sh",
|
|
33
|
+
"scripts/pgtest-diff-check.sh",
|
|
33
34
|
"scripts/gate-coverage.sh",
|
|
34
35
|
"scripts/verify.sh",
|
|
35
36
|
"scripts/runner-drop-forensics.mjs",
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
# Does the push about to happen touch the paths that make the real-Postgres
|
|
3
|
+
# lane matter — `db/imports/**` or a `*_pg.py` module?
|
|
4
|
+
#
|
|
5
|
+
# ## Why this exists (tabsii-platform#656)
|
|
6
|
+
#
|
|
7
|
+
# `scripts/verify.sh` already reports `pg-test` as `APPLICABLE BUT NOT RUN`
|
|
8
|
+
# when the repo has Postgres-dependent tests and no DSN reached it — an honest
|
|
9
|
+
# amber line, not a silent pass. It surfaced on a change that was ENTIRELY RLS
|
|
10
|
+
# policy DDL: the gate is least useful exactly where the diff most needs it,
|
|
11
|
+
# and a human reading a wall of green `OK` lines does not weight one amber line
|
|
12
|
+
# at 5pm.
|
|
13
|
+
#
|
|
14
|
+
# `verify.sh` cannot answer "is this push worth blocking over?" by itself —
|
|
15
|
+
# that question is about the commits being PUSHED, and a plain
|
|
16
|
+
# `sh scripts/biffo.sh verify` run by hand has no ref list at all. Only
|
|
17
|
+
# `.githooks/pre-push` sees that, on stdin, in the same
|
|
18
|
+
# `<local ref> <local sha> <remote ref> <remote sha>` form `rewrite-scope-check`
|
|
19
|
+
# reads. This script answers that one question so the hook can decide whether
|
|
20
|
+
# to escalate verify.sh's amber warning into a block.
|
|
21
|
+
#
|
|
22
|
+
# ## What it deliberately does NOT do
|
|
23
|
+
#
|
|
24
|
+
# It does not run the lane, provision a database, or decide whether to block —
|
|
25
|
+
# `verify.sh` already tries to self-provision (`scripts/biffo.sh pg-test-db`),
|
|
26
|
+
# and blocking is the hook's call, made by exporting
|
|
27
|
+
# `BIFFO_PGTEST_DIFF_RELEVANT` before `exec`ing verify. This is a narrow
|
|
28
|
+
# predicate: which files changed, on the paths that matter, nothing else.
|
|
29
|
+
#
|
|
30
|
+
# ## Exit codes
|
|
31
|
+
#
|
|
32
|
+
# 0 — the push touches a relevant path.
|
|
33
|
+
# 1 — it does not (the ordinary case; most pushes are not DDL).
|
|
34
|
+
# 2 — could not tell (no integration branch resolvable, no stdin, shallow
|
|
35
|
+
# history). Reported on stderr and treated as "do not block" by the
|
|
36
|
+
# caller, the same posture `rewrite-scope-check.sh` and `claim.sh --guard`
|
|
37
|
+
# take when their own inputs are unavailable — a coordination-shaped gate
|
|
38
|
+
# that fails closed on its OWN blind spot teaches people to route around
|
|
39
|
+
# it, and this estate has that lesson recorded more than once.
|
|
40
|
+
|
|
41
|
+
set -u
|
|
42
|
+
|
|
43
|
+
ZERO=0000000000000000000000000000000000000000
|
|
44
|
+
PATTERN='(^|/)db/imports/|_pg\.py$'
|
|
45
|
+
|
|
46
|
+
note() { printf 'pgtest-diff-check: %s\n' "$1" >&2; }
|
|
47
|
+
|
|
48
|
+
integration=""
|
|
49
|
+
for candidate in dev main master; do
|
|
50
|
+
if git rev-parse --verify --quiet "refs/remotes/origin/$candidate" >/dev/null 2>&1; then
|
|
51
|
+
integration="origin/$candidate"
|
|
52
|
+
break
|
|
53
|
+
fi
|
|
54
|
+
done
|
|
55
|
+
|
|
56
|
+
# Collected through a file rather than a variable, for the same reason
|
|
57
|
+
# rewrite-scope-check.sh does: the read loop below cannot assign to a variable
|
|
58
|
+
# in the parent shell once it is fed from a pipe. One line per ref: `hit` (this
|
|
59
|
+
# ref touches a relevant path), `indeterminate` (could not compute its range),
|
|
60
|
+
# or nothing (ref checked, not relevant).
|
|
61
|
+
RESULT_FILE=$(mktemp) || {
|
|
62
|
+
note "could not create a temp file - could not tell"
|
|
63
|
+
exit 2
|
|
64
|
+
}
|
|
65
|
+
trap 'rm -f "$RESULT_FILE"' EXIT HUP INT TERM
|
|
66
|
+
|
|
67
|
+
saw_ref=0
|
|
68
|
+
while read -r _local_ref local_sha _remote_ref remote_sha; do
|
|
69
|
+
[ -z "${local_sha:-}" ] && continue
|
|
70
|
+
saw_ref=1
|
|
71
|
+
# Branch deletion: nothing is being pushed.
|
|
72
|
+
[ "$local_sha" = "$ZERO" ] && continue
|
|
73
|
+
|
|
74
|
+
range=""
|
|
75
|
+
if [ "$remote_sha" != "$ZERO" ] && git cat-file -e "$remote_sha^{commit}" 2>/dev/null; then
|
|
76
|
+
# The ordinary case: compare against what the remote tip actually holds.
|
|
77
|
+
range="$remote_sha..$local_sha"
|
|
78
|
+
elif [ -n "$integration" ]; then
|
|
79
|
+
# A brand-new branch, or a remote tip we do not have locally (shallow
|
|
80
|
+
# clone, pruned object). Fall back to "everything this branch adds since
|
|
81
|
+
# it forked from the integration branch" — the same shape a reviewer would
|
|
82
|
+
# see in the PR diff.
|
|
83
|
+
base=$(git merge-base "$local_sha" "$integration" 2>/dev/null) || base=""
|
|
84
|
+
[ -n "$base" ] && range="$base..$local_sha"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
if [ -z "$range" ]; then
|
|
88
|
+
echo indeterminate >>"$RESULT_FILE"
|
|
89
|
+
continue
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
if git diff --name-only "$range" 2>/dev/null | grep -qE "$PATTERN"; then
|
|
93
|
+
echo hit >>"$RESULT_FILE"
|
|
94
|
+
fi
|
|
95
|
+
done
|
|
96
|
+
|
|
97
|
+
if [ "$saw_ref" -eq 0 ]; then
|
|
98
|
+
note "no ref list on stdin - could not tell"
|
|
99
|
+
exit 2
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
if grep -qx hit "$RESULT_FILE" 2>/dev/null; then
|
|
103
|
+
exit 0
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
if grep -qx indeterminate "$RESULT_FILE" 2>/dev/null; then
|
|
107
|
+
note "could not resolve one or more refs' range - could not tell"
|
|
108
|
+
exit 2
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
exit 1
|
package/scripts/verify.sh
CHANGED
|
@@ -757,6 +757,39 @@ elif [ -z "$PG_TEST_DSN" ]; then
|
|
|
757
757
|
"CI runs these as a required check; nothing local is checking them."
|
|
758
758
|
printf ' \033[90m%s\033[0m\n' \
|
|
759
759
|
"set BIFFO_TEST_PG_DSN, or run scripts/pg-test-db.sh if this repo ships one"
|
|
760
|
+
|
|
761
|
+
# --- Block on a relevant diff (tabsii-platform#656) --------------------
|
|
762
|
+
#
|
|
763
|
+
# The line above is honest -- it says NOT RUN, not passing -- but that is
|
|
764
|
+
# not enough on its own: it does not block, and a wall of green `OK` lines
|
|
765
|
+
# trains a reader not to weight one amber line correctly. It surfaced on a
|
|
766
|
+
# push that was ENTIRELY RLS policy DDL, exactly the diff this lane exists
|
|
767
|
+
# to check.
|
|
768
|
+
#
|
|
769
|
+
# `BIFFO_PGTEST_DIFF_RELEVANT` is set by `.githooks/pre-push`, never by a
|
|
770
|
+
# developer -- it is the hook's answer to "does this push touch
|
|
771
|
+
# db/imports/** or a *_pg.py module?", computed from the actual ref list
|
|
772
|
+
# via `scripts/pgtest-diff-check.sh`. A plain `sh scripts/biffo.sh verify`
|
|
773
|
+
# run by hand therefore stays advisory, exactly as before: this variable is
|
|
774
|
+
# only ever present when the hook itself decided the diff warranted it.
|
|
775
|
+
#
|
|
776
|
+
# `BIFFO_SKIP_PGTEST` is checked again here, not only in the hook, so this
|
|
777
|
+
# is provable by driving verify.sh directly (see verify-pg-lane.test.ts)
|
|
778
|
+
# and so a developer who sets it before invoking verify.sh by hand gets the
|
|
779
|
+
# same escape hatch the hook advertises.
|
|
780
|
+
if [ -n "${BIFFO_PGTEST_DIFF_RELEVANT:-}" ] && [ -z "${BIFFO_SKIP_PGTEST:-}" ]; then
|
|
781
|
+
FAILED="$FAILED pg-test-required"
|
|
782
|
+
printf '\n'
|
|
783
|
+
printf ' \033[31mBLOCKED\033[0m: this push touches db/imports/** or a *_pg.py module, and\n'
|
|
784
|
+
printf ' the pg-test lane above did not run. CI treats it as a required check, so a\n'
|
|
785
|
+
printf ' push here would report green without having checked the thing most likely\n'
|
|
786
|
+
printf ' to need it.\n\n'
|
|
787
|
+
printf ' Get a DSN and re-run:\n'
|
|
788
|
+
printf ' eval "$(sh scripts/pg-test-db.sh --export)" # if this repo ships one\n'
|
|
789
|
+
printf ' export BIFFO_TEST_PG_DSN=postgresql+asyncpg://user:pass@host:port/db\n\n'
|
|
790
|
+
printf ' Deliberate escape hatch, printed rather than silent (AGENTS.md section 7):\n'
|
|
791
|
+
printf ' BIFFO_SKIP_PGTEST=1 git push ...\n\n'
|
|
792
|
+
fi
|
|
760
793
|
fi
|
|
761
794
|
elif ! command -v uv >/dev/null 2>&1; then
|
|
762
795
|
skip pg-test "uv not installed"
|