feat: reusable ci.yml — estate CI standard (Phase 0, step 1) #19

Merged
peptiderepo merged 11 commits from claude/reusable-ci-20260616 into main 2026-06-16 12:12:07 +00:00

11 Commits

Author SHA1 Message Date
peptiderepo
6adf255dea fix(ci): P2-A injection, P2-B lint-js fallback, P2-C phpcs config detection
P2-A: move ${{ inputs.line_limit_paths }} from raw shell into env: block (PATHS)
      to eliminate template-injection surface on caller-controlled input.
P2-B: replace 'npm run lint --if-present' (always exits 0 on missing script,
      killing the node --check fallback) with explicit node -e detection;
      fallback now actually runs when no lint npm script is defined.
P2-C: both phpcbf and phpcs steps now detect which of phpcs.xml /
      phpcs.xml.dist / .phpcs.xml.dist is present and pass it to --standard;
      guard and command now agree for all three config filename variants.

Validators: actionlint 1.7.4 clean, yamllint 1.38.0 clean (both files).
Version: 1.6.1

Agent-Session: claude/reusable-ci-20260616-p2-fixes
2026-06-16 12:01:53 +00:00
peptiderepo
47acc85a0e fix(ci): graceful PHPCS skip when phpcs.xml not present
Add guard to phpcbf and phpcs strict steps: if neither phpcs.xml,
phpcs.xml.dist, nor .phpcs.xml.dist exists in the repo root, both steps
exit 0 with an info message. This prevents startup_failure on the self-test
(peptide-e2e is a Node repo with no PHPCS config) and provides clean
feedback for repos not yet configured for PHPCS.

Real PHP repos all have a phpcs.xml (prautoblogger, theme, pr-core, etc.)
so the guard is transparent for them.

Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:46:12 +00:00
peptiderepo
d0f8c1d65c fix(ci): permissions model — no top-level perms in ci.yml; callers need write
GitHub Actions permission model for reusable workflows: callers must declare
at least the permission level that any job in the called workflow requests.
Since the phpcs job declares 'permissions: contents: write' (for phpcbf
commit-back), all callers must include 'permissions: contents: write' at
their workflow level.

Changes:
- ci.yml: remove top-level permissions block (was: contents: read); phpcs job
  already has job-level contents: write. Docblock now explains the caller
  requirement clearly.
- ci-self-test.yml: add 'permissions: contents: write' at workflow level.
- README.md: adoption snippet now includes the required permissions block.
- Remove diagnostic bisect/minimal test workflows (used to identify the root
  cause of startup_failure; finding: job-level write in reusable workflow
  requires caller to declare write at workflow level).

Confirmed: ci-bisect-caller with permissions: contents: write = SUCCESS.
Confirmed: actionlint 1.7.4 + yamllint 1.38.0 both clean.

Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:44:24 +00:00
peptiderepo
fa1df001ea test: bisect v3 — caller has write, called has only job-level write
Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:42:38 +00:00
peptiderepo
d0f4844af8 test: bisect v2 — no top-level perms in called, job-level write only
Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:41:35 +00:00
peptiderepo
3fb920e343 fix(ci): move permissions: contents: write to phpcs job level
Workflow-level permissions: write in a reusable workflow causes startup_failure
when calling workflow has default (read-only) permissions. Move write scope to
the phpcs job level only — the one job that actually needs it (phpcbf commit-back).
All other jobs run with the inherited read scope.

Self-test caller (ci-self-test.yml) confirmed clean with no top-level write
permission declared — job-level override in the reusable workflow is sufficient.

Confirmed via bisect: ci-bisect.yml (workflow-level write) startup_failed;
ci-minimal.yml (no write needed) succeeded; ci-bisect-caller with
permissions: write added succeeded. Job-level approach is the correct pattern.

Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:40:29 +00:00
peptiderepo
49daffafb6 test: bisect — add permissions: contents: write to caller
Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:38:16 +00:00
peptiderepo
be686bb3e0 test: bisect ci.yml startup_failure (matrix+if+permissions)
Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:37:21 +00:00
peptiderepo
84e1bfebfd test: minimal reusable workflow diagnostic
Adds ci-minimal.yml + ci-minimal-test.yml to diagnose the startup_failure
on the self-test reusable workflow call. To be removed after diagnosis.

Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:36:29 +00:00
peptiderepo
e3be036d19 fix(ci-self-test): use relative path for same-repo reusable workflow call
GitHub requires ./.github/workflows/ci.yml (not @branch-ref) for same-repo
reusable workflow calls from a PR branch. The @claude/reusable-ci-20260616
ref caused startup_failure because GitHub can't resolve branch-ref reusable
workflows that aren't on main yet.

Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:32:03 +00:00
peptiderepo
b5e54a4bdd feat: reusable ci.yml — estate CI standard (Phase 0, step 1)
Add .github/workflows/ci.yml as a reusable workflow_call entrypoint for
all 7 estate repos. Consistent job names (lint-php, phpcs, file-size,
phpunit, lint-js) so deploy-app.yml can needs: them uniformly.

Inputs: php_versions (JSON matrix), tests (stubs|wp-framework|brain-monkey|none),
enforce_300, line_limit_paths, has_js, phpcs_autofix.

phpcbf auto-commit: on pull_request, phpcbf runs and commits any auto-fixable
PHPCS violations back to the branch via GITHUB_TOKEN before strict phpcs.
On push events the commit step is skipped to prevent loops.

wp-framework PHPUnit path handles all three known WP CI gotchas:
(1) install svn (ubuntu-latest lacks it);
(2) skip-db-create=true (MySQL service pre-creates wp_tests via MYSQL_DATABASE);
(3) WP_CORE_DIR trailing slash (ABSPATH concatenation guard).

Also adds:
- .github/workflows/ci-self-test.yml: self-test caller (tests: none) so the
  reusable workflow is exercised on this PR.
- README.md: adoption snippet + full input reference for caller repos.
- CHANGELOG.md: v1.6.0 entry.

Agent-Session: claude/reusable-ci-20260616
2026-06-16 11:30:33 +00:00