Search by

contenir / contenir-qa-tools

peptolab

Shared QA toolchain for Contenir components: Mago formatting, linting and static analysis, plus the PHPUnit baseline and CI workflow. Forked from php-db/phpdb-qa-tools.

Package info

github.com/contenir/contenir-qa-tools

pkg:composer/contenir/contenir-qa-tools

Statistics

Installs: 3 921

Dependents: 51

Suggesters: 0

Stars: 0

v0.2.0 2026-10-07 03:00 UTC

README

Shared Mago + PHPUnit configuration and reusable CI workflow for Contenir components.

Fork of php-db/phpdb-qa-tools

This repository is a fork of php-db/phpdb-qa-tools. The Mago base configuration and the PHPUnit baseline are kept in step with upstream; the reusable CI workflow carries Contenir-specific changes:

  • No AI attributions — an extra attributions job fails the build when a pull request title, description or commit message carries an AI attribution.
  • Codecov failures fail the build — fail_ci_if_error: true, because Contenir packages are held at full coverage and a silent upload failure would hide a regression.
  • apt-packages input — installs Ubuntu packages before the test and mutation-test jobs, for system tools the tests shell out to (e.g. imagemagick).
  • Pinned runners — every job runs on ubuntu-24.04 rather than ubuntu-latest.
  • Codecov and mutation testing on by default — enable-codecov and enable-infection default to true. A package with no executable code opts out by setting them to false.

Upstream changes are merged in from the upstream remote:

git remote add upstream https://github.com/php-db/phpdb-qa-tools.git
git fetch upstream
git merge upstream/0.1.x

Prerequisite: install Mago

Mago is a self-contained static binary and is not delivered through Composer. Install it once per machine:

curl --proto '=https' --tlsv1.2 -sSf https://carthage.software/mago.sh | bash
# or
brew install mago
# or
cargo install mago

The shared configuration pins the expected Mago version, so a stale or too-new binary is flagged immediately.

Installation

composer require --dev contenir/contenir-qa-tools

Usage

1. Mago

Create a mago.toml in your repository root that extends the shared base and adds only the project-specific facts. Contenir components keep their suites under tests/, while the shared base assumes test/, so the test-path rules are overridden locally:

extends = "vendor/contenir/contenir-qa-tools/mago.toml"
php-version = "8.3.0"

[source]
paths = ["src", "tests"]
includes = ["vendor"]

[formatter]
# Keep `(new Foo())->bar()`: CI formats under each job's PHP version, and the
# unparenthesised form PHP 8.4+ allows does not parse on 8.3, the minimum.
parentheses-around-new-in-member-access = true

[linter.rules]
too-many-methods = { exclude = ["tests/"] }

[analyzer]
excludes = ["tests"]

Merge semantics: nested tables merge deeply, arrays concatenate (parent first), and child scalars win — so you can tighten or relax individual rules locally without forking the whole standard.

2. PHPUnit

Copy the strict baseline into your repository (PHPUnit has no config inheritance):

cp vendor/contenir/contenir-qa-tools/templates/phpunit.xml.dist .

The template's suites point at test/unit and test/integration. Contenir components use tests/Unit and tests/Integration with suites named unit and integration, so adjust the <testsuites> block after copying.

3. Composer scripts

Add the standard scripts to your composer.json:

{
    "scripts": {
        "check": ["@cs-check", "@static-analysis", "@test", "@test-integration"],
        "cs-check": ["mago format --check", "mago lint"],
        "cs-fix": ["mago format", "mago lint --fix"],
        "static-analysis": "mago analyze",
        "test": "phpunit --colors=always --testsuite unit",
        "test-integration": "phpunit --colors=always --testsuite integration",
        "test-coverage": "phpunit --colors=always --coverage-clover clover.xml",
        "mutation-test": "infection"
    }
}

4. CI

This repository ships a reusable CI workflow (.github/workflows/continuous-integration.yml) with six jobs: attributions (no AI attributions), mago (format/lint/analyze/guard, optional Rector), test (unit + optional integration, across a php x [lowest, locked, latest] matrix), an optional composer job (validate/audit), and two downstream jobs, codecov and mutation-test, both gated on test succeeding and both on by default. A consuming library's entire CI file becomes:

# .github/workflows/continuous-integration.yml
name: "Continuous Integration"

on:
  push:
  pull_request:

jobs:
  qa:
    uses: contenir/contenir-qa-tools/.github/workflows/continuous-integration.yml@0.1.x
    secrets: inherit
    with:
      php-versions: '["8.3", "8.4", "8.5"]'
      run-integration: true
      coverage-php-version: "8.4"
      min-msi: "100"
      min-covered-msi: "100"
      # Only when the tests shell out to system tools.
      apt-packages: "imagemagick"

Mutation testing needs infection/infection in require-dev, the mutation-test script above and an infection.json5.dist:

composer require --dev infection/infection
cp vendor/contenir/contenir-qa-tools/templates/infection.json5.dist .

An application tests only its lock file and usually needs extensions, a .env and sometimes a private dependency:

jobs:
  qa:
    uses: contenir/contenir-qa-tools/.github/workflows/continuous-integration.yml@0.1.x
    secrets:
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
      # Read-only deploy key for a private VCS dependency.
      SSH_PRIVATE_KEY: ${{ secrets.PRIVATE_DEPENDENCY_DEPLOY_KEY }}
    with:
      php-versions: '["8.3"]'
      dependency-versions: '["locked"]'
      php-extensions: "intl, pdo_mysql, gd"
      dotenv: |
        APP_ENV=testing
      enable-rector: true
      enable-composer-audit: true
      # Codecov and mutation testing are on by default. Remove this line once
      # the application runs Infection.
      enable-infection: false

Every input carries a description in the workflow file. See Workflow architecture for the full input list, the job graph, the DB-service mechanics, and the Codecov/Infection secrets wiring.

Documentation

  • Migration guide — moving a Contenir repository onto the shared toolchain.
  • Rule rationale — why the non-default choices are what they are.
  • Workflow architecture — job-split design for DB-backed integration tests, Codecov, and Infection.
  • Auto-dev — reusable workflow that triages issues and turns accepted ones into draft PRs.
  • llms.txt — condensed setup facts for coding agents.

License

BSD-3-Clause. See LICENSE.