Repository navigation
Releases
v1.1.1
v1.1.0
v1.0.0
First tagged release. Consumers pin @v1.
Changed
-
Every reusable workflow takes its runner from a new
runs-oninput (JSON: a label or a list of labels), defaulting to GitHub-hosted"ubuntu-latest", andwp-ci.ymlandwp-cd.ymlforward it to every workflow they call. Hard-coding[self-hosted]left public callers (and this public repository's own CI) queued with no runner, since a reusable workflow's jobs run in the calling repository. rtCamp's private repositories pass'["self-hosted"]', as the org runner policy requires.ci-self-check.ymlruns onubuntu-latest, andbin/check-workflows.shnow requires reusable workflows to use and forward the input instead of checking a label allow-list. -
Caller values no longer reach a
run:body through${{ }}interpolation — a conventionAGENTS.mdalready documented but sixteen steps across eight workflows broke. Value inputs (composer-flags,phpstan-level) now travel through stepenv:and become argv, so shell metacharacters in them stay literal instead of executing. Command inputs (build-command,test-command,phpcs-command,phpstan-command,lint-command, andcd-built-branch.yml's per-target equivalents) also travel throughenv:and are run asbash -eo pipefail -c "$COMMAND": executing them is the contract, but routing them through the environment stops render-time splicing, where a newline in the value injects extra lines into the generated script.-eo pipefailis not optional — a barebash -cdoes not inheritset -e, so a failing command would exit 0 and pass a job green.bin/check-workflows.shnow fails on any${{ inputs. }}/${{ matrix. }}inside arun:body, so the convention is verified rather than merely documented. -
cd-github-release.ymlpackages the release asset instead of attaching the artifact's top-level entries directly.gh release createonly accepts files, butdownload-artifactunpacks a directory artifact, so any plugin with a subdirectory — including the shapeexamples/cd-github-release.ymlproduces — failed at the upload. A directory artifact is now re-rooted under<slug>/and zipped to a single<slug>.zipthat installs through wp-admin; an artifact that is already a single archive is attached untouched, so a pre-zippedartifact-pathkeeps working. The two cases are told apart by archive extension rather than file count, so a single-file plugin still gets packaged. Adds an optionalsluginput (defaults toartifact-name). -
ci-test-js.yml'senable-cachenow caches something. Jest has noJEST_CACHE_DIRECTORYenvironment variable, so the previous wiring cached an always-empty directory, and the fixedjest-<os>key was written once and never updated again. The cache directory is now passed as a real--cacheDirectoryargument and the key includes theworking-dir-scoped lockfile hash with arestore-keysfallback. A customtest-commandmust forward its arguments for the flag to land; the default does. -
ci-self-check.ymlrunsyamllintover the whole repository rather than just.github/workflows/andexamples/, matching theyamllint .thatAGENTS.mdtells contributors to run — previously.yamllint.ymland.github/actionlint.yamlcould fail locally while CI stayed green. -
cd-built-branch.yml'spublishedandpublished-shaoutput descriptions now cover every no-push outcome. A run superseded by a newer one also reportspublished=falsewith an empty SHA, sofalsenever meant "dry run" on its own. The job summary distinguishes the two cases as well, instead of reporting a superseded run as "Publish did not complete". -
AGENTS.mdandCONTRIBUTING.mddescribebin/as Bash, not POSIX shell —bin/check-workflows.shusesBASH_SOURCE,[[ ]], arrays and process substitution, so the POSIX label gave contributors the wrong portability contract. -
Documentation restructured for a public
main. Caller examples move out ofREADME.mdintoexamples/, one runnable file per workflow, verified in CI bybin/check-workflows.sh.README.mdis now a workflow index plus a versioning guide, and no longer duplicates the input tables — each workflow'sworkflow_callblock is the single source of truth, and GitHub renders those descriptions when a caller is configured. Repo conventions move to a tool-agnosticAGENTS.md, whichCLAUDE.mdimports. AddsLICENSE(GPL-2.0-or-later, previously declared but absent) andCONTRIBUTING.md. -
version-monitor.ymlnow pinsactions/checkoutandactions/setup-nodeto the same SHAs as the other fifteen workflows, and its job carries an explicitname:. -
The
wp-tooling-tokensecret is removed fromci-detect-changes.yml,version-monitor.ymlandwp-ci.yml.rtCamp/wp-toolingis public, so the CLI now installs straight from itsnpm/wp-toolingbranch with no token. This secret never appeared in a tagged release, so v1.0.0 simply ships without it — no major bump is owed. Anyone pinned to a branch ref for pre-release smoke testing must still delete the line, or the call fails withInvalid input, wp-tooling-token is not defined in the referenced workflow. A newwp-tooling-refinput (forwarded throughwp-ci.yml) pins the install to a commit SHA and installs with--ignore-scripts, so a change on that branch cannot alter what your CI runs; override it to track the tip. The package is still not on the npm registry, so the install remains a git ref. -
The
packages-tokensecret is removed fromci-lint-php.yml,ci-test-php.ymlandwp-ci.yml.rtCamp/wp-frameworkis public, so no known private Composer dependency is left to authenticate. It was added in6274f32and removed here, both within the unreleased v1.0.0 cycle, so no tagged release ever accepted it. Anyone pinned to a branch ref must delete the line, or the call fails withInvalid input, packages-token is not defined in the referenced workflow.setup-phpstill receivesgithub-token: ${{ github.token }}for the API rate limit, which never depended on the secret, andci-test-php.ymldrops the wp-env Composer-auth step that existed only to forward it into the container. -
Monorepo fixes across the CI leaves. All six
setup-nodesteps that usecache: npmnow passcache-dependency-path, andci-lint-php.yml's Composer cache key is scoped to<working-dir>/composer.lock.ci-build-artifact-gate.ymlnormalises and regex-escapesworking-dirbefore anchoring its pattern — previously a./-prefixed or metacharacter-containing value matched nothing, so the gate passed green on a PR that committed build output.ci-test-build-artifact.ymlgainsworking-dir. -
cd-github-release.ymlandcd-wp-org.ymlgainworking-diras a path prefix, not a working directory: it scopes only the source-tree paths they read (changelog-path,assets-path), since the deployed files come from an already unit-scoped artifact. Both previously fell back to the repo root in a monorepo and failed silently — another unit'sCHANGELOG.mdstill parses, and a missing.wordpress-orgonly emits a notice. Both now reject absolute and..paths.cd-s3.ymlis unchanged. -
cd-github-release.yml,cd-wp-org.ymlandcd-s3.ymlfail fast in a first validation step when a required input arrives empty:tagandartifact-nameeverywhere, plusslugfor wporg andbucketfor s3.required: truedoes not reject an empty string, and an emptyartifact-namemakesdownload-artifactfetch every artifact in the run; an emptyslugwould fall back to the deploy action's repo-name default and could deploy to the wrong wordpress.org plugin, and an emptytagwould upload to<prefix>.zip.cd-wp-org.ymlandcd-s3.ymlalso presence-check their secrets as booleans, since a caller mapping an unset secret satisfies GitHub's required-secret check with an empty value. -
Every job runs on
runs-on: [self-hosted], per rtCamp's policy for private repositories. A reusable workflow's jobs run in the calling repository, so the caller needs access to the org's self-hosted runner group.bin/check-workflows.shapplies the same label allow-list as the org's runner-policy scanner, which stops checking a repository once it is public. These runners do not ship the AWS CLI, socd-s3.ymlinstalls a pinned, checksum-verified one when the runner has none. -
ci-detect-changes.yml, and sowp-ci.yml, now fetch an explicitbase-refbefore diffing. The CLI diffs an explicit base as-is, and the depth-2 checkout never holds a branch such asmain, so the diff failed, the CLI reported zero changes, and every downstream job skipped while the run passed green. The step also fails when the CLI reports a failed diff in any mode, instead of passing with nothing checked. -
ci-test-build-artifact.ymlpinswp-cli/doctor-commandto 2.3.1.@stableresolved to v3.0.0 (released 2026-08-04), which requires wp-cli ^3.0, while the wp-env cli container ships 2.12, so the job failed at the package install for every caller. -
AGENTS.mdandCONTRIBUTING.mdnow base task branches and pull requests onmain, addpipxto the install line becausepipx run yamllintneeds it, and list Docker Compose v2 as missing on the self-hosted runners.
Added
cd-built-branch.yml: reusable workflow that builds a project and force-pushes source plus generated output (Composervendor/, compiledassets/build/) to a dedicated branch, for platforms that deploy from a git branch rather than an artifact. Three jobs:discoverresolves thetargetsJSON into a build matrix,buildbuilds each target in parallel, andpublishforce-pushes a single commit whose parent is the source commit — sogit diff <source>..<target>is exactly the generated files, and rollback is a dispatch withsource-refplusallow-rewind: true. Every run republishes every target, so the branch is always a complete tree; a target whosediris miss...