Contributing¶
Thanks for helping make pennylane-sdk better! Contributions of every size are welcome: bug reports, docs fixes, new endpoint coverage, ideas.
Development setup¶
Requirements: PHP 8.2 or later, and Composer.
git clone https://github.com/GoatAndCow7/pennylane-sdk-php
cd pennylane-sdk-php
composer install
Run the checks the CI runs:
composer test # phpunit, all mocked, no token needed
composer stan # PHPStan at level max
composer cs # coding style, dry run (use composer cs:fix to apply)
composer coverage-audit # every spec operation implemented, no unknown calls
Or run all of them at once with composer check.
Project layout¶
specs/ vendored official OpenAPI specs (source of truth)
scripts/update-specs.php refresh the specs from pennylane.readme.io
scripts/check-coverage.php audits that every spec operation exists in the resource classes
scripts/show-endpoint.php inspect one endpoint's schema from the specs
src/
Pennylane.php Company API v2 client
PennylaneFirm.php Firm API v1 client
Internal/ HTTP engine: auth, retries, throttle, error mapping
Pagination/ cursor and page-number auto-paginating pages
Resources/Company|Firm/ one class per URL namespace, extending AbstractResource
Types/Company|Firm/ response DTOs, extending PennylaneObject
tests/ mirrors src/, mocked with php-http/mock-client
docs/ mkdocs-material site
Adding or fixing an endpoint¶
- Find the operation in the spec:
php scripts/show-endpoint.php company "customer_invoices/{id}/finalize" put - Follow the conventions in
docs/design/resource-map.md: method naming, DTO shape, docblock format. - Write the resource method, its DTO if needed, and tests.
- Make the four checks above pass.
composer coverage-auditmust report every operation covered, with no unknown calls.
Style rules¶
- English everywhere in code and docs.
- No em dashes or en dashes in text; use plain punctuation instead.
- Resource methods call the
AbstractResourcehelpers (doGet,doGetPage,doGetNumberedPage,doPost,doPut,doDelete, and their variants) with the endpoint path as a single double quoted string literal, interpolating variables only in{$variable}form. This is whatscripts/check-coverage.phpparses; never build a path with concatenation,sprintfor an intermediate variable. - Docblocks state the required OAuth scope on a
Scope:line and link the official reference page on aReference:line. - Response DTO fields are nullable except
id; monetary amounts and quantities stay?string, neverfloat.
Releasing (maintainers)¶
- Update
CHANGELOG.md(move the relevantUnreleasedentries under a new version heading) and bumpVersion::SDK_VERSIONinsrc/Version.php. - Commit both changes together.
- Tag:
git tag v0.x.y && git push --tags. - The release workflow tests, builds and publishes the package to Packagist.
When the API changes¶
Refresh the vendored specs and see what the coverage audit reports:
composer update-specs
composer coverage-audit
New operations show up as MISSING; removed ones as UNKNOWN CALL. Please open an issue even if you cannot fix it yourself.