Development Workflow¶
How to set up the project locally, run the quality checks, and deploy code to a development server.
Local Setup¶
Prerequisites: PHP 8.1 (the codebase pins php: 8.1.33; newer majors are not supported) and Composer available locally.
The committed src/vendor/ is production-only, so the dev tools (PHPStan,
phpcs) are not in the tree. Install them once from the committed lock:
This adds the require-dev packages into src/vendor/. Never commit them —
the committed vendor must stay production-only (composer install --no-dev).
.gitignore keeps the dev packages out of git add, and a CI gate
(check-vendor-prod-only) fails the build if one is ever committed.
Quality Checks¶
Run these before pushing — CI runs the same set:
| Command | Checks |
|---|---|
make phpstan |
Static analysis against the committed baseline (fails only on NEW issues) |
make cs |
Code style — import/namespace hygiene (phpcs + Slevomat) |
make cs-fix |
Apply the style fixes in place |
make gates |
PSR-4 regression gates (below) |
php tools/.bin/phpunit.phar -c tests/phpunit.xml.dist |
Unit tests — see PHPUnit Setup |
make phpstan and make cs need the dev tools — run make dev-tools first.
The PHPStan baseline lives at build/phpstan-baseline.neon — it freezes all pre-existing
issues so only new ones fail CI. If you intentionally change the level or accept a batch of
findings, regenerate it with make phpstan-baseline and commit the result. Don't regenerate it
just to silence a real new error — fix the code.
make gates bundles three guards:
- check-procedural-use — procedural / view files import every migrated class they use (PHP imports are positional, so the
usemust precede the usage); - verify-lb-archive — the Load Balancer build excludes privileged code (admin/reseller controllers, user/device domain, install/root commands) — see Build System (MAIN vs LB) for the exclusion boundary;
- check-vendor-prod-only — no
require-devpackage is committed undersrc/vendor/.
Deploying Code to VDS via SFTP¶
For daily development, we recommend the SFTP extension for VS Code — edit locally, auto-upload on save.
Setup¶
Create .vscode/sftp.json:
[
{
"name": "My Dev VDS",
"host": "YOUR_VDS_IP",
"protocol": "sftp",
"port": 22,
"username": "root",
"remotePath": "/home/xc_vm",
"useTempFile": false,
"uploadOnSave": true,
"openSsh": false,
"watcher": {
"files": "**/*",
"autoUpload": false,
"autoDelete": true
},
"ignore": [
".vscode",
".git",
".gitattributes",
".gitignore",
"update",
"*pycache/",
"*.gitkeep",
"bin/",
"config/",
"tmp/"
],
"context": "./src/",
"profiles": {}
},
{
"name": "My Dev VDS Tests",
"host": "YOUR_VDS_IP",
"protocol": "sftp",
"port": 22,
"username": "root",
"remotePath": "/home/xc_vm/tests",
"useTempFile": false,
"uploadOnSave": true,
"openSsh": false,
"watcher": {
"files": "**/*",
"autoUpload": false,
"autoDelete": true
},
"ignore": [
".vscode",
".git",
".gitattributes",
".gitignore",
"tmp/",
".cache/"
],
"context": "./tests/",
"profiles": {}
}
]
Key Settings¶
context: "./src/"— maps localsrc/to remote/home/xc_vm/context: "./tests/"— maps localtests/to remote/home/xc_vm/tests/uploadOnSave: true— every Ctrl+S pushes the file to VDS instantlyignore— protects server-specific files (bin/,config/,tmp/)
⚠️
watcher.autoDelete: true— deleting a file locally deletes it on the VDS too. Handy for keeping the tree in sync, but a mis-deleted local file (or a bad rename) will remove the remote copy. Keep theignorelist tight, or set it tofalseif you don't want the watcher to propagate deletions.Security: Use SSH keys instead of password. The
.vscode/directory is in.gitignore, so credentials won't leak to git.
How to sync the tests folder¶
- Add a second SFTP entry with
context: "./tests/"andremotePath: "/home/xc_vm/tests". - Save files under
tests/locally. - The extension will upload them separately from
src/into/home/xc_vm/tests. - This is required because tests are stored outside
src/and will not be uploaded by the main entry.
Workflow¶
- Open project in VS Code
- Edit any file under
src/ - If you add a test, edit the file under
tests/ - Save — the matching SFTP entry uploads the file to VDS
- Run the relevant test on VDS
- Commit to git as usual
Related files¶
| File | Role |
|---|---|
.vscode/sftp.json |
Local → VDS sync config (gitignored) |
Makefile |
make dev-tools, make phpstan, make cs, make gates |
src/composer.json |
Dependencies + PSR-4 autoload |