The smoke test could not fail, and other people's eyes
Four fixes, two of them serious, three of them found by the session porting
this into subscriptions.
1. THE SMOKE TEST COULD NOT FAIL. `wp eval-file` runs the file through eval()
INSIDE A METHOD, so the top level is function scope. `$wc_edm_failures = 0`
at the top and `global $wc_edm_failures` in the helper were two different
variables: the helpers incremented the real global, the verdict read the
local, and the local was always zero.
Measured rather than reasoned. A deliberately false assertion added to the
unmodified file:
FAIL DELIBERATE FAILURE — this run must go red
All assertions passed on WordPress 7.1 with WooCommerce 11.1.0.
EXIT=0
and with the fix, the same forced failure:
FAIL DELIBERATE FAILURE — this run must go red
1 assertion(s) failed on WordPress 7.1.
EXIT=1
The FAIL lines always printed, so failures found by reading the output were
real finds. What was broken is the CI gate: a regression on either forge
would have gone green. Four lines at the top now prove the counter reaches
the verdict before anything relies on it — this is the one file whose whole
job is to be able to go red, so it checks that it can.
2. `git ls-files` QUOTES NON-ASCII PATHS. "TESTMILJØ.md" comes back as the
literal string "TESTMILJ\303\230.md", which matches no pattern in
.distignore, so the file is kept — an internal document walking into the
release zip with nothing said. Fixed in ci/dist-files.sh and in
ci/static.sh's trailing-?> check, which had the same bug and would have
silently skipped the file it exists to check. Verified by adding such a
filename and watching it be excluded. `done < <(...)` rather than a pipe, or
the loop runs in a subshell and the failure counter stops incrementing.
3. THE FEED CACHE WAS SIX HOURS, and Kristian hit it: a release published and
his shop shown nothing. The reasoning ("WordPress checks twice a day") was
wrong. WordPress gates its own check by screen in wp_update_plugins() — one
minute on Dashboard → Updates, one hour on Plugins, 2–12 hours in the
background — so WordPress is already the rate limiter and a longer cache
only hides releases underneath it. Fifteen minutes now, pinned by an
assertion.
4. The wp_update_plugins() assertion made a real HTTP request, because the
force-check tests had just deleted the transient. It passed only because
this feed repo is public, which made it measure the environment rather than
the code. Re-primed first.
ci_in_container() replaces the inline docker plumbing in ci_php(), taken from
the subscriptions port: the script goes in as a file rather than interpolated
into `sh -c`, and --entrypoint sh matters for images whose entrypoint swallows
its arguments.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
48119f2034
commit
a1f6e54f9d
@@ -46,33 +46,51 @@ ci_plugin_header() {
|
||||
"$(ci_repo_root)/$PLUGIN_MAIN" | head -1 | sed -E 's/[[:space:]]+$//'
|
||||
}
|
||||
|
||||
# Run a shell script against a checkout of this repository, inside a container.
|
||||
#
|
||||
# The repository goes in over a tarball and `docker cp`, never a bind mount: a
|
||||
# Gitea Actions job runs inside a container talking to the HOST's docker
|
||||
# daemon, so a host path here lands on an empty directory nobody created and
|
||||
# the check passes by checking nothing. The symptom reads like a typo in a path.
|
||||
#
|
||||
# Two details are load-bearing. The script is copied in as a FILE rather than
|
||||
# interpolated into `sh -c`, so it can contain $, quotes and newlines without
|
||||
# being mangled — which matters the moment it is more than one command. And
|
||||
# --entrypoint sh is not decoration: some images (composer:2, for one) have an
|
||||
# entrypoint that swallows its arguments.
|
||||
#
|
||||
# Taken from the subscriptions port, which needed it for composer.
|
||||
ci_in_container() { # image script-text
|
||||
local image="$1" script="$2"
|
||||
local dir cid code=0
|
||||
|
||||
dir=$(mktemp -d -t wpci-XXXXXX)
|
||||
( cd "$(ci_repo_root)" && git ls-files -z | tar --null -T - -cf "$dir/src.tar" )
|
||||
printf '%s\n' "$script" > "$dir/run.sh"
|
||||
|
||||
cid=$(docker create --entrypoint sh -w /src "$image" \
|
||||
-c 'mkdir -p /src && tar -xf /tmp/src.tar -C /src && exec sh /tmp/run.sh')
|
||||
docker cp "$dir/src.tar" "$cid:/tmp/src.tar" >/dev/null
|
||||
docker cp "$dir/run.sh" "$cid:/tmp/run.sh" >/dev/null
|
||||
docker start -a "$cid" || code=$?
|
||||
docker rm -f "$cid" >/dev/null
|
||||
rm -rf "$dir"
|
||||
return "$code"
|
||||
}
|
||||
|
||||
# Run one of this repository's PHP scripts.
|
||||
#
|
||||
# Uses the local php when there is one — a laptop, GitHub's hosted runners —
|
||||
# and a container otherwise. The Gitea runner image has no php, and losing a
|
||||
# build to "php: command not found" after everything else passed is a silly way
|
||||
# to spend an afternoon. Measured: it happened on the very first Gitea run.
|
||||
#
|
||||
# The repository goes in over a tarball and `docker cp`, never a bind mount: a
|
||||
# Gitea Actions job runs inside a container talking to the HOST's docker
|
||||
# daemon, so a host path here lands on an empty directory nobody created.
|
||||
ci_php() {
|
||||
if command -v php >/dev/null 2>&1; then
|
||||
php "$@"
|
||||
return
|
||||
fi
|
||||
|
||||
local tarball cid code=0
|
||||
tarball=$(mktemp -t wpci-php-XXXXXX.tar)
|
||||
( cd "$(ci_repo_root)" && git ls-files -z | tar --null -T - -cf "$tarball" )
|
||||
|
||||
cid=$(docker create "php:8.4-cli" sh -c \
|
||||
"mkdir -p /src && tar -xf /tmp/src.tar -C /src && cd /src && exec php $(printf '%q ' "$@")")
|
||||
docker cp "$tarball" "$cid:/tmp/src.tar" >/dev/null
|
||||
docker start -a "$cid" || code=$?
|
||||
docker rm -f "$cid" >/dev/null
|
||||
rm -f "$tarball"
|
||||
return "$code"
|
||||
ci_in_container "php:8.4-cli" "exec php $(printf '%q ' "$@")"
|
||||
}
|
||||
|
||||
ci_step() { printf '\n\033[1m→ %s\033[0m\n' "$*"; }
|
||||
|
||||
Reference in New Issue
Block a user