# The only file under ci/ that knows anything about this particular plugin. # # Everything else in ci/ is plugin-agnostic on purpose: copying ci/, tests/ and # the two workflow roots into another plugin and rewriting these six lines is # the whole port. docs/REUSE.md walks through it. # Directory name the plugin gets inside wp-content/plugins, and the name of the # built zip. WordPress identifies a plugin by "/
", so changing # this after release orphans every installed copy. # # 🔴 THIS DELIBERATELY DOES NOT MATCH THE REPOSITORY NAME, and it must not be # "tidied up" to. The repo is woo-discount-manager; the installed directory has # been woocommerce-email-discount-manager since the first release and is on a # live shop. Renaming it would not move that installation — it would put a # SECOND copy beside it and leave the old one active. The repo name is free to # change (Gitea keeps a 301, measured), the installed slug never is. PLUGIN_SLUG=woocommerce-email-discount-manager # The file carrying the plugin header. Version: in here is the version. PLUGIN_MAIN=woocommerce-email-discount-manager.php # Every __() and esc_html__() call must use this domain or the translation is # silently dropped at runtime. TEXT_DOMAIN=wc-email-discount # WooCommerce is installed into the test site before the plugin is activated. # Set to no for a plugin that does not need it, and the site comes up faster. NEEDS_WOOCOMMERCE=yes # Run inside the live test site with `wp eval-file`, in this order. Fixtures # create the data; the smoke files assert against it. A non-zero exit or an # uncaught error fails the build. SITE_TESTS="tests/fixtures.php tests/smoke.php" # Plausibility floors for the hygiene checks. They exist because a check that # examined NOTHING prints the same reassuring line as one that examined # everything, and only the passing side can tell them apart — a pattern that is # too broad fails loudly on first contact with real code, one that finds nothing # survives verification forever. # # Both are deliberately far below the real numbers. They are not assertions # about this plugin's size: a tight number goes red on ordinary churn and gets # raised until it means nothing. They assert that the scan still finds this # plugin at all. # # Real counts when these were set (2026-09-17): 13 shipped PHP files, 142 # translation calls across 17 files. Both floors were broken once and watched to # fail before being believed. MIN_SHIPPED_PHP_FILES=5 # Set to 0 for a plugin with no translatable strings: the check then warns # instead of failing, so zero is never silent either way. MIN_TRANSLATION_CALLS=60 # Where releases are published, when that is not the repository running the # workflow. The source repo is kw/nolimit-discounts; the plugin's update feed # is a separate PUBLIC repo holding built zips only, so a shop can fetch # updates without credentials and without the source being readable. # # 🔴 This and the "Update URI:" header in the plugin file must name the same # repository. ci/static.sh fails when they disagree — a feed that moves while # the header stands still is how every installed copy silently stops receiving # updates, and nothing announces it because latest_release() just returns false. # # Publishing here needs a token with write access to that OTHER repository. The # job token only covers the repo it runs in, so this is a cross-repo PAT and # Kristian's to add. RELEASE_REPO=kw/nolimit-discounts-dist # The sha256 of includes/shared-menu.php, which is byte-identical in all six # plugins. Which copy a site loads is decided by activation order and PHP # cannot un-declare a function, so the first one wins for the whole request — # a shop with two plugins on one version and three on another gets whichever # booted first, while every repository's own check is green on its own side. # The frozen hash is therefore a family-wide fact, not a local one, and taking # a new one is something all six do in the same window. # # 471b0a2a = contract 1.2.2: the icon box is sized 100%/100% instead of a # hardcoded 36x34. WordPress declares that parent three times and they # disagree (36x34 open, 35x30 folded, 34x30 under 960px), so a fixed number is # right in one state and wrong in the two a laptop is usually in. # Withdrawn: 678f1f03 = 1.2.1: the glyph is centred with flex inside an explicit # 36x34 box instead of inheriting WordPress's 7px padding, which made the # pseudo-element 42px tall inside a 34px parent and pushed the sign above # centre. Kristian reported it from the live shop. # Earlier: 9012fe98 = contract 1.2.0. The glyph is now emitted as CSS numeric escapes # rather than through esc_attr(): HTML entities are not decoded by the CSS # parser, so esc_attr was protecting by coincidence — and a backslash, which it # leaves alone, IS a CSS escape and swallowed the closing quote. Changing the # alphabet beats filtering the input: what is emitted is nothing but # backslashes, hex digits and spaces, so there is nothing left to leave the # string with. Verified here against seven hostile inputs. # Earlier frozen hashes: 184cebdc = 1.1.0, f4862d5c = 1.0.0. WPMGR_MENU_SHA=471b0a2aab47b6b7f8d839ac8b12d60637bbe2c07df86f7e40089c677fbab3cc # The name this plugin used before the Nolimit rename. Kept so ci/static.sh # can fail when it reappears in text a user reads — a sentence that goes stale # breaks nothing by itself, which is why it survives. OLD_PLUGIN_NAME="WooCommerce Email Discount Manager"