Both Claude reviewers caught this independently, and they are right. The test
job I added wrote a PUSH-CAPABLE REGISTRY_PASSWORD into a plaintext
~/.gitconfig and then ran `go build`/`go vet`/`go test` — repository code — on
pull_request events. This repo is public, so a fork PR could ship a test whose
only job is to print that file. The image build had already answered this
question correctly: its credentials are BuildKit secrets scoped to the
module-download RUN and are never present while code executes. I bolted on a
job that skipped the boundary its neighbour maintains.
Dependencies are now fetched in their own step which deletes ~/.gitconfig
before anything else runs, and asserts the scrub — against the whole home
directory, not against the file it just removed, because the credential can
also land in ~/.netrc or ~/.config/go/env. Verified the assertion is not
vacuous: planting the secret in ~/.netrc trips it. Later steps run with
GOPROXY=off, so any attempt to reach the network fails loudly rather than
quietly hunting for the credential that is now gone.
Also from round 4: TestEndpointProviderNamesAreAllAccepted pinned only
endpointProvider, while the constant is the error text for BOTH resolution
paths — it now asserts each advertised name resolves either way (break-checked
by dropping the gemini alias from resolveModel alone). preflight.sh documents
that ollama-cloud is checked on OLLAMA_API_KEY but hinted as
OLLAMA_CLOUD_API_KEY because run.sh copies one to the other first, an ordering
dependency that was invisible from the file.
And the comments that narrated this PR's own edit history ("the first version
of this change...") are rewritten as invariants. That history stops being true
the moment this merges, and the repo's doc policy says as much.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
87 lines
3.8 KiB
Bash
87 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Table test for the credential pre-flight in preflight.sh.
|
|
#
|
|
# It SOURCES the real implementation rather than copying it, so there is no
|
|
# second definition that can pass while production fails.
|
|
#
|
|
# Run: scripts/preflight_test.sh (exit 0 = all cases pass)
|
|
set -u
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
# shellcheck source=preflight.sh
|
|
. "$SCRIPT_DIR/preflight.sh"
|
|
|
|
fail=0
|
|
check() { # description, want, got
|
|
if [ "$2" = "$3" ]; then
|
|
echo "ok $1"
|
|
else
|
|
echo "FAIL $1 — want '$2', got '$3'"
|
|
fail=1
|
|
fi
|
|
}
|
|
|
|
# probe <provider> [VAR=VAL ...] — run the real function in a clean environment
|
|
# under the same shell options production uses (set -u), so an unset-variable
|
|
# bug surfaces here instead of in a live review.
|
|
probe() {
|
|
local provider="$1"; shift
|
|
env -i PATH="$PATH" HOME="$HOME" "$@" bash -c "
|
|
set -u
|
|
. '$SCRIPT_DIR/preflight.sh'
|
|
gadfly_preflight_key '$provider'
|
|
"
|
|
}
|
|
|
|
echo "== registry path: keyed providers with no key must name their variable =="
|
|
check "qwen, no key" "QWEN_API_KEY" "$(probe qwen)"
|
|
check "kimi, no key" "KIMI_API_KEY" "$(probe kimi)"
|
|
check "ollama-cloud, no key" "OLLAMA_CLOUD_API_KEY" "$(probe ollama-cloud)"
|
|
check "openai, no key" "OPENAI_API_KEY" "$(probe openai)"
|
|
check "openai-compatible, none" "OPENAI_API_KEY" "$(probe openai-compatible)"
|
|
check "anthropic, no key" "ANTHROPIC_API_KEY" "$(probe anthropic)"
|
|
|
|
echo "== registry path: the provider's own key lets it run =="
|
|
check "qwen, keyed" "" "$(probe qwen QWEN_API_KEY=k)"
|
|
check "kimi, keyed" "" "$(probe kimi KIMI_API_KEY=k)"
|
|
check "ollama-cloud, keyed" "" "$(probe ollama-cloud OLLAMA_API_KEY=k)"
|
|
check "openai-compatible, keyed" "" "$(probe openai-compatible OPENAI_API_KEY=k)"
|
|
|
|
echo "== a wrong-provider key never satisfies a provider (no cross-fallback) =="
|
|
check "qwen w/ only OPENAI key" "QWEN_API_KEY" "$(probe qwen OPENAI_API_KEY=k)"
|
|
check "kimi w/ only QWEN key" "KIMI_API_KEY" "$(probe kimi QWEN_API_KEY=k)"
|
|
|
|
echo "== an empty-string key counts as missing, not present =="
|
|
check "qwen, empty key" "QWEN_API_KEY" "$(probe qwen QWEN_API_KEY=)"
|
|
|
|
echo "== GADFLY_API_KEY does NOT substitute on the registry path =="
|
|
# resolveModel reads GADFLY_API_KEY only after its `baseURL == ""` early
|
|
# return, so on this path the built-in reads its own variable and a set
|
|
# GADFLY_API_KEY changes nothing. Treating it as sufficient was a false pass.
|
|
check "qwen w/ GADFLY_API_KEY only" "QWEN_API_KEY" "$(probe qwen GADFLY_API_KEY=k)"
|
|
|
|
echo "== override path (GADFLY_BASE_URL set) is deliberately not pre-flighted =="
|
|
# The credential there is GADFLY_API_KEY with a client-specific fallback, and
|
|
# the built-ins' own variables are never read. Checking one path's rules
|
|
# against the other produced a false pass in BOTH directions, so this path is
|
|
# left alone rather than guessed at.
|
|
check "qwen + BASE_URL, no keys" "" "$(probe qwen GADFLY_BASE_URL=https://x)"
|
|
check "qwen + BASE_URL + own key" "" "$(probe qwen GADFLY_BASE_URL=https://x QWEN_API_KEY=k)"
|
|
check "qwen + BASE_URL + GADFLY key" "" "$(probe qwen GADFLY_BASE_URL=https://x GADFLY_API_KEY=k)"
|
|
check "openai + BASE_URL, no keys" "" "$(probe openai GADFLY_BASE_URL=https://x)"
|
|
|
|
echo "== providers needing no key are never blocked, with nothing set =="
|
|
for p in ollama llama-swap llama-swaps llamaswap llamaswaps foreman google gemini some-dsn-name; do
|
|
check "unkeyed $p" "" "$(probe "$p")"
|
|
done
|
|
|
|
# google is absent from the table on purpose: it accepts GOOGLE_API_KEY *or*
|
|
# GEMINI_API_KEY, so a one-name arm would skip a correctly-configured run.
|
|
check "google w/ only GEMINI_API_KEY" "" "$(probe google GEMINI_API_KEY=k)"
|
|
|
|
if [ "$fail" -ne 0 ]; then
|
|
echo "RESULT: preflight table FAILED"
|
|
exit 1
|
|
fi
|
|
echo "RESULT: all pre-flight cases pass"
|