Files
XC_VM/.github/workflows/ci.yml
T
Divarion_D 734f4751c9 chore(tests): move phpunit.phar into tests/ and repoint references
The committed PHPUnit runner lived at tools/.bin/phpunit.phar, away from
the suite it runs. Move it next to the tests it drives —
tests/phpunit.phar — and update every invocation to
`php tests/phpunit.phar -c tests/phpunit.xml.dist`:

- CI workflows (ci, build-release, build_pre-release) + the ci.yml header,
- CLAUDE.md, CONTRIBUTING.md, tools/README.md, the qa-lead-reviewer agent,
- docs/en (dev-workflow, updates_checklist, phpunit-phar, refactoring).

docs/ru is generated from docs/en (make docs-translate) and is left for
the next regeneration, per the docs workflow.
2026-09-13 22:04:10 +03:00

169 lines
5.5 KiB
YAML

name: CI
# Quality gate: runs on pushes to main and on every pull request.
# Tests run via the committed PHAR (tests/phpunit.phar). Class loading uses
# the committed Composer PSR-4 autoloader (src/vendor/) first, with the legacy
# src/autoload.php scanner as an end-of-queue fallback. The deploy path ships
# vendor/ as-is and never runs `composer install`.
# `push` is scoped to main so a commit on a PR branch does NOT run the workflow
# twice (once for push, once for pull_request); PR branches are covered by the
# pull_request trigger. The concurrency group cancels superseded in-flight runs
# on rapid re-pushes / new commits to the same ref.
#
# `paths-ignore` (blocklist, NOT an allowlist) skips CI only when EVERY changed
# file is documentation. Any commit that also touches code still runs the full
# gate — so this can never silently disable checks for a real source change. Do
# not switch this to a `src/**` allowlist: the result also depends on tools/,
# tests/, Makefile, composer.json/lock, build/phpcs.xml.dist and build/phpstan.dist.neon.
on:
push:
branches: [main]
paths-ignore:
- 'docs/**'
- '**/*.md'
- 'LICENSE'
pull_request:
paths-ignore:
- 'docs/**'
- '**/*.md'
- 'LICENSE'
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
phpstan:
name: PHPStan (static analysis)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
# Matches phpVersion (80300) the analysis targets.
php-version: '8.3'
coverage: none
tools: composer:v2
# The committed src/vendor/ is production-only; PHPStan is a require-dev
# tool, so install it here (from the committed lock — reproducible).
- name: Install dev dependencies
run: composer install --no-interaction --working-dir=src
# Analyses against the committed baseline — fails only on NEW issues.
- name: Run PHPStan
run: make phpstan
code-style:
name: Code Style (phpcs + Slevomat)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
coverage: none
tools: composer:v2
# phpcs + Slevomat are require-dev tools; the committed src/vendor/ is
# production-only, so install them here (from the committed lock). The
# phpcodesniffer-composer-installer plugin is allow-listed in composer.json.
- name: Install dev dependencies
run: composer install --no-interaction --working-dir=src
# Narrow ruleset: import / namespace hygiene only (see build/phpcs.xml.dist).
# phpcs exits non-zero on any violation.
- name: Run phpcs
run: make cs
psr4-gates:
name: PSR-4 Regression Gates
runs-on: ubuntu-latest
steps:
- name: Checkout
# Full history not needed, but git ls-files requires the working tree.
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
coverage: none
# check-procedural-use: procedural/view files must import every migrated
# class they use (top-of-file `use`; PHP imports are positional).
# verify-lb-archive: the LoadBalancer archive must exclude privileged code
# (security blocker 1 — silent rm misses after the PascalCase rename).
- name: Run PSR-4 gates
run: make gates
composer-audit:
name: Composer Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
coverage: none
tools: composer:v2
# Audits the committed install set (src/vendor/composer/installed.json)
# against the Packagist advisory database. Does NOT run `composer install`
# (vendor/ is committed and shipped) and does NOT use --locked
# (composer.lock is gitignored, never committed). A no-op while every
# dependency is path-mapped/vendored without metadata, but gates real
# installed packages the moment any are added.
- name: Composer audit
run: |
count=$(php -r '$f="src/vendor/composer/installed.json";$d=is_file($f)?json_decode(file_get_contents($f),true):[];echo is_array($d["packages"]??null)?count($d["packages"]):0;')
if [ "$count" -eq 0 ]; then
echo "No installed Composer packages — nothing to audit."
else
composer audit --no-interaction --working-dir=src
fi
test:
name: PHPUnit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
coverage: pcov
- name: Run unit tests
run: php tests/phpunit.phar -c tests/phpunit.xml.dist
- name: Coverage report
run: |
php tests/phpunit.phar -c tests/phpunit.xml.dist \
--coverage-text \
--coverage-clover coverage.xml
continue-on-error: true
- name: Upload coverage artifact
if: always()
uses: actions/upload-artifact@v7
with:
name: coverage
path: coverage.xml
if-no-files-found: ignore