Skip to content

Commit 9fd35df

Browse files
authored
Modernize for PHP 8.4+, Symfony 6.4/7.4/8.1+, PHPUnit 12 (#238)
* Modernize for PHP 8.4+, Symfony 6.4/7.4/8.1+, PHPUnit 12 - composer.json: require php ^8.4, symfony/process ^6.4 || ^7.4 || ^8.1, bump phpunit/phpunit to ^12.0 and psr/log to ^3.0, drop phpspec/prophecy-phpunit (its one use site now uses native PHPUnit mocks) - CI matrix now runs PHP 8.4/8.5 plus a prefer-lowest job; phpunit.xml.dist rewritten for the PHPUnit 12 schema - README/CONTRIBUTING updated for the new PHP baseline and a couple of stale references - Full property/parameter/return type coverage across src/, with readonly applied wherever a property is genuinely write-once (mostly via constructor promotion) - Classes marked final wherever nothing extends them, and final readonly where every property is readonly; left plain where they're actually extended or inherit mutable state (Revision, Reference, ParserBase, CommitParser, Exception\RuntimeException) - Tests converted from doc-comment metadata (@dataProvider/@before/@after) to PHPUnit 12 attributes, since PHPUnit 12 no longer reads the old annotations; AbstractTest renamed to AbstractTestCase so PHPUnit doesn't mistake it for a test case via the *Test.php glob - Fixed bugs surfaced along the way: Log's ReferenceNotFoundException call silently dropped the previous exception (constructor didn't accept it); DiffTest called restore_exception_handler() instead of restore_error_handler(), leaking handlers between tests; a dead @dataProvider on ReferenceTest::testIsBranchMergedToMaster wastefully cloned repos it never used * Drop StyleCI references and README badges StyleCI never had a .styleci.yml or a workflow step in this repo — it only ran as a separate GitHub App integration. Removing it here means dropping every textual reference; actually uninstalling the app is a repo-settings action outside of this checkout. * Add php-cs-fixer, PHPStan and Castor tooling Mirrors JoliCode's own JoliNotif project setup: - php-cs-fixer and phpstan each live in tools/<name>/ with their own isolated composer.json/lock (avoids dependency conflicts with the library's own require-dev), wired together via a root castor.php that imports each tool's own castor.php. `castor install`, `castor cs`, `castor phpstan` and `castor phpunit` all work end to end. - .php-cs-fixer.php: @PHP84Migration + @PhpCsFixer + @symfony(:risky), gitlib's own license header enforced via header_comment. Ran it for real across the codebase (58 files reformatted, all mechanical); it also filled in the license header on two files that were missing it entirely (RuntimeException.php, tests/bootstrap.php). - phpstan.neon: level 9 on src/. Fixed the ~20 findings that were real bugs or design smells rather than annotation gaps: - Reference\Tag::getCommit() could pass an undefined $commitHash to getCommit() when show-ref returned no matching row - Repository::getDiff(null) and Log::getCommits()'s catch block would fatal-error calling a method on null on a reachable path (a Log built with no revision filter) - Repository's $gitDir/$workingDir were readonly-assigned outside the constructor; moved to a static resolveDir() helper - Repository's single $objects cache (typed Commit|Tree|Blob) split into three properly-typed caches - RevisionList/Tree array-shape narrowing fixed by restructuring the loops that build them - ReferenceBag::update() and a new getAs() helper made generic so createBranch()/getTag()/etc. return their real narrow type - CommitReference was missing a getHash() getter entirely - Blob::getMimetype() honestly typed string|false (finfo::buffer() can fail) The remaining ~94 findings are baselined in phpstan-baseline.neon: mostly Commit/Reference\Tag's untyped getData(): mixed internals, and Repository::run()'s ?string return propagating into code that assumes a string. Fixing those properly means redesigning that data-caching layer or auditing every run() call site for the debug=false null case, which is bigger than "add phpstan". - CI: check-cs and phpstan jobs pinned to PHP 8.4 (our floor) using castor-php/setup-castor@v1.1.0. - CONTRIBUTING.md: Castor install step, "Standard code" and "Static analysis" sections. * Remove redundant readonly on properties of readonly classes A class-level `readonly` modifier already makes every declared property readonly, so repeating the keyword on each promoted constructor property was dead weight.
1 parent c1476cb commit 9fd35df

72 files changed

Lines changed: 5067 additions & 1996 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/CONTRIBUTING.md‎

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,23 @@ We accept contributions via pull requests on GitHub. Please review these guideli
66

77
## Guidelines
88

9-
* Please follow the [PSR-12 Coding Style Guide](https://www.php-fig.org/psr/psr-12/), enforced by [StyleCI](https://styleci.io/).
9+
* Please follow the [PSR-12 Coding Style Guide](https://www.php-fig.org/psr/psr-12/).
1010
* Ensure that the current tests pass, and if you've added something new, add the tests where relevant.
1111
* Send a coherent commit history, making sure each commit in your pull request is meaningful.
1212
* You may need to [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) to avoid merge conflicts.
1313
* If you are changing or adding to the behaviour or public API, you may need to update the docs.
1414
* Please remember that we follow [Semantic Versioning](https://semver.org/).
1515

16+
You will need [Castor](https://castor.jolicode.com/) to run the tests, fix CS
17+
violations and run the static analysis. See [Castor's documentation](https://castor.jolicode.com/getting-started/installation/)
18+
for installation instructions.
19+
20+
To install all the dependencies and tools, run:
21+
22+
```bash
23+
$ castor install
24+
```
25+
1626
## Running Tests
1727

1828
First, install the dependencies using [Composer](https://getcomposer.org/):
@@ -27,6 +37,23 @@ Then run [PHPUnit](https://phpunit.de/):
2737
$ vendor/bin/phpunit
2838
```
2939

30-
* A script `test-git-version.sh` is available in repository to test gitlib against many git versions.
40+
* A script `test-git-versions.sh` is available in repository to test gitlib against many git versions.
3141
* The tests will be automatically run by [GitHub Actions](https://github.com/features/actions) against pull requests.
32-
* We also have [StyleCI](https://styleci.io/) set up to automatically fix any code style issues.
42+
43+
## Standard code
44+
45+
Use PHP-CS-Fixer to make your code compliant with gitlib's coding standards:
46+
47+
```bash
48+
$ castor cs
49+
```
50+
51+
## Static analysis
52+
53+
Use PHPStan to ensure the code is free of errors:
54+
55+
```bash
56+
$ castor phpstan
57+
```
58+
59+
Both checks run automatically via GitHub Actions against pull requests.

‎.github/workflows/tests.yml‎

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,56 @@ on:
66
pull_request:
77

88
jobs:
9+
check-cs:
10+
name: Check Coding Standards
11+
runs-on: ubuntu-24.04
12+
steps:
13+
- name: Checkout Code
14+
uses: actions/checkout@v4
15+
16+
- name: Setup PHP
17+
uses: shivammathur/setup-php@v2
18+
with:
19+
php-version: '8.4'
20+
21+
- name: Setup Castor
22+
uses: castor-php/setup-castor@2a495b8c91f00be6768ad8a040ba8634c797d386 # v1.1.0
23+
24+
- name: Run CS check
25+
run: castor cs --dry-run
26+
27+
phpstan:
28+
name: Static Analysis
29+
runs-on: ubuntu-24.04
30+
steps:
31+
- name: Checkout Code
32+
uses: actions/checkout@v4
33+
34+
- name: Setup PHP
35+
uses: shivammathur/setup-php@v2
36+
with:
37+
php-version: '8.4'
38+
39+
- name: Setup Castor
40+
uses: castor-php/setup-castor@2a495b8c91f00be6768ad8a040ba8634c797d386 # v1.1.0
41+
42+
- name: Install dependencies
43+
run: castor install
44+
45+
- name: Run PHPStan
46+
run: castor phpstan
47+
948
tests:
1049
name: Test PHP ${{ matrix.php }} ${{ matrix.name }}
1150
runs-on: ubuntu-24.04
1251
strategy:
1352
fail-fast: false
1453
matrix:
15-
php: ['8.1', '8.2', '8.3', '8.4']
54+
php: ['8.4', '8.5']
1655
composer-flags: ['']
1756
name: ['']
1857
include:
19-
- php: '8.0'
58+
- php: '8.4'
2059
composer-flags: '--prefer-lowest'
2160
name: '(prefer lowest dependencies)'
2261

@@ -32,6 +71,9 @@ jobs:
3271
- name: Setup Problem Matchers
3372
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
3473

74+
- name: Validate composer.json
75+
run: composer validate --strict
76+
3577
- name: Install Composer dependencies
3678
run: |
3779
composer update --prefer-dist --no-interaction ${{ matrix.composer-flags }}

‎.gitignore‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
/.phpunit.result.cache
1+
/.castor.stub.php
2+
/.php-cs-fixer.cache
3+
/.phpunit.cache
24
/composer.lock
35
/phpunit.xml
6+
/var/
47
/vendor

‎.php-cs-fixer.php‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Gitonomy.
5+
*
6+
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
7+
* (c) Julien DIDIER <genzo.wm@gmail.com>
8+
*
9+
* This source file is subject to the MIT license that is bundled
10+
* with this source code in the file LICENSE.
11+
*/
12+
13+
$fileHeaderComment = <<<'EOF'
14+
This file is part of Gitonomy.
15+
16+
(c) Alexandre Salomé <alexandre.salome@gmail.com>
17+
(c) Julien DIDIER <genzo.wm@gmail.com>
18+
19+
This source file is subject to the MIT license that is bundled
20+
with this source code in the file LICENSE.
21+
EOF;
22+
23+
$finder = PhpCsFixer\Finder::create()
24+
->in(__DIR__)
25+
->append([
26+
__FILE__,
27+
'castor.php',
28+
])
29+
->notPath('var')
30+
;
31+
32+
return new PhpCsFixer\Config()
33+
->setRiskyAllowed(true)
34+
->setUnsupportedPhpVersionAllowed(true)
35+
->setRules([
36+
'@PHP84Migration' => true,
37+
'@PhpCsFixer' => true,
38+
'@Symfony' => true,
39+
'@Symfony:risky' => true,
40+
'php_unit_internal_class' => false, // From @PhpCsFixer but we don't want it
41+
'php_unit_test_class_requires_covers' => false, // From @PhpCsFixer but we don't want it
42+
'phpdoc_add_missing_param_annotation' => false, // From @PhpCsFixer but we don't want it
43+
'header_comment' => ['header' => $fileHeaderComment],
44+
'ordered_class_elements' => true, // Symfony(PSR12) override the default value, but we don't want
45+
'blank_line_before_statement' => true, // Symfony(PSR12) override the default value, but we don't want
46+
])
47+
->setFinder($finder)
48+
;

‎README.md‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
Gitlib for Gitonomy
22
===================
33

4-
[![Build Status](https://img.shields.io/github/actions/workflow/status/gitonomy/gitlib/tests.yml?label=Tests&style=flat-square&branch=1.3)](https://github.com/gitonomy/gitlib/actions?query=workflow%3ATests+branch%3A1.3)
5-
[![StyleCI](https://github.styleci.io/repos/5709354/shield?branch=1.3)](https://github.styleci.io/repos/5709354?branch=1.3)
6-
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](https://opensource.org/licenses/MIT)
7-
[![Downloads](https://img.shields.io/packagist/dt/gitonomy/gitlib?style=flat-square)](https://packagist.org/packages/gitonomy/gitlib)
8-
9-
This library provides methods to access Git repository from PHP 5.6+.
4+
This library provides methods to access Git repository from PHP 8.4+.
105

116
It makes shell calls, which makes it less performant than any solution.
127

‎castor.php‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Gitonomy.
5+
*
6+
* (c) Alexandre Salomé <alexandre.salome@gmail.com>
7+
* (c) Julien DIDIER <genzo.wm@gmail.com>
8+
*
9+
* This source file is subject to the MIT license that is bundled
10+
* with this source code in the file LICENSE.
11+
*/
12+
13+
use Castor\Attribute\AsRawTokens;
14+
use Castor\Attribute\AsTask;
15+
16+
use function Castor\guard_min_version;
17+
use function Castor\import;
18+
use function Castor\run;
19+
20+
guard_min_version('1.0.0');
21+
22+
import(__DIR__.'/tools/php-cs-fixer/castor.php');
23+
import(__DIR__.'/tools/phpstan/castor.php');
24+
25+
#[AsTask(description: 'Install dependencies')]
26+
function install(): void
27+
{
28+
run(['composer', 'install']);
29+
qa\cs\install();
30+
qa\phpstan\install();
31+
}
32+
33+
#[AsTask(description: 'Run PHPUnit', ignoreValidationErrors: true)]
34+
function phpunit(#[AsRawTokens] array $rawTokens): void
35+
{
36+
run(['vendor/bin/phpunit', ...$rawTokens]);
37+
}

‎composer.json‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,15 @@
3535
}
3636
},
3737
"require": {
38-
"php": "^8.0",
38+
"php": "^8.4",
3939
"ext-pcre": "*",
4040
"symfony/polyfill-mbstring": "^1.7",
41-
"symfony/process": "^5.4 || ^6.0 || ^7.0 || ^8.0"
41+
"symfony/process": "^6.4 || ^7.4 || ^8.1"
4242
},
4343
"require-dev": {
4444
"ext-fileinfo": "*",
45-
"phpspec/prophecy-phpunit": "^2.0",
46-
"phpunit/phpunit": "^7.5.20 || ^8.5.20 || ^9.5.9",
47-
"psr/log": "^1.0"
45+
"phpunit/phpunit": "^12.0",
46+
"psr/log": "^3.0"
4847
},
4948
"config": {
5049
"preferred-install": "dist",

0 commit comments

Comments
 (0)