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>
42 lines
1.8 KiB
Bash
Executable File
42 lines
1.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# List the files that go into the installed plugin: everything git tracks,
|
|
# minus the patterns in .distignore.
|
|
#
|
|
# Deliberately the only answer to "what ships". The release zip and the
|
|
# hygiene checks both read it, so a file cannot be excluded from one and
|
|
# included in the other — which is the version of this bug that ends with
|
|
# internal notes readable over HTTP on a live shop.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
[ -f .distignore ] || { echo ".distignore is missing — the zip would contain git files and internal notes." >&2; exit 1; }
|
|
|
|
patterns=()
|
|
while IFS= read -r line; do
|
|
line="${line%%#*}"
|
|
line="$(printf '%s' "$line" | sed -E 's/^[[:space:]]+|[[:space:]]+$//g')"
|
|
[ -n "$line" ] && patterns+=("${line%/}")
|
|
done < .distignore
|
|
|
|
# -z, not plain `git ls-files`: git QUOTES any path containing a non-ASCII
|
|
# byte, so "TESTMILJØ.md" comes out as the literal 14-character string
|
|
# "TESTMILJ\303\230.md". That form matches no pattern in .distignore, so the
|
|
# file is kept — an internal document walking straight into the release zip
|
|
# with nothing said. (-z also covers paths with spaces.) Found in a sibling
|
|
# plugin that has exactly such a filename; this repo has none today, which is
|
|
# precisely why it would have sat here until someone added one.
|
|
git ls-files -z | while IFS= read -r -d '' file; do
|
|
keep=1
|
|
for p in "${patterns[@]}"; do
|
|
# A bare name excludes the file or directory wherever it appears, which is
|
|
# how .distignore is read everywhere else. Anchor with a leading / to mean
|
|
# the repo root only.
|
|
case "$p" in
|
|
/*) case "$file" in "${p#/}"|"${p#/}"/*) keep=0 ;; esac ;;
|
|
*) case "$file" in $p|$p/*|*/$p|*/$p/*) keep=0 ;; esac ;;
|
|
esac
|
|
[ "$keep" = 0 ] && break
|
|
done
|
|
[ "$keep" = 1 ] && printf '%s\n' "$file"
|
|
done
|