chore: add a single entry point for local development (#7922)

There was no root CONTRIBUTING.md and no way to run the CI gates locally in one
step, so reproducing a CI failure meant reading workflow YAML. Add a
'composer check' target that chains the gates, expose the sink and hotspot
guards, the changelog validator and the JavaScript tests as their own targets,
and document setup and the changelog.d fragment workflow.

Pin Node in .nvmrc to the version CI uses, and move the one remaining
setup-node still on 20 to 22 so every workflow agrees.

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
This commit is contained in:
Thomas Vincent authored and GitHub committed 2026-09-02 20:34:00 -07:00
1 parent c54a5595de
commit 97b5a1d4f5
4 files changed
+72 -2

No files matched your search

+1 -1
View File
@@ -160,7 +160,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with: with:
node-version: '20' node-version: '22'
cache: npm cache: npm
cache-dependency-path: | cache-dependency-path: |
package-lock.json package-lock.json
+1
View File
@@ -0,0 +1 @@
22
+54
View File
@@ -0,0 +1,54 @@
# Contributing to Cacti
## Setup
Cacti needs PHP (see `composer.json` for the supported range) and Node for the
front-end assets. `.nvmrc` pins the Node version CI uses.
composer install
npm ci
`npm ci` builds the JavaScript libraries under `include/js/` from the versions
pinned in `package.json`; see `build/README.md`.
## Checks
Run everything CI enforces:
composer check
That chains the individual targets, each of which can be run on its own:
| Command | What it checks |
| --- | --- |
| `composer lint` | PHP syntax |
| `composer phpstan` | Static analysis at level 6 |
| `composer php-cs-fixer` | Formatting, without writing changes |
| `composer php-cs-fixit` | Formatting, applying changes |
| `composer hardening-patterns` | Required security patterns |
| `composer changelog` | CHANGELOG and `changelog.d` fragment format |
| `composer sink-guard` | Dangerous-call inventory against its baseline |
| `composer hotspot-guard` | Architectural hotspot baseline |
| `composer test` | PHP test suite |
| `composer test-js` | JavaScript unit tests |
Install the pre-commit hook with `composer install-hooks`.
## Changelog
Do not edit `CHANGELOG` directly. Add a fragment under `changelog.d/` named for
the issue or pull request number, as described in `changelog.d/README.md`:
changelog.d/7692.issue
changelog.d/7634.feature
changelog.d/GHSA-wpjq-m269-mghj.security
Each fragment is a new file, so concurrent pull requests do not conflict.
## Baselines
`composer sink-guard` and `composer hotspot-guard` compare against checked-in
baselines. If a change legitimately adds or removes an entry, refresh it:
tests/security/build_sink_inventory.sh | tr -d '\r' | LC_ALL=C sort > tests/security/baselines/sink_inventory.baseline.tsv
tests/security/build_architectural_helper_report.sh --hotspots | tr -d '\r' | LC_ALL=C sort > tests/security/baselines/architectural_hotspots.baseline.tsv
+16 -1
View File
@@ -80,7 +80,22 @@
"hardening-patterns": "php tests/tools/check_hardening_patterns.php", "hardening-patterns": "php tests/tools/check_hardening_patterns.php",
"php-cs-fixit": "php-cs-fixer fix ", "php-cs-fixit": "php-cs-fixer fix ",
"install-hooks": "bash -c 'install -m 755 tests/tools/pre-commit \"$(git rev-parse --git-path hooks/pre-commit)\"'", "install-hooks": "bash -c 'install -m 755 tests/tools/pre-commit \"$(git rev-parse --git-path hooks/pre-commit)\"'",
"test": "include/vendor/bin/pest --display-warnings" "test": "include/vendor/bin/pest --display-warnings",
"sink-guard": "bash tests/security/verify_sink_inventory.sh",
"hotspot-guard": "bash tests/security/verify_architectural_hotspots.sh",
"changelog": "python3 .github/scripts/check-changelog.py",
"test-js": "node --test tests/js/*.test.js",
"check": [
"@lint",
"@phpstan",
"@php-cs-fixer",
"@hardening-patterns",
"@changelog",
"@sink-guard",
"@hotspot-guard",
"@test",
"@test-js"
]
}, },
"authors": [ "authors": [
{ {