test(19.7-09): gate workspace check and unreleased-pin policy, TestSessionReaper and TestAuthTime
- check-phase19.7.sh: workspace_check (framework to this checkout, the OAuth server plugin's user plugin to USER_PLUGIN) in the plugins, consumers and docker stages; consumer_with_user_plugin builds fonoteka.go and sm-bm-app against USER_PLUGIN through a scratch go.work; demo_pins accepts unreleased commits its canonical checkout holds and refuses any drift with PHASE197_RELEASED=1; self-test cases for each, one PASS line each - TestSessionReaper pins A-CR-01, A-IN-01 and A-IN-06 (memory and Redis stores, store errors, the GET stream re-check, the ephemeral label) - TestAuthTime pins auth_time at mint and through every refresh path - GO_TESTS and GO_TAGGED_TESTS require them with the plan 06/07 smokes
This commit is contained in:
@@ -15,14 +15,17 @@
|
||||
# the Docker-free framework tests by required name (GO_TESTS,
|
||||
# and GO_TAGGED_TESTS with -tags summercms_mcp).
|
||||
# plugins in the user plugin (GOWORK=off), the OAuth server plugin and
|
||||
# the blog plugin: go vet, go test -short, the Docker-free tests
|
||||
# the blog plugin: the workspace check, go vet, go test -short,
|
||||
# the Docker-free tests
|
||||
# by required name and the additive check (no exported func,
|
||||
# method or type removed from a non-test .go file since the
|
||||
# plugin's last commit before the phase).
|
||||
# consumers the applications at their bumped pins (D-31): go build ./...
|
||||
# and go test -short ./... in each, the demo also with -tags
|
||||
# summercms_mcp, its pin check and its deploy check (the nginx
|
||||
# locations of the MCP endpoint).
|
||||
# consumers the applications at their bumped pins (D-31): the workspace
|
||||
# check, go build ./... and go test -short ./... in each, the
|
||||
# demo also with -tags summercms_mcp, its pin check and its
|
||||
# deploy check (the nginx locations of the MCP endpoint); the
|
||||
# applications that use the user plugin are also built against
|
||||
# USER_PLUGIN through a scratch copy of their go.work.
|
||||
# docker Docker host only: the Postgres suites by required name in the
|
||||
# framework (cabana), the three plugins and the demo (tagged).
|
||||
# admin npm --prefix admin run typecheck, the vitest run (the phase's
|
||||
@@ -48,11 +51,24 @@
|
||||
# docker when a Docker daemon answers (NOT RUN docker otherwise, a failure
|
||||
# with PHASE197_REQUIRE_DOCKER=1).
|
||||
#
|
||||
# The workspace check: before a repository's commands run, it must resolve
|
||||
# the framework to this checkout (go list -m, through its go.work or its
|
||||
# go.mod replace), and the OAuth server plugin must resolve the user plugin
|
||||
# to USER_PLUGIN. A mismatch is a refuse: line naming both paths.
|
||||
#
|
||||
# The demo's pin check: a plugin submodule ahead of its pin by test-only
|
||||
# commits is reported; one ahead by other commits is accepted only when its
|
||||
# HEAD descends from the pin and is the HEAD of, or an ancestor of, the
|
||||
# canonical checkout (USER_PLUGIN, OAUTHSERVER_PLUGIN or JOURNAL_PLUGIN),
|
||||
# and is reported as unreleased commits; anything else fails.
|
||||
#
|
||||
# Environment overrides (default: the sibling checkouts next to this
|
||||
# repository): PHASE197_ROOT (this repository), USER_PLUGIN,
|
||||
# OAUTHSERVER_PLUGIN, JOURNAL_PLUGIN, DEMO_APP, FONOTEKA, BM_APP, the
|
||||
# additive bases PHASE197_USER_BASE, PHASE197_OAS_BASE,
|
||||
# PHASE197_JOURNAL_BASE, and PHASE197_REQUIRE_DOCKER.
|
||||
# PHASE197_JOURNAL_BASE, PHASE197_REQUIRE_DOCKER, and PHASE197_RELEASED
|
||||
# (1 after the plugin tags and the application bumps: the demo's pin check
|
||||
# then refuses any drift, test-only or unreleased).
|
||||
set -euo pipefail
|
||||
|
||||
unset FORCE_COLOR
|
||||
@@ -102,6 +118,9 @@ GO_TESTS=(
|
||||
./modules/wristband:TestMCPScopes
|
||||
./modules/cabana:TestAccountContributions ./modules/cabana:TestRecordActionPrompt
|
||||
./modules/cabana:TestScopeLimitForMethods
|
||||
# Gap closure, plans 06 and 07: the smokes and the named tests of plan 09.
|
||||
./modules/pier:TestPierReaperSmoke ./modules/bouncer:TestAuthTimeSmoke
|
||||
./modules/pier:TestSessionReaper ./modules/bouncer:TestAuthTime
|
||||
)
|
||||
|
||||
# go stage: framework tests that also run in a binary built with the MCP
|
||||
@@ -111,6 +130,7 @@ GO_TAGGED_TESTS=(
|
||||
./modules/pier:TestGuardRules ./modules/pier:TestSessions ./modules/pier:TestFanOut
|
||||
./modules/pier:TestPierTracerSmoke ./modules/pier:TestPierStatelessSmoke ./modules/pier:TestEndpointGuards
|
||||
./modules/surf:TestPierMount ./modules/surf:TestStreamingRoute ./modules/surf:TestDispatchSmoke
|
||||
./modules/pier:TestSessionReaper
|
||||
)
|
||||
|
||||
# docker stage: Postgres tests in the framework.
|
||||
@@ -159,6 +179,8 @@ PHASE_TEST_FILES=(
|
||||
modules/surf/pier_mount_test.go modules/surf/pier_mount_smoke_test.go modules/surf/dispatch_smoke_test.go
|
||||
modules/wristband/mcp_scopes_test.go modules/wristband/mcp_scopes_smoke_test.go
|
||||
admin/tests/account/AccountContributions.test.ts admin/tests/form/RecordActionsPrompt.test.ts
|
||||
modules/pier/reaper_test.go modules/pier/reaper_smoke_test.go
|
||||
modules/bouncer/auth_time_test.go modules/bouncer/auth_time_smoke_test.go
|
||||
)
|
||||
STACK_NAMES=("github.com/modelcontextprotocol/go-sdk" "github.com/google/jsonschema-go")
|
||||
|
||||
@@ -357,6 +379,112 @@ require_dir() {
|
||||
}
|
||||
}
|
||||
|
||||
# workspace_resolve DIR MODULE prints the directory MODULE resolves to in
|
||||
# DIR (its replacement's directory, else its own); GO_ENV is prepended to
|
||||
# the go command's environment, for GOWORK=off.
|
||||
workspace_resolve() {
|
||||
# shellcheck disable=SC2086
|
||||
(cd "$1" && env ${GO_ENV:-} go list -m -f '{{if .Replace}}{{.Replace.Dir}}{{else}}{{.Dir}}{{end}}' "$2" 2>/dev/null) || true
|
||||
}
|
||||
|
||||
# workspace_verdict LABEL MODULE GOT WANT compares a resolved directory with
|
||||
# the expected one (both through realpath) and refuses a mismatch, naming
|
||||
# both paths.
|
||||
workspace_verdict() {
|
||||
local label="$1" module="$2" got="$3" want="$4" rgot rwant
|
||||
rgot="$(realpath -e -- "$got" 2>/dev/null || true)"
|
||||
rwant="$(realpath -e -- "$want" 2>/dev/null || true)"
|
||||
if [[ -z "$got" || -z "$rgot" || -z "$rwant" || "$rgot" != "$rwant" ]]; then
|
||||
echo "refuse: $label resolves $module to ${got:-<nothing>}, not $want" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "workspace: $label resolves $module to $rwant"
|
||||
}
|
||||
|
||||
# workspace_check DIR [EXPECT_USER_PLUGIN] refuses a repository that does
|
||||
# not resolve the framework to ROOT and, with a second argument, the user
|
||||
# plugin to it (P-40: no trust in local go.work files).
|
||||
workspace_check() {
|
||||
local dir="$1" user="${2:-}"
|
||||
workspace_verdict "$dir" git.golem15.com/golem15/summercms "$(workspace_resolve "$dir" git.golem15.com/golem15/summercms)" "$ROOT"
|
||||
if [[ -n "$user" ]]; then
|
||||
workspace_verdict "$dir" git.golem15.com/golem15/sm-user-plugin "$(workspace_resolve "$dir" git.golem15.com/golem15/sm-user-plugin)" "$user"
|
||||
fi
|
||||
}
|
||||
|
||||
# gowork_with_user_plugin APP USER FRAMEWORK prints APP's go.work rewritten
|
||||
# for a scratch workspace: every use and replace path absolute, APP's own
|
||||
# plugins/golem15/user swapped for USER, and the framework replaced by
|
||||
# FRAMEWORK (any framework replace of the original is dropped).
|
||||
gowork_with_user_plugin() {
|
||||
python3 - "$1" "$2" "$3" <<'PY'
|
||||
import os, re, sys
|
||||
app, user, root = (os.path.realpath(a) for a in sys.argv[1:4])
|
||||
own_user = os.path.realpath(os.path.join(app, "plugins", "golem15", "user"))
|
||||
framework = "git.golem15.com/golem15/summercms"
|
||||
|
||||
def absolute(path):
|
||||
full = path if path.startswith("/") else os.path.normpath(os.path.join(app, path))
|
||||
return user if os.path.realpath(full) == own_user else full
|
||||
|
||||
def replace(spec):
|
||||
left, right = (part.strip() for part in spec.split("=>", 1))
|
||||
if left.split()[0] == framework:
|
||||
return None
|
||||
target = right.split()
|
||||
if len(target) == 1 and target[0].startswith((".", "/")):
|
||||
right = absolute(target[0])
|
||||
return f"{left} => {right}"
|
||||
|
||||
out, block = [], None
|
||||
for line in open(os.path.join(app, "go.work"), encoding="utf-8").read().splitlines():
|
||||
code = line.split("//", 1)[0].strip()
|
||||
if block is not None:
|
||||
if code == ")":
|
||||
block = None
|
||||
out.append(")")
|
||||
elif code and block == "use":
|
||||
out.append("\t" + absolute(code))
|
||||
elif code:
|
||||
rewritten = replace(code)
|
||||
if rewritten is not None:
|
||||
out.append("\t" + rewritten)
|
||||
continue
|
||||
if code in ("use (", "replace ("):
|
||||
block = code.split()[0]
|
||||
out.append(code)
|
||||
continue
|
||||
m = re.fullmatch(r"use\s+(\S+)", code)
|
||||
if m:
|
||||
out.append("use " + absolute(m.group(1)))
|
||||
continue
|
||||
m = re.fullmatch(r"replace\s+(.+)", code)
|
||||
if m:
|
||||
rewritten = replace(m.group(1))
|
||||
if rewritten is not None:
|
||||
out.append("replace " + rewritten)
|
||||
continue
|
||||
out.append(line)
|
||||
out += ["", f"replace {framework} => {root}"]
|
||||
print("\n".join(out))
|
||||
PY
|
||||
}
|
||||
|
||||
# consumer_with_user_plugin APP builds APP against USER_PLUGIN through a
|
||||
# scratch copy of its go.work (APP's own go.work is never edited), after
|
||||
# checking that the scratch workspace resolves the user plugin there.
|
||||
consumer_with_user_plugin() {
|
||||
local app="$1"
|
||||
(
|
||||
work="$(mktemp -d)"
|
||||
trap 'rm -rf "$work"' EXIT
|
||||
gowork_with_user_plugin "$app" "$USER_PLUGIN" "$ROOT" >"$work/go.work"
|
||||
GO_ENV="GOWORK=$work/go.work" workspace_check "$app" "$USER_PLUGIN" >/dev/null
|
||||
(cd "$app" && GOWORK="$work/go.work" go build ./...)
|
||||
)
|
||||
echo "build: $app against $USER_PLUGIN (scratch go.work)"
|
||||
}
|
||||
|
||||
expect_detector() {
|
||||
local detector="$1" name="$2" want="$3" payload="$4" log dc=0
|
||||
log="$(mktemp)"
|
||||
@@ -367,6 +495,7 @@ expect_detector() {
|
||||
echo "refuse: self-test $detector $name: exit $dc, want $want" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "PASS self-test $detector $name"
|
||||
}
|
||||
|
||||
# expect_mode NAME WANT_EXIT WANT_TEXT MODE ENV... runs this script in MODE
|
||||
@@ -381,6 +510,7 @@ expect_mode() {
|
||||
echo "refuse: self-test $name: exit $rc (want $want), output must carry \"$text\"" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "PASS self-test $name"
|
||||
}
|
||||
|
||||
# marker_callers DIR prints every non-test .go file under DIR/modules,
|
||||
@@ -457,6 +587,7 @@ run_self_test() {
|
||||
echo "refuse: self-test marker_callers missed a caller outside pier" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "PASS self-test marker_callers"
|
||||
|
||||
# The docker NOT RUN rule: a docker that does not answer.
|
||||
mkdir -p "$tmp/bin"
|
||||
@@ -485,6 +616,7 @@ run_self_test() {
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
echo "PASS self-test removed_exports"
|
||||
|
||||
# additive_check end to end on a planted repository: an added export
|
||||
# passes, a removed one fails, an unknown base fails.
|
||||
@@ -513,6 +645,101 @@ run_self_test() {
|
||||
return 1
|
||||
fi
|
||||
rm -rf "$repo"
|
||||
echo "PASS self-test additive_check"
|
||||
|
||||
# The workspace check on planted go list answers: this checkout (also
|
||||
# through a symlink) passes, another checkout or no answer is refused
|
||||
# with both paths named.
|
||||
local ws out
|
||||
ws="$(mktemp -d)"
|
||||
mkdir -p "$ws/framework" "$ws/other"
|
||||
ln -s "$ws/framework" "$ws/link"
|
||||
if ! workspace_verdict planted git.golem15.com/golem15/summercms "$ws/link" "$ws/framework" >/dev/null 2>&1; then
|
||||
rm -rf "$ws"
|
||||
echo "refuse: self-test workspace_verdict refused a matching answer" >&2
|
||||
return 1
|
||||
fi
|
||||
out="$(workspace_verdict planted git.golem15.com/golem15/summercms "$ws/other" "$ws/framework" 2>&1)" && {
|
||||
rm -rf "$ws"
|
||||
echo "refuse: self-test workspace_verdict accepted another checkout" >&2
|
||||
return 1
|
||||
}
|
||||
if ! grep -qF "refuse: planted resolves git.golem15.com/golem15/summercms to $ws/other, not $ws/framework" <<<"$out"; then
|
||||
rm -rf "$ws"
|
||||
echo "refuse: self-test workspace_verdict did not name both paths: $out" >&2
|
||||
return 1
|
||||
fi
|
||||
if workspace_verdict planted git.golem15.com/golem15/summercms "" "$ws/framework" >/dev/null 2>&1; then
|
||||
rm -rf "$ws"
|
||||
echo "refuse: self-test workspace_verdict accepted an empty answer" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "PASS self-test workspace_verdict (match, symlinked match, mismatch naming both paths, empty answer)"
|
||||
|
||||
# The scratch go.work of consumer_with_user_plugin on a planted
|
||||
# application: absolute use and replace paths, the application's user
|
||||
# checkout swapped for the given one, one framework replace.
|
||||
local gw
|
||||
mkdir -p "$ws/app/plugins/golem15/user" "$ws/user"
|
||||
printf '%s\n' 'go 1.27.0' '' 'use (' ' .' ' ./plugins/golem15/user' ' ./plugins/golem15/feedback // a comment' ')' '' \
|
||||
'use ./tools' '' 'replace git.golem15.com/golem15/summercms => ../summercms.go' '' \
|
||||
'replace (' ' git.golem15.com/golem15/sm-golem-plugin => ./plugins/golem15/golem' ' git.golem15.com/golem15/sm-user-plugin => ./plugins/golem15/user' ' example.com/x v1.0.0 => example.com/y v1.1.0' ')' >"$ws/app/go.work"
|
||||
gw="$(gowork_with_user_plugin "$ws/app" "$ws/user" "$ws/framework")"
|
||||
local want_line
|
||||
for want_line in " $ws/app" " $ws/user" " $ws/app/plugins/golem15/feedback" "use $ws/app/tools" \
|
||||
" git.golem15.com/golem15/sm-golem-plugin => $ws/app/plugins/golem15/golem" \
|
||||
" git.golem15.com/golem15/sm-user-plugin => $ws/user" \
|
||||
" example.com/x v1.0.0 => example.com/y v1.1.0" \
|
||||
"replace git.golem15.com/golem15/summercms => $ws/framework"; do
|
||||
if ! grep -qxF -- "$want_line" <<<"$gw"; then
|
||||
rm -rf "$ws"
|
||||
echo "refuse: self-test gowork_with_user_plugin lacks the line \"$want_line\": $gw" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
if [[ "$(grep -c 'golem15/summercms =>' <<<"$gw")" != 1 ]] || grep -qE '(^|[[:space:]])\./|\.\./' <<<"$gw"; then
|
||||
rm -rf "$ws"
|
||||
echo "refuse: self-test gowork_with_user_plugin left a relative path or a second framework replace: $gw" >&2
|
||||
return 1
|
||||
fi
|
||||
rm -rf "$ws"
|
||||
echo "PASS self-test gowork_with_user_plugin"
|
||||
|
||||
# The demo pin policy on a planted demo whose check-pins.sh prints one
|
||||
# mismatch: test-only drift is reported, a non-test commit the canonical
|
||||
# checkout holds is accepted as unreleased, one it does not hold is
|
||||
# refused, and PHASE197_RELEASED=1 refuses any drift.
|
||||
local demo sub pin canon
|
||||
demo="$(mktemp -d)"
|
||||
sub="$demo/plugins/golem15/user"
|
||||
mkdir -p "$demo/scripts" "$sub"
|
||||
git -C "$sub" init -q
|
||||
printf 'package user\n' >"$sub/user.go"
|
||||
git -C "$sub" add user.go
|
||||
git -C "$sub" -c user.name=t -c user.email=t@example.test commit -q -m pin
|
||||
pin="$(git -C "$sub" rev-parse HEAD)"
|
||||
printf 'package user\n' >"$sub/user_test.go"
|
||||
git -C "$sub" add user_test.go
|
||||
git -C "$sub" -c user.name=t -c user.email=t@example.test commit -q -m test-only
|
||||
planted_pins() {
|
||||
printf '#!/usr/bin/env bash\necho "check-pins: plugins/golem15/user is at %s, go.mod requires git.golem15.com/golem15/sm-user-plugin v0.1.10 (%s)" >&2\nexit 1\n' \
|
||||
"$(git -C "$sub" rev-parse --short=12 HEAD)" "${pin:0:12}" >"$demo/scripts/check-pins.sh"
|
||||
}
|
||||
planted_pins
|
||||
expect_mode pins-test-only 0 "by test-only commits" --demo-pins "DEMO_APP=$demo" "USER_PLUGIN=$sub" PHASE197_RELEASED=0
|
||||
expect_mode pins-released-test-only 1 "refuse: PHASE197_RELEASED=1" --demo-pins "DEMO_APP=$demo" "USER_PLUGIN=$sub" PHASE197_RELEASED=1
|
||||
printf 'package user\n\nfunc Added() {}\n' >"$sub/user.go"
|
||||
git -C "$sub" -c user.name=t -c user.email=t@example.test commit -q -am feature
|
||||
planted_pins
|
||||
canon="$demo/canonical"
|
||||
git clone -q "$sub" "$canon"
|
||||
expect_mode pins-unreleased-accepted 0 "is ahead of its pin by unreleased commits" --demo-pins "DEMO_APP=$demo" "USER_PLUGIN=$canon" PHASE197_RELEASED=0
|
||||
git -C "$canon" checkout -q "$pin"
|
||||
expect_mode pins-unreleased-refused 1 "does not hold" --demo-pins "DEMO_APP=$demo" "USER_PLUGIN=$canon" PHASE197_RELEASED=0
|
||||
git -C "$canon" checkout -q -
|
||||
expect_mode pins-released-unreleased 1 "refuse: PHASE197_RELEASED=1" --demo-pins "DEMO_APP=$demo" "USER_PLUGIN=$canon" PHASE197_RELEASED=1
|
||||
unset -f planted_pins
|
||||
rm -rf "$demo"
|
||||
|
||||
local mode
|
||||
for mode in self-test go plugins consumers docker admin docs marker all; do
|
||||
@@ -604,6 +831,9 @@ run_plugins() {
|
||||
require_dir "$JOURNAL_PLUGIN" "blog plugin"
|
||||
# The user plugin is checked against its own go.mod (GOWORK=off), the
|
||||
# way a consuming application resolves it.
|
||||
GO_ENV="GOWORK=off" workspace_check "$USER_PLUGIN"
|
||||
workspace_check "$OAUTHSERVER_PLUGIN" "$USER_PLUGIN"
|
||||
workspace_check "$JOURNAL_PLUGIN"
|
||||
GO_ENV="GOWORK=off" go_vet "$USER_PLUGIN" ./...
|
||||
GO_ENV="GOWORK=off" go_short "$USER_PLUGIN" ./...
|
||||
additive_check user "$USER_PLUGIN" "$USER_BASE"
|
||||
@@ -624,10 +854,17 @@ run_consumers() {
|
||||
local app
|
||||
for app in "$FONOTEKA" "$BM_APP" "$DEMO_APP"; do
|
||||
require_dir "$app" "application"
|
||||
workspace_check "$app"
|
||||
done
|
||||
for app in "$FONOTEKA" "$BM_APP" "$DEMO_APP"; do
|
||||
(cd "$app" && go build ./...)
|
||||
echo "build: $app"
|
||||
go_short "$app" ./...
|
||||
done
|
||||
# The unreleased user plugin compiles with the applications that use it
|
||||
# (P-40: additive for its consumers before any tag).
|
||||
consumer_with_user_plugin "$FONOTEKA"
|
||||
consumer_with_user_plugin "$BM_APP"
|
||||
(cd "$DEMO_APP" && go build -tags "$MCP_TAG" ./...)
|
||||
echo "build: $DEMO_APP (-tags $MCP_TAG)"
|
||||
GO_FLAGS="-tags $MCP_TAG" go_short "$DEMO_APP" ./...
|
||||
@@ -637,13 +874,26 @@ run_consumers() {
|
||||
echo "phase19.7 consumers passed"
|
||||
}
|
||||
|
||||
# canonical_checkout NAME maps a demo plugin submodule to the checkout its
|
||||
# commits are developed in.
|
||||
canonical_checkout() {
|
||||
case "$1" in
|
||||
plugins/golem15/user) echo "$USER_PLUGIN" ;;
|
||||
plugins/golem15/oauthserver) echo "$OAUTHSERVER_PLUGIN" ;;
|
||||
plugins/golem15/journal) echo "$JOURNAL_PLUGIN" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# demo_pins runs the demo's pin check (every plugin submodule on the commit
|
||||
# go.mod requires). A submodule ahead of its pin only by commits that touch
|
||||
# *_test.go files (this phase's plugin tests, committed but not released)
|
||||
# ships the same code and is reported, not refused; any other mismatch
|
||||
# fails.
|
||||
# go.mod requires). With PHASE197_RELEASED=1 any mismatch fails. Otherwise
|
||||
# a submodule that descends from its pin is accepted when the commits past
|
||||
# the pin touch only *_test.go files (the same shipped code, reported as
|
||||
# test-only), or when its HEAD is the HEAD of, or an ancestor of, the
|
||||
# plugin's canonical checkout (reported as unreleased commits, released
|
||||
# after verification); any other mismatch fails.
|
||||
demo_pins() {
|
||||
local out rc=0 line name want head changed
|
||||
local out rc=0 line name want head full changed canonical
|
||||
[[ -f "$DEMO_APP/scripts/check-pins.sh" ]] || {
|
||||
echo "refuse: $DEMO_APP/scripts/check-pins.sh not found" >&2
|
||||
return 1
|
||||
@@ -653,6 +903,11 @@ demo_pins() {
|
||||
printf '%s\n' "$out"
|
||||
return 0
|
||||
fi
|
||||
if [[ "${PHASE197_RELEASED:-0}" == "1" ]]; then
|
||||
printf '%s\n' "$out" >&2
|
||||
echo "refuse: PHASE197_RELEASED=1 and a demo plugin submodule is not on its pin (bump the pins after the release)" >&2
|
||||
return 1
|
||||
fi
|
||||
while IFS= read -r line; do
|
||||
[[ -z "$line" ]] && continue
|
||||
if [[ "$line" =~ ^check-pins:\ (plugins/[^ ]+)\ is\ at\ ([0-9a-f]+),\ go\.mod\ requires\ .*\(([0-9a-f]+)\)$ ]]; then
|
||||
@@ -664,13 +919,19 @@ demo_pins() {
|
||||
return 1
|
||||
fi
|
||||
changed="$(git -C "$DEMO_APP/$name" diff --name-only "$want" HEAD | grep -vE '_test\.go$' || true)"
|
||||
if [[ -n "$changed" ]]; then
|
||||
printf '%s\n' "$changed" >&2
|
||||
echo "refuse: $name is ahead of its pin $want with non-test changes" >&2
|
||||
return 1
|
||||
if [[ -z "$changed" ]]; then
|
||||
echo "pins: $name is ahead of its pin $want by test-only commits (release not needed for shipped code)"
|
||||
continue
|
||||
fi
|
||||
echo "pins: $name is ahead of its pin $want by test-only commits (release not needed for shipped code)"
|
||||
continue
|
||||
canonical="$(canonical_checkout "$name")"
|
||||
full="$(git -C "$DEMO_APP/$name" rev-parse HEAD)"
|
||||
if [[ -n "$canonical" ]] && git -C "$canonical" merge-base --is-ancestor "$full" HEAD 2>/dev/null; then
|
||||
echo "pins: $name is ahead of its pin by unreleased commits (release after verification)"
|
||||
continue
|
||||
fi
|
||||
printf '%s\n' "$changed" >&2
|
||||
echo "refuse: $name is ahead of its pin $want with non-test changes its canonical checkout ${canonical:-<none>} does not hold" >&2
|
||||
return 1
|
||||
fi
|
||||
printf '%s\n' "$out" >&2
|
||||
echo "refuse: the demo's pin check failed" >&2
|
||||
@@ -690,6 +951,9 @@ run_docker() {
|
||||
require_dir "$USER_PLUGIN" "user plugin"
|
||||
require_dir "$OAUTHSERVER_PLUGIN" "OAuth server plugin"
|
||||
require_dir "$DEMO_APP" "demo application"
|
||||
GO_ENV="GOWORK=off" workspace_check "$USER_PLUGIN"
|
||||
workspace_check "$OAUTHSERVER_PLUGIN" "$USER_PLUGIN"
|
||||
workspace_check "$DEMO_APP"
|
||||
go_pkg_named "$ROOT" "-timeout 20m" "${DOCKER_TESTS[@]}"
|
||||
GO_ENV="GOWORK=off" go_named "$USER_PLUGIN" . "-timeout 20m" "${USER_TESTS[@]}"
|
||||
go_named "$OAUTHSERVER_PLUGIN" . "-timeout 20m" "${OAS_TESTS[@]}"
|
||||
@@ -829,6 +1093,7 @@ case "${1:---all}" in
|
||||
--consumers | consumers) run_consumers ;;
|
||||
--docker | docker) run_docker ;;
|
||||
--docker-gate) docker_gate ;;
|
||||
--demo-pins) demo_pins ;;
|
||||
--admin | admin) run_admin ;;
|
||||
--docs | docs) run_docs ;;
|
||||
--marker | marker) run_marker ;;
|
||||
|
||||
Reference in New Issue
Block a user