fix(release): post-mortem fixes discovered during 1.2.0 release

Issue 1: `unzip -l "$ZIP_PATH" | grep -q ...` combined with set -o
pipefail silently fails when grep -q exits on first match and SIGPIPEs
the upstream unzip (which has not yet finished streaming the long file
list). pipefail sees unzip's non-zero exit and fails the pipeline, so
the guard thinks the file is missing. Fix: capture unzip -l output to
a variable once, then grep the string via herestring. The first two
sanity checks using `unzip -p` (short output, tight race window) were
not affected.

Issue 2: test_wp_plugin_info_json_download_url_contains_expected_asset_name
assumed Gitea asset URLs always contain the asset filename. This is
not true on git.netranking.ru, which returns /attachments/<uuid> — a
UUID-only URL. Relaxed the test to assert the URL is an HTTPS Gitea
URL; freshness of download_url is enforced indirectly via the
version-match test.

Post-mortem: 1.2.0 release was completed via a manual recovery script
after release.sh failed at the zip-sanity step. State on main is
consistent: tag v1.2.0 -> release commit, JSON commit directly on top
of release commit, JSON points to the live Gitea asset.
This commit is contained in:
Vladimir Bryzgalov
2026-04-21 23:55:16 +05:00
parent 1a15f0c872
commit 79e46ccf7e
2 changed files with 21 additions and 9 deletions
+7 -3
View File
@@ -129,14 +129,18 @@ unzip -p "$ZIP_PATH" cf7-spam-to-telegram/cf7-spam-to-telegram.php \
| grep -q "CF7STG_VERSION', '${VERSION}'" \ | grep -q "CF7STG_VERSION', '${VERSION}'" \
|| fail "zip sanity: CF7STG_VERSION mismatch inside $ZIP_PATH" || fail "zip sanity: CF7STG_VERSION mismatch inside $ZIP_PATH"
unzip -l "$ZIP_PATH" | grep -q "cf7-spam-to-telegram/includes/lib/plugin-update-checker/plugin-update-checker.php" \ # Cache zip listing once — `unzip -l | grep -q` triggers SIGPIPE to unzip with
# set -o pipefail, falsely failing the pipeline. Capture the list, then grep the string.
ZIP_LISTING="$(unzip -l "$ZIP_PATH")"
grep -q "cf7-spam-to-telegram/includes/lib/plugin-update-checker/plugin-update-checker.php" <<< "$ZIP_LISTING" \
|| fail "zip sanity: PUC loader missing from $ZIP_PATH" || fail "zip sanity: PUC loader missing from $ZIP_PATH"
unzip -l "$ZIP_PATH" | grep -q "cf7-spam-to-telegram/wp-plugin-info.json" \ grep -q "cf7-spam-to-telegram/wp-plugin-info.json" <<< "$ZIP_LISTING" \
|| fail "zip sanity: wp-plugin-info.json missing from $ZIP_PATH" || fail "zip sanity: wp-plugin-info.json missing from $ZIP_PATH"
for dev in tests/ docs/ composer.json composer.lock phpunit.xml release.sh CLAUDE.md AGENTS.md .gitattributes .gitignore; do for dev in tests/ docs/ composer.json composer.lock phpunit.xml release.sh CLAUDE.md AGENTS.md .gitattributes .gitignore; do
if unzip -l "$ZIP_PATH" | grep -q "cf7-spam-to-telegram/${dev}"; then if grep -q "cf7-spam-to-telegram/${dev}" <<< "$ZIP_LISTING"; then
fail "zip sanity: dev file must not be in zip: $dev" fail "zip sanity: dev file must not be in zip: $dev"
fi fi
done done
+14 -6
View File
@@ -54,15 +54,23 @@ final class UpdateCheckerIntegrationTest extends Cf7stgTestCase
); );
} }
public function test_wp_plugin_info_json_download_url_contains_expected_asset_name(): void public function test_wp_plugin_info_json_download_url_is_gitea_asset_url(): void
{ {
$data = json_decode(file_get_contents(self::WP_PLUGIN_INFO_JSON), true); $data = json_decode(file_get_contents(self::WP_PLUGIN_INFO_JSON), true);
$expectedAssetName = 'cf7-spam-to-telegram-' . $data['version'] . '.zip'; $url = $data['download_url'];
self::assertStringContainsString( self::assertNotEmpty($url, 'download_url must not be empty');
$expectedAssetName, self::assertStringStartsWith(
$data['download_url'], 'https://git.netranking.ru/',
"download_url must contain expected asset name $expectedAssetName" $url,
'download_url must point to our Gitea host'
); );
// Gitea returns one of two formats for release asset URLs:
// https://git.netranking.ru/<owner>/<repo>/releases/download/<tag>/<name>
// https://git.netranking.ru/attachments/<uuid>
// We cannot assert the asset name in the URL because the UUID format
// (used by git.netranking.ru) omits the filename entirely. Freshness
// is enforced indirectly: the plugin version must match CF7STG_VERSION
// (see test above), so a stale JSON would fail that test instead.
} }
public function test_plugin_class_has_register_update_checker_method(): void public function test_plugin_class_has_register_update_checker_method(): void