Packages
This repository is a monorepo. The code is split into packages, and everything else, including this site, is shared at the root.
| Directory | Package | Namespace | Purpose |
|---|---|---|---|
packages/core | dpi/namespace-shortener-core | Dpi\NamespaceShortener\Core | The rule itself, working on plain strings. It knows nothing about any tool |
packages/php-cs-fixer | dpi/namespace-shortener-php-cs-fixer | Dpi\NamespaceShortener\PhpCsFixer | The adapter for PHP-CS-Fixer |
packages/php-codesniffer | dpi/namespace-shortener-phpcs | Dpi\NamespaceShortener\PhpCodeSniffer | The adapter for PHP_CodeSniffer, including its standard |
Each adapter depends on the core package and its own tool. Neither depends on the other, so installing one never brings in the other's tool.
At the root
| Path | Purpose |
|---|---|
docs | This site |
tests/Fixtures | Fixtures shared by the core tests and the adapters |
tests/Support | Helpers shared by every package's tests |
tests/DocumentationTest.php | Checks that the docs and the code agree |
composer.json | The development environment, including the autoloading for every package's tests |
.php-cs-fixer.dist.php, phpstan.neon, phpunit.xml.dist | Tool configuration, covering every package |
Working on it
Run composer install at the root, and run everything from there. There's one vendor directory, and vendor/dpi holds symlinks to packages, so a change to a package takes effect immediately. Packages don't have a vendor directory or a lock file of their own.
Adding a tool
- Create
packages/<tool>, with acomposer.jsonrequiring the core package atself.versionand the tool, and with thedevkeyword, so thatcomposer requirerecommends--dev. Give it theLICENSEand.gitattributesthe others have. - Add it to
require-devin the rootcomposer.jsonat@dev, and to theautoload-devsection for its tests. - Add its
srcandteststophpstan.neon, and add a test suite tophpunit.xml.dist. - Translate the conflicts and other exceptions from
Rewriterinto the tool's failures. UseRewriter::rewrite()if the tool takes a whole file, orRewriter::plan()if it reports each change. - Add a tool page, a tab in each guide page that has them, and a row in the table above.
- Create its repository, give the
SPLIT_TOKENsecret access to it, add it to the matrix in.github/workflows/split.yml, and register it on Packagist.
Versions
The packages share one version number, and the Git tag is the only place it's set. Each adapter requires the core package at self.version, which means exactly the adapter's own version, so nothing needs raising before you tag.
Locally, Composer takes the packages' version from Git, such as dev-main, and the root composer.json accepts it with @dev. Running composer update on another branch changes those versions in composer.lock, so don't commit that part of the change.
Publishing
Composer needs each package's composer.json at the root of its own repository, so .github/workflows/split.yml uses splitsh-lite to split each directory in packages out to a read-only repository, each registered on Packagist:
| Directory | Repository |
|---|---|
packages/core | dpi/namespace-shortener-core |
packages/php-cs-fixer | dpi/namespace-shortener-php-cs-fixer |
packages/php-codesniffer | dpi/namespace-shortener-phpcs |
Every push to main updates each repository's main, so make changes here, not there. Pushing a tag starting with v to this repository creates the same tag in all of them, which publishes that version of every package:
sh
git tag v1.0.0-beta2
git push origin v1.0.0-beta2The workflow pushes with the SPLIT_TOKEN secret, a fine-grained personal access token with read and write access to the contents of those repositories. It never force pushes, so its run fails if a repository has diverged, or if a tag already exists there on a different commit.