psbits / qa
Shared QA infrastructure for PSBits TYPO3 extensions: test matrix scripts, Docker setup, linter and fixer configuration, custom PHP CS Fixer rules
Requires
- php: ^8.3
- friendsofphp/php-cs-fixer: ^3.95
Requires (Dev)
- ergebnis/composer-normalize: ^2.56
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11
- typo3/cms-core: ^13.4 || ^14.3
- typo3/testing-framework: ^9.5
Suggests
- psbits/crafter: Code and file generator for PSBits TYPO3 extensions
Provides
None
Conflicts
None
Replaces
None
README
Shared QA infrastructure for the PSBits TYPO3 extension repositories. The package holds the single source of truth for:
- the unit/functional test matrix (v13.4 / v14.3, sqlite / mysql / postgres, local
and Docker legs) -
Resources/Testing/Scripts/,Resources/Testing/Docker/ - the PHPUnit suite configurations - rendered into
<repo>/.Build/phpunit/(git-ignored) with absolute paths byResources/Testing/renderPhpunitXml.php - linter and fixer configuration -
Resources/Quality/(php-cs-fixer incl. the sharedPSBits/*custom fixers, PHPStan baseline, prettier, yamllint, typoscript-lint, lint-class-attributes) - the shared skills (
psbits-qa,psbits-foundation,psbits-v14-compat) and the git pre-commit hook -Resources/Skill/,Resources/GitHooks/, installed bybin/qa sync - the shared GitHub CI workflow (
extension-ci.ymlin this repository's.github/workflows/) and its caller template -Resources/CI/ci.yml, kept in sync with the repositories bybin/qa sync/bin/qa check
Usage in an extension
{
"require-dev": {
"psbits/qa": "@dev"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/phantasie-schmiede/qa.git"
}
],
"scripts": {
"post-install-cmd": [".Build/bin/qa sync"],
"post-update-cmd": [".Build/bin/qa sync"]
}
}
Caller CI workflow
The extension repository keeps only a thin caller workflow
(.github/workflows/ci.yml) that invokes the shared test-matrix workflow of
this repository:
jobs: ci: uses: phantasie-schmiede/qa/.github/workflows/extension-ci.yml@main secrets: inherit
Adopt it by copying Resources/CI/ci.yml from this package into
.github/workflows/ci.yml once; from then on bin/qa sync
(composer post-install/update) keeps the file in sync with the template and
bin/qa check (run by the CI qa job) fails on drift. Repositories without
Tests/Functional run unit-only: the functional suite is skipped by
runTests.sh/runCoverage.sh and the database legs (MariaDB/PostgreSQL)
are skipped entirely by the shared workflow. The TYPO3_API_TOKEN secret
is optional: repositories without it skip the TER publish, everything else
runs unchanged.
The extension keeps only its repo-specific QA files:
Build/Quality/phpstan.neon.dist (thin shim over the package baseline),
Build/Quality/coverage-baseline.json and Build/Quality/.prettierignore
(where applicable). The composer scripts point at the package resources, e.g.
php .Build/vendor/psbits/qa/Resources/Testing/renderPhpunitXml.php unit
php -d memory_limit=1G .Build/bin/phpunit -c .Build/phpunit/UnitTests.xml
The test matrix scripts resolve the repository root from PSBITS_QA_REPO_ROOT
or the current working directory (composer and CI both run from the repo
root); the Docker image name derives from PSBITS_QA_EXTENSION (default:
the repository directory name).
Linting the package itself
The package is linted with the tooling it ships: the root
phpstan.neon.dist includes the shared baseline
Resources/Quality/phpstan.neon (paths src, tests, bin/qa), the root
.php-cs-fixer.php calls CsFixerFactory::create(['src', 'tests', 'Resources']), and composer normalize keeps the composer.json clean.
The CI lint job (single PHP 8.4) runs composer analyze:php,
composer lint:composer and composer lint:php.
CLI
bin/qa sync install git hook + skill symlinks and create or sync the
caller CI workflow (idempotent)
bin/qa check verify hook, skill links and caller CI workflow (CI gate,
exits non-zero on drift)
bin/qa paths print the shared resource locations