ci/woodpecker/pr/pr-review Pipeline was successful
Addresses the a7890e0a review.
- pr-review.yml: strip REVIEW_TOKEN from the valid-model.sh call too (it runs a
script from $HOMELAB, branch-supplied for a homelab PR), and guard it with
`|| true` so a missing script can't kill the step -- restoring the stated "a
run never dies on selection" invariant. For a complex/security-sensitive
review, ignore the (injectable) triage pick and run on the CLI default
(strongest configured) model.
- valid-model.sh: reject a leading dash at the shape check (making the header
accurate) so an option-like value is refused even without a catalog.
- fetch-models.sh: --retry 2 --retry-connrefused so a transient blip doesn't
drop the run to the default; add a FETCH_MODELS_BODY_FILE test seam.
- pick-model.sh: pass --settings (new ci/agents/model-picker/settings.json,
Read deny-list) as belt-and-suspenders behind --allowedTools "".
- test-model-selection.sh: add fetch-models.sh mapping tests (well-formed body
-> non-null capability columns; degraded body -> loud warning) via the seam,
and wire the whole suite into .woodpecker/e2e.yml so it runs in CI.
- Condense the duplicated model-selection comment in the four fixed jobs to a
one-line pointer to pick-model.sh.
- PR description: state the cost / no-fixed-ceiling property change.
Deferred with rationale (in the PR thread): selected-model in the four crons'
posted artifacts (already logged per run), pagination past limit=1000 (API max;
has_more warns), and unit-testing pick-model.sh's JSON extraction (its output
always passes through the tested valid-model.sh gate, and the picker prompt is
developer-controlled, not attacker input).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
37 lines
1.6 KiB
Bash
Executable File
37 lines
1.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# Validate an UNTRUSTED model id against the live catalog.
|
|
#
|
|
# This is the one gate that stands between an agent-written model string and an
|
|
# unquoted `--model $MODEL` expansion in the pipelines, so it lives in a single
|
|
# tested place (see scripts/ci/test-model-selection.sh) rather than inline in a
|
|
# Woodpecker `commands:` block. Written in POSIX sh (run as `sh`), matching the
|
|
# other scripts/ci/ helpers added alongside it.
|
|
#
|
|
# Echoes the id on stdout IFF it is BOTH:
|
|
# 1. a single safe token — only [A-Za-z0-9._-] AND not starting with a dash, so
|
|
# a value carrying a newline or a space, or one that looks like an option
|
|
# (e.g. "--dangerously-skip-permissions", or
|
|
# "claude-x\n--dangerously-skip-permissions"), can never pass and then
|
|
# word-split into an injected CLI flag; and
|
|
# 2. present in column 1 of the catalog read on stdin (fetch-models.sh --table
|
|
# output, or a bare id-per-line list).
|
|
# Otherwise echoes nothing. Always exits 0 so callers can use $(...) under set -e.
|
|
# The two checks are independent: step 1 alone makes the value safe to pass to a
|
|
# command line even if a caller supplies no catalog.
|
|
#
|
|
# Usage: printf '%s\n' "$TABLE" | valid-model.sh "$candidate"
|
|
set -eu
|
|
|
|
CAND="${1:-}"
|
|
|
|
# 1. shape check — reject empty, a leading dash (option-like), or any char
|
|
# outside the safe set. A real model id never starts with '-'.
|
|
case "$CAND" in ""|-*|*[!A-Za-z0-9._-]*) exit 0 ;; esac
|
|
|
|
# 2. membership check — must be a currently-available id (catalog on stdin).
|
|
CATALOG="$(cat)"
|
|
[ -n "$CATALOG" ] || exit 0
|
|
printf '%s\n' "$CATALOG" | cut -f1 | grep -qxF -- "$CAND" || exit 0
|
|
|
|
printf '%s\n' "$CAND"
|