ci/woodpecker/pr/ci Pipeline was successful
On a fleet host, load_credentials gitea-mosaicstack / gitea-usc now resolve a git identity's SEAT SLOT (MOSAIC_GIT_IDENTITY with a directory under MOSAIC_BRAIN_HOME/fleet/agents/) as the token source, mirroring get_gitea_token in detect-platform.sh (the #1311 lineage). URL still comes from credentials.json (provider config, not identity). A seat with an empty or missing slot REFUSES (rc 1, identity and slot path named) rather than falling back to the shared service store — the same no-fallback rule the git credential helper and detect-platform enforce; a silent fallback would act as the wrong identity (#1343 family, usc/uconnect#3084 precedent). No identity resolved, or a non-seat identity: the service store, unchanged. Other services untouched (no seat concept to invent). Hermetic suite test-credentials-gitea-seats.sh (sandbox brain + sandbox credentials.json; no real credential read), CI-reachable via test:framework-shell. Six pins: slot-sourced token, seat-miss refusal without fallback (token compared against the service value), no-identity service path, non-seat identity, woodpecker indifference to the identity, pre-set GITEA_TOKEN never overridden. Mutants killed: seat-miss-falls-back (dies at G2), seat-reads-service-store (dies at G1). Known pre-existing (out of scope, unchanged by this PR): this host's credentials.json stores gitea tokens under .gitea.<inst>.default and per-identity keys, while the loader reads .gitea.<inst>.token — the no-identity service path fails identically before and after this change (verified against origin/next's loader). Filed for the wrapper-defect batch rather than widened here.
89 lines
4.3 KiB
Bash
Executable File
89 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Hermetic regression for load_credentials gitea seat-slot resolution.
|
|
# Sandbox brain home + sandbox credentials.json; no real credential is read.
|
|
#
|
|
# Pins:
|
|
# G1 MOSAIC_GIT_IDENTITY naming a seat with a populated slot → GITEA_TOKEN
|
|
# comes from the SLOT, URL from credentials.json.
|
|
# G2 seat with an EMPTY slot → rc 1, refusal names the identity and the
|
|
# slot path, and NO fallback to the service store occurred (the token
|
|
# must not equal the service-store value).
|
|
# G3 no identity → service store, unchanged behavior (token from
|
|
# credentials.json).
|
|
# G4 identity that is NOT a seat (no directory) → service store (same as
|
|
# G3; the identity is irrelevant on a non-fleet path).
|
|
# G5 other services are untouched: woodpecker resolution works the same
|
|
# with and without MOSAIC_GIT_IDENTITY set.
|
|
# G6 pre-existing GITEA_TOKEN env is never overridden by the seat path.
|
|
set -uo pipefail
|
|
|
|
W="${TMPDIR:-/tmp}/creds-seat-test-$$"
|
|
BRAIN="$W/brain"; CREDS="$W/credentials.json"
|
|
mkdir -p "$BRAIN/fleet/agents/live-seat/secrets" "$BRAIN/fleet/agents/empty-seat"
|
|
printf 'seat-token-value-abc123\n' > "$BRAIN/fleet/agents/live-seat/secrets/gitea-mosaicstack-live-seat.token"
|
|
cat > "$CREDS" <<'EOF'
|
|
{"gitea":{"mosaicstack":{"url":"https://gitea.example.test","token":"service-token-value-xyz789"}},
|
|
"woodpecker":{"default":"mosaic","mosaic":{"url":"https://ci.example.test","token":"wp-token-1"}}}
|
|
EOF
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
# shellcheck source=/dev/null
|
|
source "$SCRIPT_DIR/credentials.sh"
|
|
|
|
fail() { echo "FAIL: $*" >&2; exit 1; }
|
|
|
|
load_env() { # $1=service, $2=env-setup; clean subshell; echoes rc then token
|
|
local svc="$1" setup="$2"
|
|
(
|
|
eval "$setup"
|
|
unset GITEA_TOKEN GITEA_URL
|
|
export MOSAIC_CREDENTIALS_FILE="$CREDS" MOSAIC_BRAIN_HOME="$BRAIN"
|
|
load_credentials "$svc" >/dev/null 2>"$W/err"
|
|
rc=$?
|
|
printf '%s\n%s\n' "$rc" "${GITEA_TOKEN:-}"
|
|
)
|
|
}
|
|
|
|
# G1: seat with populated slot
|
|
out=$(load_env gitea-mosaicstack 'export MOSAIC_GIT_IDENTITY=live-seat')
|
|
rc=$(printf '%s' "$out" | sed -n 1p); tok=$(printf '%s' "$out" | sed -n 2p)
|
|
[ "$rc" = 0 ] || fail "G1: rc=$rc err=$(cat "$W/err")"
|
|
[ "$tok" = "seat-token-value-abc123" ] || fail "G1: token not from slot: ${tok:0:20}"
|
|
|
|
# G2: seat with empty slot refuses, no fallback
|
|
out=$(load_env gitea-mosaicstack 'export MOSAIC_GIT_IDENTITY=empty-seat')
|
|
rc=$(printf '%s' "$out" | sed -n 1p); tok=$(printf '%s' "$out" | sed -n 2p)
|
|
[ "$rc" = 1 ] || fail "G2: expected rc=1 refusal, got rc=$rc tok=${tok:0:20}"
|
|
[ "$tok" != "service-token-value-xyz789" ] || fail "G2: FELL BACK to service store on seat-miss"
|
|
grep -q "empty-seat" "$W/err" || fail "G2: refusal does not name the identity"
|
|
grep -q "fleet/agents/empty-seat" "$W/err" || fail "G2: refusal does not name the slot path"
|
|
|
|
# G3: no identity → service store
|
|
out=$(load_env gitea-mosaicstack 'unset MOSAIC_GIT_IDENTITY')
|
|
rc=$(printf '%s' "$out" | sed -n 1p); tok=$(printf '%s' "$out" | sed -n 2p)
|
|
[ "$rc" = 0 ] || fail "G3: rc=$rc err=$(cat "$W/err")"
|
|
[ "$tok" = "service-token-value-xyz789" ] || fail "G3: service-store token not loaded"
|
|
|
|
# G4: identity that is not a seat → service store
|
|
out=$(load_env gitea-mosaicstack 'export MOSAIC_GIT_IDENTITY=nobody')
|
|
rc=$(printf '%s' "$out" | sed -n 1p); tok=$(printf '%s' "$out" | sed -n 2p)
|
|
[ "$rc" = 0 ] || fail "G4: rc=$rc err=$(cat "$W/err")"
|
|
[ "$tok" = "service-token-value-xyz789" ] || fail "G4: non-seat identity broke the service path"
|
|
|
|
# G5: woodpecker ignores MOSAIC_GIT_IDENTITY entirely
|
|
( export MOSAIC_CREDENTIALS_FILE="$CREDS"
|
|
export MOSAIC_GIT_IDENTITY=live-seat
|
|
unset WOODPECKER_URL WOODPECKER_TOKEN
|
|
load_credentials woodpecker >/dev/null 2>&1 || fail "G5: woodpecker load failed with identity set"
|
|
[ "$WOODPECKER_TOKEN" = "wp-token-1" ] || fail "G5: woodpecker token wrong"
|
|
[ "$WOODPECKER_URL" = "https://ci.example.test" ] || fail "G5: woodpecker url wrong" )
|
|
|
|
# G6: pre-set GITEA_TOKEN env is preserved (both arms)
|
|
( export MOSAIC_CREDENTIALS_FILE="$CREDS" MOSAIC_BRAIN_HOME="$BRAIN"
|
|
export MOSAIC_GIT_IDENTITY=live-seat GITEA_TOKEN=already-set-env
|
|
load_credentials gitea-mosaicstack >/dev/null 2>&1 || fail "G6: load failed"
|
|
[ "$GITEA_TOKEN" = "already-set-env" ] || fail "G6: seat path overrode existing GITEA_TOKEN" )
|
|
|
|
rm -rf "$W"
|
|
echo "credentials seat-slot regression passed"
|