Skip to content

Commit 38d96ae

Browse files
committed
Add tooling
1 parent f2268ed commit 38d96ae

16 files changed

Lines changed: 424 additions & 52 deletions

.github/workflows/ci.yml

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
name: CI
2+
on:
3+
pull_request: null
4+
push: null
5+
permissions:
6+
contents: read
7+
8+
jobs:
9+
dependency-validation:
10+
name: Dependency Validation
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 5
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: shivammathur/setup-php@v2
16+
with:
17+
php-version: 8.4
18+
tools: composer-normalize, composer-require-checker
19+
- uses: ramsey/composer-install@v3
20+
- run: composer validate --no-ansi --strict composer.json
21+
- run: composer-normalize --dry-run
22+
- run: composer-require-checker check
23+
coding-guidelines:
24+
name: Coding Guidelines
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 5
27+
steps:
28+
- uses: actions/checkout@v4
29+
- uses: shivammathur/setup-php@v2
30+
with:
31+
php-version: 8.3 # php-cs-fixer is not yet compatible with 8.4
32+
tools: php-cs-fixer
33+
- run: php-cs-fixer fix --dry-run --show-progress=dots --using-cache=no --verbose
34+
static-analysis:
35+
name: Static Analysis
36+
needs:
37+
- dependency-validation
38+
runs-on: ubuntu-latest
39+
timeout-minutes: 5
40+
steps:
41+
- uses: actions/checkout@v4
42+
- uses: shivammathur/setup-php@v2
43+
with:
44+
php-version: 8.4
45+
tools: phpstan
46+
- uses: "ramsey/composer-install@v3"
47+
- run: phpstan --memory-limit=512M --ansi --no-progress --error-format=github
48+
unit-tests:
49+
name: Unit Tests
50+
needs:
51+
- dependency-validation
52+
runs-on: ${{ matrix.os }}
53+
timeout-minutes: 5
54+
strategy:
55+
fail-fast: false
56+
matrix:
57+
os:
58+
- ubuntu-latest
59+
php-version:
60+
- "8.4"
61+
- "8.5"
62+
steps:
63+
- uses: actions/checkout@v4
64+
- uses: shivammathur/setup-php@v2
65+
with:
66+
php-version: ${{ matrix.php-version }}
67+
- uses: ramsey/composer-install@v3
68+
- run: vendor/bin/phpunit --log-junit junit.xml
69+
- if: ${{ !cancelled() }}
70+
uses: codecov/test-results-action@v1
71+
with:
72+
token: ${{ secrets.CODECOV_TOKEN }}
73+
coverage:
74+
name: Coverage
75+
needs:
76+
- dependency-validation
77+
runs-on: ubuntu-latest
78+
timeout-minutes: 5
79+
steps:
80+
- uses: actions/checkout@v4
81+
- uses: shivammathur/setup-php@v2
82+
with:
83+
php-version: 8.4
84+
- uses: ramsey/composer-install@v3
85+
- run: vendor/bin/phpunit --coverage-clover=coverage.xml
86+
- uses: codecov/codecov-action@v5
87+
env:
88+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
89+
mutation-tests:
90+
name: Mutation Tests
91+
needs:
92+
- dependency-validation
93+
runs-on: ubuntu-latest
94+
timeout-minutes: 5
95+
steps:
96+
- uses: actions/checkout@v4
97+
- uses: shivammathur/setup-php@v2
98+
with:
99+
php-version: 8.4
100+
tools: infection
101+
- uses: ramsey/composer-install@v3
102+
- run: infection --min-msi=65 --min-covered-msi=70 --threads=4
103+
env:
104+
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }}

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
vendor/
22
composer.lock
33
.phpunit.result.cache
4-
var/
4+
var/
5+
tools/
6+
coverage/

.php-cs-fixer.dist.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
if (!file_exists(__DIR__.'/src')) {
4+
exit(0);
5+
}
6+
7+
return (new PhpCsFixer\Config())
8+
// @see https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/pull/7777
9+
->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect())
10+
->setRules([
11+
'@PHP71Migration' => true,
12+
'@PHPUnit75Migration:risky' => true,
13+
'@Symfony' => true,
14+
'@Symfony:risky' => true,
15+
'protected_to_private' => false,
16+
])
17+
->setRiskyAllowed(true)
18+
->setFinder(
19+
(new PhpCsFixer\Finder())
20+
->in([__DIR__.'/src'])
21+
->append([__FILE__])
22+
)
23+
->setCacheFile('.php-cs-fixer.cache');

composer.json

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,44 @@
11
{
22
"name": "sourecode/timezone-bundle",
3-
"type": "symfony-bundle",
3+
"description": "A Symfony bundle for managing timezones in applications.",
44
"license": "MIT",
5-
"autoload": {
6-
"psr-4": {
7-
"SoureCode\\Bundle\\Timezone\\": "src/"
8-
}
9-
},
10-
"autoload-dev": {
11-
"psr-4": {
12-
"SoureCode\\Bundle\\Timezone\\Tests\\": "tests/",
13-
"App\\": "tests/app/src/"
14-
}
15-
},
5+
"type": "symfony-bundle",
166
"authors": [
177
{
188
"name": "chapterjason",
199
"email": "jason@sourecode.dev"
2010
}
2111
],
2212
"require": {
23-
"symfony/http-kernel": "^7.1",
13+
"php": ">=8.3",
14+
"symfony/clock": "^7.1",
2415
"symfony/config": "^7.1",
2516
"symfony/dependency-injection": "^7.1",
26-
"symfony/intl": "^7.1"
17+
"symfony/event-dispatcher": "^7.1",
18+
"symfony/http-foundation": "^7.1",
19+
"symfony/http-kernel": "^7.1",
20+
"symfony/intl": "^7.1",
21+
"twig/twig": "^3.21"
2722
},
2823
"require-dev": {
29-
"symfony/clock": "^7.1",
30-
"twig/twig": "^v3.2",
31-
"symfony/browser-kit": "^7.1",
3224
"nyholm/symfony-bundle-test": "^3.0",
3325
"phpunit/phpunit": "^9.5",
26+
"symfony/browser-kit": "^7.1",
27+
"symfony/monolog-bundle": "^3.10",
3428
"symfony/phpunit-bridge": "^7.1",
3529
"symfony/runtime": "^7.1"
3630
},
31+
"autoload": {
32+
"psr-4": {
33+
"SoureCode\\Bundle\\Timezone\\": "src/"
34+
}
35+
},
36+
"autoload-dev": {
37+
"psr-4": {
38+
"App\\": "tests/app/src/",
39+
"SoureCode\\Bundle\\Timezone\\Tests\\": "tests/"
40+
}
41+
},
3742
"config": {
3843
"allow-plugins": {
3944
"symfony/runtime": true

infection.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"source": {
3+
"directories": [
4+
"src"
5+
],
6+
"excludes": [
7+
"SoureCodeDoctrineExtensionBundle.php",
8+
"/Interface\\.php/"
9+
]
10+
},
11+
"timeout": 10,
12+
"logs": {
13+
"text": "coverage/infections.log",
14+
"html": "coverage/mutants.html",
15+
"stryker": {
16+
"badge": "master"
17+
}
18+
},
19+
"mutators": {
20+
"@default": true
21+
}
22+
}

phpstan-baseline.neon

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#^Parameter \#1 \$value of method SoureCode\\Bundle\\Timezone\\Manager\\TimezoneManager\:\:setTimezone\(\) expects DateTimeZone\|string, mixed given\.$#'
5+
identifier: argument.type
6+
count: 1
7+
path: src/EventListener/TimezoneListener.php
8+
9+
-
10+
message: '#^Method SoureCode\\Bundle\\Timezone\\Manager\\TimezoneManager\:\:__construct\(\) has parameter \$enabledTimezoneNames with no value type specified in iterable type array\.$#'
11+
identifier: missingType.iterableValue
12+
count: 1
13+
path: src/Manager/TimezoneManager.php
14+
15+
-
16+
message: '#^Method SoureCode\\Bundle\\Timezone\\Manager\\TimezoneManager\:\:getEnabledTimezoneNames\(\) return type has no value type specified in iterable type array\.$#'
17+
identifier: missingType.iterableValue
18+
count: 1
19+
path: src/Manager/TimezoneManager.php
20+
21+
-
22+
message: '#^Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\NodeDefinition\:\:fixXmlConfig\(\)\.$#'
23+
identifier: method.notFound
24+
count: 1
25+
path: src/SoureCodeTimezoneBundle.php
26+
27+
-
28+
message: '#^Cannot call method arrayNode\(\) on mixed\.$#'
29+
identifier: method.nonObject
30+
count: 1
31+
path: src/SoureCodeTimezoneBundle.php
32+
33+
-
34+
message: '#^Cannot call method children\(\) on mixed\.$#'
35+
identifier: method.nonObject
36+
count: 1
37+
path: src/SoureCodeTimezoneBundle.php
38+
39+
-
40+
message: '#^Cannot call method defaultValue\(\) on mixed\.$#'
41+
identifier: method.nonObject
42+
count: 1
43+
path: src/SoureCodeTimezoneBundle.php
44+
45+
-
46+
message: '#^Cannot call method end\(\) on mixed\.$#'
47+
identifier: method.nonObject
48+
count: 6
49+
path: src/SoureCodeTimezoneBundle.php
50+
51+
-
52+
message: '#^Cannot call method ifTrue\(\) on mixed\.$#'
53+
identifier: method.nonObject
54+
count: 2
55+
path: src/SoureCodeTimezoneBundle.php
56+
57+
-
58+
message: '#^Cannot call method info\(\) on mixed\.$#'
59+
identifier: method.nonObject
60+
count: 2
61+
path: src/SoureCodeTimezoneBundle.php
62+
63+
-
64+
message: '#^Cannot call method scalarNode\(\) on mixed\.$#'
65+
identifier: method.nonObject
66+
count: 1
67+
path: src/SoureCodeTimezoneBundle.php
68+
69+
-
70+
message: '#^Cannot call method scalarPrototype\(\) on mixed\.$#'
71+
identifier: method.nonObject
72+
count: 1
73+
path: src/SoureCodeTimezoneBundle.php
74+
75+
-
76+
message: '#^Cannot call method then\(\) on mixed\.$#'
77+
identifier: method.nonObject
78+
count: 1
79+
path: src/SoureCodeTimezoneBundle.php
80+
81+
-
82+
message: '#^Cannot call method thenInvalid\(\) on mixed\.$#'
83+
identifier: method.nonObject
84+
count: 1
85+
path: src/SoureCodeTimezoneBundle.php
86+
87+
-
88+
message: '#^Cannot call method validate\(\) on mixed\.$#'
89+
identifier: method.nonObject
90+
count: 2
91+
path: src/SoureCodeTimezoneBundle.php
92+
93+
-
94+
message: '#^Method SoureCode\\Bundle\\Timezone\\SoureCodeTimezoneBundle\:\:loadExtension\(\) has parameter \$config with no value type specified in iterable type array\.$#'
95+
identifier: missingType.iterableValue
96+
count: 1
97+
path: src/SoureCodeTimezoneBundle.php
98+
99+
-
100+
message: '#^Method SoureCode\\Bundle\\Timezone\\Tests\\BundleInitializationTest\:\:createKernel\(\) has parameter \$options with no value type specified in iterable type array\.$#'
101+
identifier: missingType.iterableValue
102+
count: 1
103+
path: tests/BundleInitializationTest.php
104+
105+
-
106+
message: '#^Method SoureCode\\Bundle\\Timezone\\Tests\\EventListener\\TimezoneListenerTest\:\:createKernel\(\) has parameter \$options with no value type specified in iterable type array\.$#'
107+
identifier: missingType.iterableValue
108+
count: 1
109+
path: tests/EventListener/TimezoneListenerTest.php
110+
111+
-
112+
message: '#^Method SoureCode\\Bundle\\Timezone\\Tests\\Manager\\TimezoneManagerTest\:\:createKernel\(\) has parameter \$options with no value type specified in iterable type array\.$#'
113+
identifier: missingType.iterableValue
114+
count: 1
115+
path: tests/Manager/TimezoneManagerTest.php
116+
117+
-
118+
message: '#^Method SoureCode\\Bundle\\Timezone\\Tests\\Manager\\TimezoneManagerTest\:\:testSomething\(\) has no return type specified\.$#'
119+
identifier: missingType.return
120+
count: 1
121+
path: tests/Manager/TimezoneManagerTest.php
122+
123+
-
124+
message: '#^Parameter \#1 \$value of method SoureCode\\Bundle\\Timezone\\Manager\\TimezoneManager\:\:setTimezone\(\) expects DateTimeZone\|string, float\|int\<min, \-1\>\|int\<1, max\>\|string\|true given\.$#'
125+
identifier: argument.type
126+
count: 1
127+
path: tests/app/src/Controller/TestController.php

phpstan.neon.dist

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
includes:
2+
- phpstan-baseline.neon
3+
parameters:
4+
editorUrl: '%%file%%:%%line%%'
5+
editorUrlTitle: ' '
6+
level: 10
7+
paths:
8+
- src
9+
- tests

scripts/baseline.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
CURRENT_DIRECTORY="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6+
PROJECT_DIRECTORY="$(dirname "$CURRENT_DIRECTORY")"
7+
8+
pushd "$PROJECT_DIRECTORY" >/dev/null
9+
10+
symfony composer update --no-interaction --no-progress --ansi
11+
symfony composer validate --no-ansi --strict composer.json
12+
13+
kyx phpstan analyse --memory-limit=512M --ansi --no-progress --error-format=table --generate-baseline=phpstan-baseline.neon
14+
15+
popd >/dev/null

0 commit comments

Comments
 (0)