ci: add GitHub Actions workflow - #8
Merged
Merged
Conversation
No CI existed. The checks that matter here are not generic PHP tooling but the project invariants that were only enforced by prose in CLAUDE.md. - guards: version consistent across the four places it lives, no external HTTP call outside assets/vendor, no em dash in user facing copy, and JS translation files named after the right handle hash. That last one guards the wp-cli 2.12 make-json bug, which names files after assets/a.js and silently leaves JS strings in English. - lint: php -l from 8.0, the declared floor, up to 8.4. - i18n: POT covers every source string, and each MO matches its PO. A stale MO serves the previous translations with no error anywhere. - plugin-check: the official WordPress action, run on a staged copy that mirrors the release zip so it sees the real artifact. Warnings ignored, errors fail the build. Every guard was verified to fail on a seeded regression, not just to pass. .github/scripts/check-all.sh runs the whole set locally.
The i18n job hung for 12 minutes on `apt-get update` before being cancelled: unattended-upgrades holds the dpkg lock on the runner image often enough for this to be a real failure mode, not bad luck. gettext already ships with ubuntu-latest, so only reach for apt when msgfmt is genuinely missing, and never refresh the package lists. Both tools now print their version so a future breakage is visible in the log. Adds timeout-minutes: 15 to every job. A hung step was otherwise free to burn the six hour default.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The repo had no CI. Rather than bolt on generic PHP tooling, this wires up the checks that map to how this plugin actually breaks.
Jobs
guardslinti18nplugin-checkWhy these
Version consistency. The release touches
Version:,BIOLINKS_VERSION,Stable tag:andTested up to:in two files. ATested up tomismatch triggersmismatched_tested_up_to_headerand drops the plugin out of directory search, which is only visible after publishing. The check also assertsreadme.txtdocuments the version under both== Changelog ==and== Upgrade Notice ==.Zero external HTTP. A product promise since 1.1.2, previously protected by nothing but discipline. Fails if
wp_remote_*,curl_init,fsockopen, a remotesrc=,@import url(httporfetch()reappears outsideassets/vendor.JS translation hash. wp-cli 2.12 names
make-jsonoutput afterassets/a.jsinstead ofassets/admin.js, so WordPress never finds the file and the admin silently stays in English. This is the exact bug 1.1.10 had to fix. The check asserts every locale hasbiolinks-<locale>-$(md5 'assets/admin.js').json.Stale MO. The
.pois never read at runtime. If it is updated without recompiling, the old translations keep being served with no error anywhere. The check compares translated-message counts between each PO and its MO.Plugin Check runs on a staged copy built with the release zip exclusions, so it validates the shipped artifact rather than the repo, tooling included. Warnings are ignored since the ~102
DirectDatabaseQuery/InterpolatedNotPreparedones are structural: the 5.9 floor rules out prepared%iplaceholders.Verification
Each guard was run twice locally: once on the current tree, where all six pass, and once against a seeded regression to confirm it actually fails and prints something actionable. A guard that cannot fail is worse than no guard. The POT check found its own bug during this: it was swallowing a
make-potfailure and reporting a false stale POT. Fixed before commit..github/scripts/check-all.shruns the full set locally. The i18n scripts need wp-cli and gettext; the others need nothing.