From 79e46ccf7e0241b6c5cb924e4156f1867f6b4237 Mon Sep 17 00:00:00 2001 From: Vladimir Bryzgalov Date: Tue, 21 Apr 2026 23:55:16 +0500 Subject: [PATCH] fix(release): post-mortem fixes discovered during 1.2.0 release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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/ — 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. --- release.sh | 10 +++++++--- tests/UpdateCheckerIntegrationTest.php | 20 ++++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/release.sh b/release.sh index 0afcd41..3f263e1 100755 --- a/release.sh +++ b/release.sh @@ -129,14 +129,18 @@ unzip -p "$ZIP_PATH" cf7-spam-to-telegram/cf7-spam-to-telegram.php \ | grep -q "CF7STG_VERSION', '${VERSION}'" \ || 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" -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" 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" fi done diff --git a/tests/UpdateCheckerIntegrationTest.php b/tests/UpdateCheckerIntegrationTest.php index 2d105ee..25eaf64 100644 --- a/tests/UpdateCheckerIntegrationTest.php +++ b/tests/UpdateCheckerIntegrationTest.php @@ -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); - $expectedAssetName = 'cf7-spam-to-telegram-' . $data['version'] . '.zip'; - self::assertStringContainsString( - $expectedAssetName, - $data['download_url'], - "download_url must contain expected asset name $expectedAssetName" + $url = $data['download_url']; + self::assertNotEmpty($url, 'download_url must not be empty'); + self::assertStringStartsWith( + 'https://git.netranking.ru/', + $url, + 'download_url must point to our Gitea host' ); + // Gitea returns one of two formats for release asset URLs: + // https://git.netranking.ru///releases/download// + // https://git.netranking.ru/attachments/ + // 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