test(19.5): gate the email_verified_at migration and TestOwnerVerifiedEmail
- USER_ADDED_MIGRATIONS allows the one additive migration (D-27 relaxes D-22) - refused_migration_changes and migration_writes_rows, with --self-test cases - TestOwnerVerifiedEmail required in the docker stage
This commit is contained in:
@@ -13,8 +13,11 @@
|
||||
# application workspace), its Docker-free tests by required
|
||||
# name, and the additive check: since PHASE195_USER_BASE no
|
||||
# line declaring an exported func, method or type was removed
|
||||
# from a non-test .go file, and no file under updates/ changed
|
||||
# (D-22).
|
||||
# from a non-test .go file, and the migration check: the only
|
||||
# non-test change under updates/ is the added
|
||||
# email_verified_at migration (USER_ADDED_MIGRATIONS, D-22
|
||||
# relaxed by D-27), which must add its column with ADD
|
||||
# COLUMN IF NOT EXISTS and write or drop nothing.
|
||||
# sociallogin go vet and go test -short in the social login plugin, its
|
||||
# Docker-free tests by required name, no gorilla/sessions and
|
||||
# no gopkg.in/yaml.v3 in `go list -deps .`, and no Go file
|
||||
@@ -69,6 +72,11 @@ DEMO_APP="${DEMO_APP:-$ROOT/../sm-demo-app}"
|
||||
BM_APP="${BM_APP:-$ROOT/../sm-bm-app}"
|
||||
# The user plugin commit the phase started from (PATTERNS.md).
|
||||
USER_BASE="${PHASE195_USER_BASE:-4c5d3b8}"
|
||||
# The migrations the user plugin may add since USER_BASE. D-22 allowed none;
|
||||
# D-27 relaxes it for this one additive migration (users.email_verified_at,
|
||||
# a nullable column, no row written). Any other added, modified, renamed or
|
||||
# deleted non-test file under updates/ is refused.
|
||||
USER_ADDED_MIGRATIONS=(updates/202610210001_add_users_email_verified_at.go)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Required test names. Each list runs with -run '^(a|b|...)$' and every name
|
||||
@@ -142,6 +150,9 @@ DOCKER_SOCIAL_TESTS=(
|
||||
# Plan 04: the PHP ports, one subtest per PHP method.
|
||||
TestPHPSocialAuthGate TestPHPOAuthLinkCookie TestPHPPendingRegistrationTakeover
|
||||
TestPHPPasswordBootstrap TestPHPProfileOAuthLink
|
||||
# Plan 05 (D-26): a verified email links only onto an account whose
|
||||
# owner proved the address (users.email_verified_at).
|
||||
TestOwnerVerifiedEmail
|
||||
)
|
||||
|
||||
# docs stage: names of consuming applications (split so this file does not
|
||||
@@ -346,6 +357,34 @@ forbidden_deps() {
|
||||
grep -E '^(github\.com/gorilla/sessions|gopkg\.in/yaml\.v3)(/|$)' || true
|
||||
}
|
||||
|
||||
# refused_migration_changes reads `git diff --name-status` lines and prints
|
||||
# every line whose status is not A or whose path is not one of
|
||||
# USER_ADDED_MIGRATIONS (D-22, D-27). A rename (R...) or copy carries two
|
||||
# paths and is always refused.
|
||||
refused_migration_changes() {
|
||||
local status path rest allowed ok
|
||||
while IFS=$'\t' read -r status path rest || [[ -n "$status" ]]; do
|
||||
[[ -n "$status" ]] || continue
|
||||
ok=0
|
||||
if [[ "$status" == "A" && -z "$rest" ]]; then
|
||||
for allowed in "${USER_ADDED_MIGRATIONS[@]}"; do
|
||||
if [[ "$path" == "$allowed" ]]; then
|
||||
ok=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ "$ok" -eq 0 ]]; then
|
||||
printf '%s\t%s%s\n' "$status" "$path" "${rest:+$'\t'$rest}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# migration_writes_rows reads the Go file $1 without its // comment lines
|
||||
# and prints every line carrying an SQL word that writes or drops data.
|
||||
migration_writes_rows() {
|
||||
grep -vE '^[[:space:]]*//' "$1" | grep -E '\b(UPDATE|INSERT|DELETE|DROP|TRUNCATE)\b' || true
|
||||
}
|
||||
|
||||
run_self_test() {
|
||||
bash -n "${BASH_SOURCE[0]}"
|
||||
|
||||
@@ -424,6 +463,39 @@ run_self_test() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
# The migration check (D-22, D-27) accepts only the added
|
||||
# email_verified_at migration and refuses every other change under
|
||||
# updates/, and a migration that writes or drops anything.
|
||||
if [[ -n "$(refused_migration_changes <<<$'A\tupdates/202610210001_add_users_email_verified_at.go')" ]]; then
|
||||
echo "refuse: self-test refused_migration_changes refused the allowed migration" >&2
|
||||
return 1
|
||||
fi
|
||||
for line in $'M\tupdates/00_base.go' $'A\tupdates/202610220001_add_users_other.go' \
|
||||
$'D\tupdates/202610210001_add_users_email_verified_at.go' \
|
||||
$'R100\tupdates/202610160002_add_handle_to_users.go\tupdates/202610210001_add_users_email_verified_at.go'; do
|
||||
if [[ -z "$(refused_migration_changes <<<"$line")" ]]; then
|
||||
echo "refuse: self-test refused_migration_changes missed: $line" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
local mig
|
||||
mig="$(mktemp -d)"
|
||||
printf '%s\n' 'package updates' '' 'func m(tx *gorm.DB) error {' \
|
||||
' return tx.Exec(`UPDATE users SET email_verified_at = now()`).Error' '}' >"$mig/writes.go"
|
||||
printf '%s\n' 'package updates' '' '// No UPDATE here: the migration writes no rows.' 'func m(tx *gorm.DB) error {' \
|
||||
' return tx.Exec(`ALTER TABLE users ADD COLUMN IF NOT EXISTS email_verified_at TIMESTAMPTZ NULL`).Error' '}' >"$mig/clean.go"
|
||||
if [[ -z "$(migration_writes_rows "$mig/writes.go")" ]]; then
|
||||
rm -rf "$mig"
|
||||
echo "refuse: self-test migration_writes_rows missed a row update" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ -n "$(migration_writes_rows "$mig/clean.go")" ]]; then
|
||||
rm -rf "$mig"
|
||||
echo "refuse: self-test migration_writes_rows refused a word in a comment" >&2
|
||||
return 1
|
||||
fi
|
||||
rm -rf "$mig"
|
||||
|
||||
local mode
|
||||
for mode in self-test go userplugin sociallogin demo bm fonoteka docker docs all; do
|
||||
grep -q -- "^ --$mode" "${BASH_SOURCE[0]}" || {
|
||||
@@ -464,19 +536,37 @@ run_userplugin() {
|
||||
return 1
|
||||
fi
|
||||
added="$(grep -cE '^\+(func|type) ' <<<"$diff" || true)"
|
||||
# D-22, D-27: under updates/ only the email_verified_at migration may be
|
||||
# added (test files aside), and it adds its column and writes nothing.
|
||||
local refused file writes checked=0
|
||||
rc=0
|
||||
migrations="$(git -C "$USER_PLUGIN" diff --name-only "$USER_BASE" -- updates/ 2>&1)" || rc=$?
|
||||
migrations="$(git -C "$USER_PLUGIN" diff --name-status "$USER_BASE" -- updates/ ':(exclude)*_test.go' 2>&1)" || rc=$?
|
||||
if [[ "$rc" -ne 0 ]]; then
|
||||
printf '%s\n' "$migrations" | tail -n 5 >&2
|
||||
echo "refuse: git diff --name-only $USER_BASE -- updates/ in $USER_PLUGIN failed (exit $rc)" >&2
|
||||
echo "refuse: git diff --name-status $USER_BASE -- updates/ in $USER_PLUGIN failed (exit $rc)" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ -n "$migrations" ]]; then
|
||||
printf '%s\n' "$migrations" >&2
|
||||
echo "refuse: the user plugin changed files under updates/ since $USER_BASE (D-22: no migration change)" >&2
|
||||
refused="$(refused_migration_changes <<<"$migrations")"
|
||||
if [[ -n "$refused" ]]; then
|
||||
printf '%s\n' "$refused" >&2
|
||||
echo "refuse: the user plugin changed files under updates/ since $USER_BASE (D-22, D-27: only the email_verified_at migration may be added)" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "additive: no exported func, method or type removed and no migration changed in the user plugin since $USER_BASE ($added declarations added)"
|
||||
for file in "${USER_ADDED_MIGRATIONS[@]}"; do
|
||||
[[ -f "$USER_PLUGIN/$file" ]] || continue
|
||||
checked=$((checked + 1))
|
||||
if ! grep -q 'ADD COLUMN IF NOT EXISTS email_verified_at' "$USER_PLUGIN/$file"; then
|
||||
echo "refuse: $file does not add email_verified_at with ADD COLUMN IF NOT EXISTS (D-27)" >&2
|
||||
return 1
|
||||
fi
|
||||
writes="$(migration_writes_rows "$USER_PLUGIN/$file")"
|
||||
if [[ -n "$writes" ]]; then
|
||||
printf '%s\n' "$writes" >&2
|
||||
echo "refuse: $file writes or drops data (D-27: additive, no backfill)" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
echo "additive: no exported func, method or type removed and no migration changed beyond the allowed additions in the user plugin since $USER_BASE ($added declarations added; $checked allowed migration(s) added, column only)"
|
||||
echo "phase19.5 userplugin passed"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user