Skip to content

ci: harden pre-merge checks and supply chain - #19

Merged
jackgranatowski merged 4 commits into
mainfrom
ci/harden-checks
Jun 8, 2026
Merged

ci: harden pre-merge checks and supply chain#19
jackgranatowski merged 4 commits into
mainfrom
ci/harden-checks

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

This pull request was created by @kiro-agent on behalf of @jackgranatowski 👻

Comment with /kiro fix to address specific feedback or /kiro all to address everything.
Learn about Kiro Web


Summary

Closes the gaps in the plugin's pre-merge gate: real PHP analysis, frontend type-checking, commit validation, dependency auditing, and supply-chain pinning.

  • PHP static analysis & standards replace the php -l syntax check alone:
    • PHPCS with a curated WordPress security/correctness ruleset (WordPress.Security, WordPress.DB, deprecated/enqueue sniffs, PHPCompatibilityWP for the PHP 7.4 floor). Advisory warnings don't fail the build; errors do.
    • PHPStan at level 5 with WordPress stubs (szepeviktor/phpstan-wordpress) and a baseline freezing the 71 pre-existing findings, so the gate catches new issues.
    • php -l is kept as a fast first pass.
  • svelte-check type-check gate added for both editor-app and admin-app (previously only build ran — no quality gate at all).
  • commitlint job validates PR commits against Conventional Commits.
  • npm audit job (root + both Svelte apps, high/critical gate).
  • All four workflows now pin actions to commit SHAs (were floating @v6/@v8/@v3/@v2 tags).
  • CI concurrency cancellation for superseded PR runs.

Real fix included

PHPCS surfaced one genuine error: a mispositioned phpcs:ignore in class-rebemer-rest.php that did not cover the $placeholders line of an IN (...) query. The query is safe (literal %s placeholders bound via $wpdb->prepare()); the comment was replaced with a correctly-scoped disable/enable block. No runtime behavior change.

Testing (run locally: Node 22, PHP 8.4, Composer)

  • composer phpcs → 0 errors (2 advisory cache warnings, non-blocking).
  • composer phpstan → 0 errors with baseline.
  • svelte-check → 0 errors in both apps.
  • npm audit --audit-level=high → 0 vulnerabilities (root + both apps).
  • npm test, npm run verify, lint:css, lint:php, check:cheatsheet → all pass.
  • commitlint accepts/rejects correctly. All workflow YAML validated.

Notes

  • composer.json + composer.lock are tracked; vendor/ is gitignored.
  • Regenerate the PHPStan baseline after intentional changes with composer phpstan -- --generate-baseline phpstan-baseline.neon.
  • Add the CI jobs + CodeQL as required status checks in branch protection for them to actually gate merges.

Summary by CodeRabbit

  • Chores
    • Enhanced code quality infrastructure with automated static analysis, standards compliance checks, and dependency security audits to improve stability and reliability.
    • Improved CI/CD pipeline reliability through pinned dependencies and expanded validation checks across all build workflows.

- pin all GitHub Actions to commit SHAs across every workflow
- add commitlint job validating PR commits (Conventional Commits)
- add svelte-check type-check gate for editor-app and admin-app
- add PHPCS (WordPress security/correctness ruleset) and PHPStan
  (level 5 with baseline) for the plugin PHP, replacing php -l alone
- add npm audit job (root + both Svelte apps, high/critical gate)
- add CI concurrency to cancel superseded PR runs
- fix mispositioned phpcs:ignore in class-rebemer-rest.php so the safe
  $wpdb->prepare() IN(...) query passes the new PreparedSQL sniff

Co-authored-by: Jack Granatowski <contact@codeslash.net>
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 11 minutes and 58 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 89ea33b0-593a-4d82-8ae8-495402eb002a

📥 Commits

Reviewing files that changed from the base of the PR and between 2989096 and 02a99ef.

📒 Files selected for processing (10)
  • .github/workflows/release.yml
  • SLASHED-for-WP/includes/class-css-parser.php
  • SLASHED-for-WP/includes/class-framework-updater.php
  • SLASHED-for-WP/includes/class-inventory.php
  • SLASHED-for-WP/integrations/bricks/includes/class-classes.php
  • SLASHED-for-WP/integrations/bricks/includes/class-variables.php
  • SLASHED-for-WP/integrations/gutenberg/includes/class-editor-enqueue.php
  • SLASHED-for-WP/integrations/gutenberg/includes/class-presets.php
  • phpcs.xml.dist
  • phpstan.neon.dist
📝 Walkthrough

Walkthrough

This PR establishes comprehensive code quality and static analysis infrastructure for the SLASHED plugin suite. It hardens GitHub Actions workflows against supply-chain attacks by pinning all third-party actions to specific commit SHAs, adds npm audit checks to catch high-severity dependency vulnerabilities, introduces PHP CodeSniffer and PHPStan static analysis with appropriate configuration, configures Svelte type-checking for both Bricks app variants, and applies widespread code formatting improvements to align with new tooling standards.

Changes

Code Quality and Tooling Infrastructure

Layer / File(s) Summary
CI/CD workflow security and dependency auditing
.github/workflows/ci.yml, .github/workflows/codeql.yml, .github/workflows/framework-sync.yml, .github/workflows/release.yml
All workflows pin actions/checkout, actions/setup-node, and framework-specific actions to specific commit SHAs (v6.0.2, v6.4.0, v2, v8) instead of major-version tags; CI workflow adds concurrency to cancel superseded PR runs and a new dependency-audit job that runs npm audit --audit-level=high for root, editor-app, and admin-app to fail on high-severity vulnerabilities.
PHP static analysis and code quality tooling
composer.json, phpcs.xml.dist, phpstan.neon.dist, phpstan-bootstrap.php, phpstan-baseline.neon, .gitignore
New composer.json declares PHP ≥7.4 with dev dependencies for PHP CodeSniffer, WordPress Coding Standards, PHPCompatibility, and PHPStan + WPStan; phpcs.xml.dist configures scanning rules for WordPress-Extra, PHPCompatibilityWP with PHP 7.4 testVersion, and custom hook delimiters; phpstan.neon.dist sets level 5 analysis with WordPress extension and frozen baseline; phpstan-bootstrap.php defines placeholder constants for static analysis; .gitignore excludes Composer-installed /vendor/ directory.
Svelte type-checking setup for Bricks apps
SLASHED-for-WP/integrations/bricks/editor-app/jsconfig.json, SLASHED-for-WP/integrations/bricks/editor-app/package.json, SLASHED-for-WP/integrations/bricks/admin-app/jsconfig.json, SLASHED-for-WP/integrations/bricks/admin-app/package.json
Both Bricks app variants receive new jsconfig.json files with ESNext module/target, bundler resolution, JS support (no type-check), non-strict settings, and src/**/*.{js,svelte} file inclusion; both package.json files add check script using svelte-check with jsconfig reference, plus svelte-check and typescript dev dependencies.
Code formatting and structural refactoring
SLASHED-for-WP/includes/*, SLASHED-for-WP/integrations/bricks/includes/*, SLASHED-for-WP/integrations/gutenberg/includes/*, SLASHED-for-WP/integrations/bricks/slashed-bricks.php, SLASHED-for-WP/integrations/gutenberg/slashed-gutenberg.php, SLASHED-for-WP/slashed.php
Widespread formatting refactoring across all PHP plugin code: reformats class constants, hook registrations, and REST responses to multi-line array style; expands token default arrays for readability; converts post-increment to pre-increment in loops; adjusts whitespace and indentation throughout. All changes are cosmetic—method signatures, logic, control flow, and public APIs remain unchanged.

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.61% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the main change: adding CI hardening via static analysis tools and supply-chain controls through action pinning.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/harden-checks

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

PHPCS now enforces the complete WordPress-Extra ruleset (was a curated
security/correctness subset):
- phpcbf-formatted all PHP to WP conventions (tabs, array layout, spacing,
  pre-increment, single quotes) — whitespace/format only, no logic change
- rename $_slashed_shared -> $slashed_shared so the bootstrap global is
  properly prefixed (PrefixAllGlobals)
- configure i18n sniff for the three real text domains (slashed,
  slashed-bricks, slashed-gutenberg) matching the standalone-plugin layout
- document-justified exclusions: class file-name convention, unused params
  in WP hook callbacks; advisory warnings stay non-blocking

PHPStan: shrink the baseline from 71 to 9 by fixing root causes instead of
freezing noise:
- phpstan-bootstrap.php declares the runtime define() constants
- ignore dynamic require_once path resolution
- treatPhpDocTypesAsCertain: false (PHPDoc types aren't runtime-enforced)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
phpstan-baseline.neon (1)

12-16: Note: Unreachable code warnings in baseline.

The baseline suppresses 4 "unreachable code" findings in class-framework-updater.php. These typically indicate dead code paths that could be removed in a follow-up cleanup. The baseline approach is appropriate for this PR's goal of establishing tooling gates without blocking on pre-existing issues.

Would you like me to investigate the unreachable code paths and suggest fixes for a follow-up PR?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@phpstan-baseline.neon` around lines 12 - 16, The baseline currently
suppresses four dead-code (deadCode.unreachable) findings for
SLASHED-for-WP/includes/class-framework-updater.php; identify the unreachable
branches inside class Framework_Updater (methods likely containing early
returns/exits) by running phpstan on that file and locating the specific
unreachable statement sites, then in a follow-up PR either remove the dead
branches or refactor control flow to make the code reachable (e.g., consolidate
early returns, remove redundant code after exit/throw, or guard branches
appropriately), and update or remove the specific baseline entries once the
unreachable statements are fixed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 35-38: The release workflow currently enables npm caching in the
actions/setup-node step (the step using
actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e and node-version:
22); remove the cache: npm entry from that step so dependencies are fetched
fresh during releases, and verify there are no other npm cache entries in the
same workflow to ensure reproducible, secure release builds.

---

Nitpick comments:
In `@phpstan-baseline.neon`:
- Around line 12-16: The baseline currently suppresses four dead-code
(deadCode.unreachable) findings for
SLASHED-for-WP/includes/class-framework-updater.php; identify the unreachable
branches inside class Framework_Updater (methods likely containing early
returns/exits) by running phpstan on that file and locating the specific
unreachable statement sites, then in a follow-up PR either remove the dead
branches or refactor control flow to make the code reachable (e.g., consolidate
early returns, remove redundant code after exit/throw, or guard branches
appropriately), and update or remove the specific baseline entries once the
unreachable statements are fixed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 37d19ddc-87fb-4787-942c-4538954a9d9e

📥 Commits

Reviewing files that changed from the base of the PR and between c9243de and 2989096.

⛔ Files ignored due to path filters (3)
  • SLASHED-for-WP/integrations/bricks/admin-app/package-lock.json is excluded by !**/package-lock.json
  • SLASHED-for-WP/integrations/bricks/editor-app/package-lock.json is excluded by !**/package-lock.json
  • composer.lock is excluded by !**/*.lock
📒 Files selected for processing (33)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/framework-sync.yml
  • .github/workflows/release.yml
  • .gitignore
  • SLASHED-for-WP/includes/class-admin.php
  • SLASHED-for-WP/includes/class-color-resolver.php
  • SLASHED-for-WP/includes/class-css-generator.php
  • SLASHED-for-WP/includes/class-framework-updater.php
  • SLASHED-for-WP/includes/class-hooks-page.php
  • SLASHED-for-WP/includes/class-inventory.php
  • SLASHED-for-WP/includes/class-rest-controller.php
  • SLASHED-for-WP/includes/class-settings.php
  • SLASHED-for-WP/includes/class-token-defaults.php
  • SLASHED-for-WP/includes/class-token-page.php
  • SLASHED-for-WP/integrations/bricks/admin-app/jsconfig.json
  • SLASHED-for-WP/integrations/bricks/admin-app/package.json
  • SLASHED-for-WP/integrations/bricks/editor-app/jsconfig.json
  • SLASHED-for-WP/integrations/bricks/editor-app/package.json
  • SLASHED-for-WP/integrations/bricks/includes/class-classes.php
  • SLASHED-for-WP/integrations/bricks/includes/class-enqueue.php
  • SLASHED-for-WP/integrations/bricks/includes/class-rebemer-rest.php
  • SLASHED-for-WP/integrations/bricks/includes/class-variables.php
  • SLASHED-for-WP/integrations/bricks/slashed-bricks.php
  • SLASHED-for-WP/integrations/gutenberg/includes/class-editor-enqueue.php
  • SLASHED-for-WP/integrations/gutenberg/includes/class-presets.php
  • SLASHED-for-WP/integrations/gutenberg/slashed-gutenberg.php
  • SLASHED-for-WP/slashed.php
  • composer.json
  • phpcs.xml.dist
  • phpstan-baseline.neon
  • phpstan-bootstrap.php
  • phpstan.neon.dist

Comment thread .github/workflows/release.yml Outdated
Resolve the leftover lint/analysis findings at the source so PHPStan now runs
with no baseline (fully strict) and PHPCS reports zero warnings:

- fix malformed @Property PHPDoc that broke the doc parser
- replace array_filter($parts, 'strlen') with a boolean callback
- guard CSS reads with is_readable() and drop the @ error suppression;
  justify file_get_contents on a local file
- remove redundant array_values() on already-list values
- remove unreachable return; after wp_send_json_* (which always exit)
- reword comments that tripped the commented-out-code heuristic
- inline @PHPStan-Ignore for the legitimate standalone-mode method_exists
  guard, with an explanatory comment
- phpcs.xml.dist: recognise Bricks' bricks_full_access capability; silence
  false-positive dynamic-hook-name and reserved-keyword ($var) advisories
Address CodeRabbit/zizmor cache-poisoning finding: a poisoned dependency
cache could be baked into the published plugin zip. Release builds now
fetch dependencies fresh from the registry with integrity verification.
CI workflows keep their cache (they don't publish artifacts).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants