Merge pull request #21 from kristianwind/selftest-gitea-safe
Make the self-test run on Gitea, where it has been failing since it landed
This commit is contained in:
+67
-11
@@ -132,31 +132,47 @@ echo "$out" | grep -qE '^ [0-9]+ shipped PHP files examined' \
|
|||||||
|| bad "the direct-access check printed no count — it cannot tell 13 files from 0"
|
|| bad "the direct-access check printed no count — it cannot tell 13 files from 0"
|
||||||
|
|
||||||
# ---------------------------------------------------------------- text domain
|
# ---------------------------------------------------------------- text domain
|
||||||
# No docker, so these are cheap. Three zeros, three verdicts.
|
# 🔴 ci_php, never a bare `php`. The Gitea runner image has NO php — that is
|
||||||
|
# why ci_php exists and says so — and this section originally called `php`
|
||||||
|
# directly. Two of its four assertions then failed there, and the other two
|
||||||
|
# PASSED FOR THE WRONG REASON: they expect a non-zero exit, and `php: command
|
||||||
|
# not found` is a non-zero exit. A green tick for a check that never ran is the
|
||||||
|
# exact thing this whole script exists to prevent, reproduced inside it.
|
||||||
|
#
|
||||||
|
# ci_php falls back to a container whose filesystem comes from `git ls-files`,
|
||||||
|
# so the fixtures live INSIDE this copy of the repo and are staged. A fixture
|
||||||
|
# outside the repo, or an unstaged one, is simply not there when it matters.
|
||||||
cd "$work/repo"
|
cd "$work/repo"
|
||||||
echo
|
echo
|
||||||
echo "→ ci/check-textdomain.php verdicts"
|
echo "→ ci/check-textdomain.php verdicts"
|
||||||
mkdir -p "$work/empty" "$work/nostrings"
|
|
||||||
printf '<?php\n$x = 1;\n' > "$work/nostrings/plugin.php"
|
|
||||||
|
|
||||||
php ci/check-textdomain.php --min=0 "$TEXT_DOMAIN" "$work/empty" >/dev/null 2>&1 \
|
# Not a literally empty directory: git cannot track one, so it would not reach
|
||||||
|
# the container at all and the check would fail for a different reason than the
|
||||||
|
# one being asserted.
|
||||||
|
mkdir -p selftest-empty selftest-nostrings selftest-dotted/includes
|
||||||
|
printf 'no php in here\n' > selftest-empty/.keep
|
||||||
|
printf '<?php\n$x = 1;\n' > selftest-nostrings/plugin.php
|
||||||
|
printf "<?php\necho __( 'x' );\n" > selftest-dotted/includes/class-db.php
|
||||||
|
git add -N selftest-empty/.keep selftest-nostrings/plugin.php \
|
||||||
|
selftest-dotted/includes/class-db.php >/dev/null
|
||||||
|
|
||||||
|
ci_php ci/check-textdomain.php --min=0 "$TEXT_DOMAIN" selftest-empty >/dev/null 2>&1 \
|
||||||
&& bad "an empty scan root passed — the root verdict must not be configurable away" \
|
&& bad "an empty scan root passed — the root verdict must not be configurable away" \
|
||||||
|| ok "an empty scan root is fatal even with --min=0"
|
|| ok "an empty scan root is fatal even with --min=0"
|
||||||
|
|
||||||
php ci/check-textdomain.php --min=999999 "$TEXT_DOMAIN" . >/dev/null 2>&1 \
|
ci_php ci/check-textdomain.php --min=999999 "$TEXT_DOMAIN" . >/dev/null 2>&1 \
|
||||||
&& bad "a --min above the real count passed" \
|
&& bad "a --min above the real count passed" \
|
||||||
|| ok "a --min above the real count is fatal"
|
|| ok "a --min above the real count is fatal"
|
||||||
|
|
||||||
php ci/check-textdomain.php "$TEXT_DOMAIN" "$work/nostrings" >/dev/null 2>&1 \
|
ci_php ci/check-textdomain.php "$TEXT_DOMAIN" selftest-nostrings >/dev/null 2>&1 \
|
||||||
&& ok "zero calls without --min warns rather than failing" \
|
&& ok "zero calls without --min warns rather than failing" \
|
||||||
|| bad "zero calls without --min failed — a small plugin may legitimately have none"
|
|| bad "zero calls without --min failed — a small plugin may legitimately have none"
|
||||||
|
|
||||||
# The annotated path must be a file that exists. str_replace( $root, '', $path )
|
# The annotated path must be a file that exists. str_replace( $root, '', $path )
|
||||||
# with the default root of "." strips every dot and yields "class-dbphp".
|
# with a root of "." strips every dot and yields "class-dbphp".
|
||||||
mkdir -p "$work/dotted/includes"
|
ann=$(ci_php ci/check-textdomain.php "$TEXT_DOMAIN" selftest-dotted 2>&1 \
|
||||||
printf "<?php\necho __( 'x' );\n" > "$work/dotted/includes/class-db.php"
|
| sed -n 's/.*file=\([^,]*\),.*/\1/p' | head -1)
|
||||||
ann=$(cd "$work/dotted" && php "$work/repo/ci/check-textdomain.php" "$TEXT_DOMAIN" . 2>&1 | sed -n 's/.*file=\([^,]*\),.*/\1/p' | head -1)
|
[ -n "$ann" ] && [ -f "selftest-dotted/$ann" ] \
|
||||||
[ -n "$ann" ] && [ -f "$work/dotted/$ann" ] \
|
|
||||||
&& ok "the annotated path exists on disk: $ann" \
|
&& ok "the annotated path exists on disk: $ann" \
|
||||||
|| bad "the annotated path is not a file: '$ann'"
|
|| bad "the annotated path is not a file: '$ann'"
|
||||||
|
|
||||||
@@ -225,6 +241,46 @@ ci_python_yaml ci/check-workflows.py >/dev/null 2>&1 \
|
|||||||
&& bad "check-workflows.py passed having parsed no file at all" \
|
&& bad "check-workflows.py passed having parsed no file at all" \
|
||||||
|| ok "parsing zero workflow files is fatal"
|
|| ok "parsing zero workflow files is fatal"
|
||||||
|
|
||||||
|
# ------------------------------------------------- no bare interpreter calls
|
||||||
|
# The bug that cost a green Gitea build: this script called `php` directly.
|
||||||
|
# The Gitea runner image has no php and no PyYAML, so a bare call there is
|
||||||
|
# "command not found" — which is a NON-ZERO exit, and therefore indistinguishable
|
||||||
|
# from the failure two of these assertions were written to expect. They went
|
||||||
|
# green having run nothing.
|
||||||
|
#
|
||||||
|
# ci_php and ci_python_yaml exist for this and say so in their comments. lib.sh
|
||||||
|
# is excluded because it is where the real calls live.
|
||||||
|
#
|
||||||
|
# Measured, so the rule is not uniform: the runner HAS python3 and has NO php,
|
||||||
|
# and PyYAML is the only missing module. A bare python3 over the stdlib is
|
||||||
|
# therefore correct and is not flagged.
|
||||||
|
echo
|
||||||
|
echo "→ no ci/ script may call php or python3 directly"
|
||||||
|
# Narrow on purpose. A broad "the word php appears" fires on every string
|
||||||
|
# literal that mentions php, and on the calls INSIDE the docker scripts in
|
||||||
|
# static.sh and site-test.sh, where php is exactly right because the container
|
||||||
|
# is a php image. A check that cries wolf gets commented out, which is worse
|
||||||
|
# than not having it. These two shapes are what the real bug looked like: the
|
||||||
|
# interpreter as the first word of a command, or inside $( ).
|
||||||
|
bare=$(cd "$work/repo" && for f in ci/*.sh; do
|
||||||
|
[ "$f" = ci/lib.sh ] && continue
|
||||||
|
sed 's/#.*//' "$f" \
|
||||||
|
| grep -nE '^[[:space:]]*php[[:space:]]|\$\((cd [^)]*&&[[:space:]]*)?php[[:space:]]' \
|
||||||
|
| sed "s|^|$f:|"
|
||||||
|
# python3 itself IS on the Gitea runner; only PyYAML is missing. So a bare
|
||||||
|
# python3 is fine for anything stdlib (build-zip.sh's zipfile, the JSON
|
||||||
|
# readers in publish-release.sh) and wrong only when yaml is involved.
|
||||||
|
sed 's/#.*//' "$f" \
|
||||||
|
| grep -nE '^[[:space:]]*python3[[:space:]].*(yaml|check-workflows)' \
|
||||||
|
| sed "s|^|$f:|"
|
||||||
|
done)
|
||||||
|
if [ -n "$bare" ]; then
|
||||||
|
printf '%s\n' "$bare" | sed 's/^/ /'
|
||||||
|
bad "a ci/ script calls an interpreter directly instead of ci_php / ci_python_yaml"
|
||||||
|
else
|
||||||
|
ok "every interpreter call goes through the container-capable wrapper"
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
if [ "$fail" != 0 ]; then
|
if [ "$fail" != 0 ]; then
|
||||||
echo "Self-test: $fail of $((pass + fail)) assertions FAILED."
|
echo "Self-test: $fail of $((pass + fail)) assertions FAILED."
|
||||||
|
|||||||
Reference in New Issue
Block a user