Quality Assurance
This document describes the quality assurance tools and processes used in the OpenRegister application and all Conduction Nextcloud apps.
Overview
We use two main tools for quality assurance:
- PHPQA - Generates comprehensive quality reports and metrics
- GrumPHP - Enforces quality standards through git hooks
PHPQA - PHP Quality Analyzer
PHPQA is our primary tool for analyzing code quality. It runs multiple analyzers and generates a comprehensive report showing the health of our codebase.
What PHPQA Checks
PHPQA runs the following analyzers:
- PHPCS (PHP CodeSniffer) - Coding standards compliance
- PHPMD (PHP Mess Detector) - Code smells and potential issues
- PHPLoc - Lines of code and project size metrics
- PHPMetrics - Complexity, maintainability, and quality metrics
- PHPCPD (Copy/Paste Detector) - Duplicate code detection
- Parallel Lint - PHP syntax checking
Running PHPQA
Quick Check
composer phpqa
or
composer qa:check
This generates reports in the 'phpqa' directory.
Full Analysis
For a complete analysis with all tools:
composer qa:full
CI/CD Mode
For continuous integration environments:
composer phpqa:ci
This mode fails the build if quality thresholds are not met.
Understanding PHPQA Reports
After running PHPQA, you will find several reports:
HTML Report
Open 'phpqa/phpqa-offline.html' in your browser for an interactive dashboard showing:
- Overall quality score
- Issues per analyzer
- Trends over time (if run multiple times)
- Detailed breakdown by file
JSON Report
The file 'phpqa/phpqa.json' contains machine-readable metrics useful for:
- CI/CD pipelines
- Custom reporting tools
- Tracking quality over time
PHPMetrics Report
The 'phpqa/phpmetrics' directory contains detailed complexity metrics:
- Cyclomatic complexity per method
- Maintainability index
- Coupling and cohesion metrics
- Dependency graphs
Quality Thresholds
We aim for the following quality standards:
| Metric | Target | Critical |
|---|---|---|
| PHPCS Errors | 0 | Must fix |
| PHPMD Violations | < 10 per file | Review critical |
| Code Duplication | < 5% | < 10% |
| Cyclomatic Complexity | < 10 per method | < 20 per method |
| Maintainability Index | > 85 | > 70 |
When to Run PHPQA
PHPQA should be run:
✅ After implementing new features ✅ After refactoring code ✅ After fixing bugs ✅ Before marking todos as complete ✅ Before requesting code review ✅ Before merging to development or main branches
Addressing PHPQA Issues
When PHPQA finds issues:
- Review the HTML report to understand the problems
- Prioritize critical issues (PHPCS errors, high complexity)
- Fix coding standards automatically with 'composer cs:fix'
- Refactor complex code to improve maintainability
- Reduce duplication by extracting common code
- Re-run PHPQA to verify fixes
GrumPHP - Git Hooks for Quality
GrumPHP automatically runs quality checks when you commit or push code, preventing bad code from reaching the repository.
What GrumPHP Checks
Pre-Commit Hook
Runs on every 'git commit':
- PHP Lint - Syntax errors
- PHPCS - Coding standards
- JSON Lint - JSON file validation
- YAML Lint - YAML file validation
- Composer - Composer.json validation
Pre-Push Hook
Runs on every 'git push':
- All pre-commit checks
- PHPMD - Code quality issues
- PHPUnit - Unit tests
Setting Up GrumPHP
Initialize Git Hooks
After installing dependencies, initialize GrumPHP:
composer grumphp:init
This creates git hooks in '.git/hooks/' directory.
Remove Git Hooks
If needed, remove GrumPHP hooks:
composer grumphp:deinit
Running GrumPHP Manually
Test what GrumPHP would check without committing:
composer grumphp
Bypassing GrumPHP (Emergency Only)
In rare emergencies, you can bypass GrumPHP:
git commit --no-verify
⚠️ Warning: Only bypass GrumPHP when absolutely necessary. Always fix issues properly rather than bypassing checks.
Understanding GrumPHP Errors
When GrumPHP fails, it shows:
- Which task failed (e.g., phpcs, phpmd, phpunit)
- Error details from that tool
- Files that caused the failure
Fix the errors and commit again. The hooks will run automatically.
Quality Workflow
Follow this workflow for maintaining high code quality:
Step-by-Step Guide
-
Write or modify code
- Follow coding standards
- Add docblocks and type hints
- Write inline comments
-
Auto-fix coding standards
composer cs:fix -
Check code quality
composer phpqa -
Review PHPQA report
- Open 'phpqa/phpqa-offline.html'
- Address critical issues
- Refactor complex code
-
Run tests
composer test:unit -
Commit changes
git add .
git commit -m "feat: description of changes"- GrumPHP runs pre-commit checks automatically
- Fix any issues that are found
-
Push changes
git push- GrumPHP runs pre-push checks automatically
- Fix any issues that are found
Configuration Files
.phpqa.yml
PHPQA configuration file that defines:
- Directories to analyze
- Tools to run
- Report formats
- Thresholds
Located at: '.phpqa.yml'
grumphp.yml
GrumPHP configuration file that defines:
- Git hooks to install
- Tasks to run on each hook
- Task configuration
- Test suites
Located at: 'grumphp.yml'
phpcs.xml
PHP CodeSniffer ruleset defining coding standards.
Located at: 'phpcs.xml'
phpmd.xml
PHP Mess Detector ruleset defining code quality rules.
Located at: 'phpmd.xml'
CI/CD Integration
We use GitHub Actions workflows to enforce quality standards and prevent low-quality code from being merged.
Automated Workflows
Our repository includes three main quality workflows:
1. Quality Check Workflow
File: '.github/workflows/quality-check.yml'
Runs on every push and pull request. Performs:
- PHPCS (Coding Standards) analysis
- PHPMD (Mess Detection) analysis
- PHPQA (Full Quality Analysis)
- Generates and uploads quality reports
- Posts results as PR comments
Quality Requirements:
- PHPCS Errors: Must be 0
- PHPMD Score: Should be ≥ 80%
- Overall Quality Score: Must be ≥ 90%
2. Tests Workflow
File: '.github/workflows/tests.yml'
Runs on every push and pull request. Performs:
- Unit tests on PHP 8.1, 8.2, and 8.3
- Integration tests (if Nextcloud environment available)
- Code coverage analysis
- Posts coverage report as PR comment
Coverage Requirements:
- Minimum: 75% (warning if below)
- Recommended: 85%
3. Branch Protection Workflow
File: '.github/workflows/branch-protection.yml'
Runs on pull requests to protected branches. This is the quality gate that blocks merges.
Quality Gate Checks:
| Check | Requirement | Blocks Merge |
|---|---|---|
| PHP Syntax | No errors | Yes |
| PHPCS Errors | Must be 0 | Yes |
| PHPMD Violations | Max 50 | Yes |
| Overall Quality Score | ≥ 90% | Yes |
| Unit Tests | Must pass | No (warning only) |
Quality Score Calculation:
The overall quality score is calculated as:
Score = 100 - (PHPCS_Errors × 2) - (PHPMD_Violations × 0.1)
Examples:
- 0 PHPCS errors, 0 PHPMD violations = 100%
- 0 PHPCS errors, 50 PHPMD violations = 95%
- 1 PHPCS error, 0 PHPMD violations = 98%
- 0 PHPCS errors, 100 PHPMD violations = 90%
- 1 PHPCS error, 100 PHPMD violations = 88% (FAIL)
Setting Up Branch Protection
To enable quality gates on GitHub:
- Go to Settings → Branches → Add rule
- Branch name pattern: 'main', 'master', or 'development'
- Enable Require status checks to pass before merging
- Select required checks:
- 'Quality Gate Check'
- 'Code Quality Analysis'
- 'PHPUnit Tests' (optional)
- Enable Require branches to be up to date before merging
- Save changes
Workflow Integration Diagram
Understanding Workflow Results
Success Example
When a PR meets all requirements:
🚦 Quality Gate Status: ✅ PASSED
| Check | Status | Details |
|-------|--------|---------|
| PHP Syntax | ✅ PASS | All PHP files are valid |
| Coding Standards (PHPCS) | ✅ PASS | Errors: 0 (must be 0) |
| Code Quality (PHPMD) | ✅ PASS | Violations: 12 (max 50) |
| Overall Quality Score | ✅ PASS | Score: 98.8% (min 90%) |
| Unit Tests | ✅ PASS | Test suite passed |
✅ All quality checks passed! This PR meets the requirements for merging.
Failure Example
When a PR does not meet requirements:
🚦 Quality Gate Status: ❌ FAILED
| Check | Status | Details |
|-------|--------|---------|
| PHP Syntax | ✅ PASS | All PHP files are valid |
| Coding Standards (PHPCS) | ❌ FAIL | Errors: 5 (must be 0) |
| Code Quality (PHPMD) | ✅ PASS | Violations: 23 (max 50) |
| Overall Quality Score | ❌ FAIL | Score: 87.7% (min 90%) |
| Unit Tests | ✅ PASS | Test suite passed |
❌ Quality gate failed. Please address the issues above before merging.
Required actions:
- Fix PHPCS errors (run 'composer cs:fix')
- Improve overall code quality to reach 90% score
Local Testing Before Push
Always test locally before pushing to avoid failed workflows:
# 1. Fix coding standards
composer cs:fix
# 2. Run quality analysis
composer phpqa
# 3. Run tests
composer test:unit
# 4. Review quality report
open phpqa/phpqa-offline.html
Bypassing Workflows (Not Recommended)
Workflows cannot be bypassed for pull requests to protected branches. This is intentional to maintain code quality.
If you need to merge urgent fixes:
- Create a hotfix branch from main/master
- Fix the urgent issue
- Ensure quality checks pass
- Merge with fast-forward (if branch protection allows)
Alternatively, repository admins can:
- Temporarily disable branch protection (not recommended)
- Override required status checks (requires admin privileges)
Viewing Workflow Artifacts
Each workflow run generates artifacts:
- Go to Actions tab on GitHub
- Click on the workflow run
- Scroll to Artifacts section
- Download:
- 'phpqa-reports' - Full quality analysis
- 'coverage-report' - Test coverage data
- 'quality-gate-reports' - Quality gate details
Troubleshooting Workflow Failures
Workflow Fails on Dependencies
If 'composer install' fails:
- Check 'composer.json' syntax
- Ensure 'composer.lock' is committed
- Verify PHP version compatibility
Workflow Fails on PHPCS
If PHPCS finds errors:
# Locally fix issues
composer cs:fix
# Verify fixes
composer cs:check
# Commit and push
git add .
git commit -m "fix: coding standards"
git push
Workflow Fails on Quality Score
If overall score is below 90%:
- Review PHPQA report locally
- Fix critical issues first
- Refactor complex code
- Reduce code duplication
- Re-run PHPQA to verify improvements
Workflow Times Out
If workflows take too long:
- Check for infinite loops in tests
- Reduce parallel processes in '.phpqa.yml'
- Optimize heavy analyzers
For AI Agents
When you are an AI agent working on this codebase:
Mandatory Steps
- Always run PHPQA after completing code changes
- Review the generated report at 'phpqa/phpqa-offline.html'
- Address critical issues before marking work complete
- Run tests to ensure functionality
- Document changes in the appropriate documentation files
Quality Commands Reference
# Fix coding standards automatically
composer cs:fix
# Check code quality
composer phpqa
# Check quality with full analysis
composer qa:full
# Run unit tests
composer test:unit
# Run all checks (lint, phpcs, psalm, tests)
composer check
# Run full checks (includes phpstan)
composer check:full
# Run strict checks (includes phpmd)
composer check:strict
Quality Checklist
Before completing a task:
- Code follows PSR-12 coding standards
- All methods have docblocks
- All methods have type hints and return types
- Inline comments explain complex logic
- PHPQA report shows no critical issues
- PHPUnit tests pass
- Code duplication is minimal
- Cyclomatic complexity is acceptable
- Documentation is updated
Interpreting Quality Scores
When reviewing PHPQA output:
-
PHPCS Score: 1000 = Perfect (0 errors, 0 warnings)
-
PHPCS Score: 950+ = Good (minor warnings only)
-
PHPCS Score: < 900 = Needs improvement (errors present)
-
PHPMD Score: 1000 = Perfect (0 violations)
-
PHPMD Score: 900+ = Good (minor issues)
-
PHPMD Score: < 800 = Needs refactoring
-
Code Coverage: 100% = All code tested
-
Code Coverage: 75%+ = Good coverage (our minimum)
-
Code Coverage: < 75% = More tests needed
Troubleshooting
GrumPHP Not Running
If GrumPHP hooks don't run:
-
Check hooks are installed:
ls -la .git/hooks/ -
Reinitialize:
composer grumphp:deinit
composer grumphp:init
PHPQA Fails to Run
If PHPQA fails:
-
Ensure dependencies are installed:
composer install -
Check PHP version:
php -v(Requires PHP 8.1+)
-
Clear previous reports:
rm -rf phpqa/
Out of Memory Errors
If analyzers run out of memory:
php -d memory_limit=1G vendor/bin/phpqa --report
Best Practices
- Run PHPQA regularly - Don't wait for CI/CD to catch issues
- Fix issues immediately - Don't let quality debt accumulate
- Use auto-fixers - Let tools fix simple issues automatically
- Understand the rules - Know why rules exist, don't just follow blindly
- Refactor proactively - Improve code quality continuously
- Test thoroughly - Quality isn't just about standards, it's about correctness
- Document changes - Keep documentation in sync with code