-
Notifications
You must be signed in to change notification settings - Fork 0
189 lines (161 loc) · 7.91 KB
/
Copy pathci.yml
File metadata and controls
189 lines (161 loc) · 7.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
check:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ['8.4', '8.5']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@728c6c6b8cf02c2e48117716a91ee48313958a19 # v2
with:
php-version: ${{ matrix.php }}
coverage: pcov
tools: composer:v2
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-interaction
- name: Audit dependencies
run: composer audit
- name: Format check
run: composer format:check
- name: Static analysis (self)
run: composer phpstan
- name: Tests with coverage
run: composer test:coverage
- name: Coverage threshold gate
run: composer coverage:check
- name: Upload coverage report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: clover-php-${{ matrix.php }}
path: build/logs/clover.xml
retention-days: 14
if-no-files-found: ignore
- name: Mutation testing
run: composer mutation:ci
- name: Upload mutation report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: infection-php-${{ matrix.php }}
path: build/logs/infection.*
retention-days: 14
if-no-files-found: ignore
# WR-0854: `check` installs dev dependencies, and `autoload-dev` classmaps
# `tests/Fixtures/` — where hand-written `Illuminate\Http\*` and
# `Symfony\…\HttpKernel` stubs live. Six rules name those FQCNs as analysis
# anchors, so the fixtures were silently satisfying `src/`: `composer
# phpstan` was green only against a tree no consumer ever installs, and
# reported 7 `class.notFound` the moment the dev autoloader was removed.
# This leg analyses the package exactly as a consumer receives it. The
# anchors are declared for analysis in `stubs/analysis-anchors.php` (wired
# via `scanFiles`), so a NEW anchor added without a declaration fails here.
check-production-tree:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup PHP 8.4
uses: shivammathur/setup-php@728c6c6b8cf02c2e48117716a91ee48313958a19 # v2
with:
php-version: '8.4'
coverage: none
tools: composer:v2
- name: Install production dependencies only
run: composer install --no-dev --prefer-dist --no-progress --no-interaction
# Positive control for the leg above it. Without this the job reports
# a clean analysis both when the production tree is genuinely sound
# and when the fixture stubs have crept back into the runtime
# autoloader — the exact failure it exists to catch. `Request` is a
# fixture-declared anchor: reachable here means dev autoloading is
# in play and the analysis below is measuring the wrong tree.
- name: Assert the dev fixture stubs are NOT autoloadable
run: |
set -euo pipefail
php -r 'require "vendor/autoload.php";
if (class_exists("Illuminate\\Http\\Request")) {
fwrite(STDERR, "Illuminate\\Http\\Request is autoloadable on a --no-dev install: the dev fixture stubs are reachable, so the analysis below is not measuring the production tree.\n");
exit(1);
}'
- name: Static analysis (production tree)
run: composer phpstan
# WR-0855: `check` resolves illuminate/* to the highest satisfying release, so
# it only ever exercised Laravel 13 — whose ConnectionInterface::transaction()
# carries `@return TReturn` and hides whether
# ConnectionTransactionReturnTypeExtension still works. Laravel 12 annotates
# `@return mixed`, the shape the extension exists for. Cheap steps only:
# coverage, mutation and audit stay on `check`. Laravel 12 is the DECLARED
# FLOOR (WR-0860 dropped `^11.0`), so this leg now tests the real lower
# bound rather than a middle major — pinning here and pinning the manifest
# floor are the same thing, and must stay that way.
check-lowest-laravel:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ['8.4', '8.5']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@728c6c6b8cf02c2e48117716a91ee48313958a19 # v2
with:
php-version: ${{ matrix.php }}
coverage: none
tools: composer:v2
- name: Pin illuminate/* to ^12.0
run: >
composer require --no-update --no-interaction
illuminate/database:^12.0
illuminate/contracts:^12.0
illuminate/cache:^12.0
illuminate/filesystem:^12.0
illuminate/log:^12.0
illuminate/mail:^12.0
- name: Install dependencies
run: composer update --prefer-dist --no-progress --no-interaction --with-all-dependencies
- name: Assert the resolved major is 12
run: composer show illuminate/database | grep -qE '^versions.*\* v12\.'
- name: Static analysis (self)
run: composer phpstan
- name: Tests
run: composer test
# Aggregate tracked by the town-crier trial (TC-0069); intended as the single
# required check (the matrix legs stop being individually required). A `needs`
# on a matrix job waits for every leg.
ci-passed:
name: ci-passed
runs-on: ubuntu-latest
needs: [check, check-lowest-laravel, check-production-tree]
if: always()
steps:
# WR-0852: this used to fail only on 'failure' or 'cancelled', so a
# SKIPPED lane passed the rollup. Nothing skips today (no upstream
# job carries an `if:` and the workflow has no `paths:` filter), but
# ci-passed is the single required check on main, so the day someone
# adds one the merge gate hollows out while still reporting green.
# Requiring success is also future-proof in the direction that
# matters: a result value GitHub has not shipped yet fails here
# rather than slipping through an enumeration of the bad ones.
- name: Verify every upstream lane succeeded
env:
RESULTS: ${{ join(needs.*.result, ' ') }}
run: |
set -euo pipefail
echo "upstream lane results: ${RESULTS:-<none>}"
if [ -z "${RESULTS//[[:space:]]/}" ]; then
echo "::error::ci-passed received no upstream results, so it is gating nothing."
exit 1
fi
for result in $RESULTS; do
if [ "$result" != "success" ]; then
echo "::error::An upstream CI lane reported '$result'. ci-passed requires every lane to succeed."
exit 1
fi
done