-
Notifications
You must be signed in to change notification settings - Fork 0
307 lines (274 loc) · 11.7 KB
/
Copy pathci.yml
File metadata and controls
307 lines (274 loc) · 11.7 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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
name: CI
on:
push:
branches: [main]
# Skip CI for pure asset / non-package commits.
# 仅核心代码变更触发 CI,跳过纯资源/非包文件提交。
#
# NOTE: user-facing docs (README*.md / USAGE.md / CHANGELOG.md / docs/**) are
# intentionally NOT ignored. Ignoring them would skip the whole ci.yml workflow
# for docs-only PRs, leaving branch-protection required checks permanently
# pending and blocking merge. Docs-only PRs still trigger ci.yml; the heavy
# jobs skip green via the path-filter (code=false).
# 注意:用户态文档(README*.md / USAGE.md / CHANGELOG.md / docs/**)刻意「不」在此忽略——
# 否则纯文档 PR 会让整条 workflow 被跳过,分支保护的 required checks 永远不出现、PR 无法合并。
# 纯文档改动仍会触发 ci.yml,但被 path-filter 判定为 code=false,重 job 绿色跳过。
#
# Finer-grained GitHub ignores — workflows/ MUST still trigger CI (Dependabot
# action updates need CI).
# 精细化忽略 GitHub 配置,但保留 workflows/ 目录的 CI 触发(Dependabot 改 action 版本需要跑 CI)
paths-ignore:
- '.github/ISSUE_TEMPLATE/**' # Issue/PR templates
- '.github/workflows/stale.yml' # Stale bot doesn't affect builds/publish
- '.github/workflows/link-check.yml' # Link checker doesn't affect builds/publish
- '.github/workflows/dependabot-pr-bilingual.yml' # PR body text injection doesn't affect builds/publish
- '**.png'
- '**.jpg'
- '**.jpeg'
- '**.gif'
- '**.webp'
- '**.svg'
- '**.ico'
- '**.txt'
- '**.gitignore'
- 'LICENSE'
- '.metadata'
# NOTE: example/** and server/** are intentionally NOT blanket-ignored — doing so
# would skip the whole workflow for example/server-only PRs and leave required
# checks pending. The path-filter below decides instead: only score-affecting
# example paths set code=true; server changes set server=true.
# 注意:example/** 与 server/** 刻意「不」整体忽略——否则只改它们的 PR 会让整条 workflow
# 跳过、required checks 卡在 pending。改由下方 path-filter 判定。
pull_request:
branches: [main]
paths-ignore:
- '.github/ISSUE_TEMPLATE/**'
- '.github/workflows/stale.yml'
- '.github/workflows/link-check.yml'
- '.github/workflows/dependabot-pr-bilingual.yml'
- '**.png'
- '**.jpg'
- '**.jpeg'
- '**.gif'
- '**.webp'
- '**.svg'
- '**.ico'
- '**.txt'
- '**.gitignore'
- 'LICENSE'
- '.metadata'
# Manual trigger / 手动触发
workflow_dispatch:
# Reused by pub-publish.yml / 支持被其他工作流复用(如 pub-publish.yml)
workflow_call:
# Keep only the latest run per branch, cancel older runs
# 仅保留最新的同分支运行,取消旧的运行
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
# Pre-path-filter: does this change touch files that affect the pub package /
# pana score, or the demo backend?
# 前置路径过滤:判断本次改动是否触及会影响 pub 包 / pana 评分的文件,或 demo 后端。
path-filter:
name: Path Filter
runs-on: ubuntu-latest
outputs:
code: ${{ steps.filter.outputs.code }}
server: ${{ steps.filter.outputs.server }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Filter paths
id: filter
uses: dorny/paths-filter@v4
with:
filters: |
# All doc/asset files are NOT listed here, so docs-only changes → code=false →
# required checks skip green (no pana). Only when any code path below is also
# changed does code=true → run real Analyze/Test/Pana.
# 所有文档/资源类文件均不在此列表 → 纯文档改动 code=false → 必需检查绿色跳过(不过 pana)。
code:
- 'lib/**'
- 'pubspec.yaml'
- 'pubspec.lock'
- 'analysis_options.yaml'
- 'test/**'
- 'example/lib/**'
- 'example/test/**'
- 'example/pubspec.yaml'
- 'example/pubspec.lock'
- 'example/analysis_options.yaml'
- '.github/workflows/ci.yml'
# The demo backend is not published, so it gets its own cheap job.
# demo 后端不随包发布,因此用单独的轻量 job 检查。
server:
- 'server/**'
analyze-and-test:
name: Analyze & Test
runs-on: ubuntu-latest
needs: path-filter
steps:
- name: Disable autocrlf on runner
run: |
git config --global core.autocrlf false
git config --global core.eol lf
git config --global core.safecrlf false
- name: Checkout repository
uses: actions/checkout@v7
# Non-package changes (docs/config/assets only): exit green to satisfy required check
# 非包代码改动(仅文档/GitHub 配置/资源)直接绿色跳过,满足分支保护 required check
- name: Skip on non-code changes
if: ${{ needs.path-filter.outputs.code != 'true' }}
run: |
echo "No package-affecting files changed; skipping Analyze & Test."
exit 0
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
# Pin the exact Flutter/Dart version so `dart format` output is identical
# across CI, publish, and the local dev environment. Unpinned `stable`
# advances over time and the formatter rules change, which makes HEAD's
# formatted files look "unformatted" on CI and loops forever.
# 固定 Flutter/Dart 版本,保证 CI、发布、本地三处的 dart format 输出一致。
flutter-version: '3.41.7'
cache: true
- name: Normalize working tree to LF
# `git add --renormalize` writes LF into the index per .gitattributes,
# then `git checkout -f -- .` materializes that LF index onto disk.
# Guarantees `dart format` (below) reads LF, so --set-exit-if-changed
# is idempotent and does not fail.
# 用纯 git 强制 LF:renormalize 写入 LF 索引,再 checkout -f 落盘。
run: |
git config core.autocrlf false
git config core.eol lf
git add --renormalize .
git checkout -f -- .
- name: Cache pub dependencies
uses: actions/cache@v6
with:
path: ~/.pub-cache
key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'example/pubspec.lock') }}
restore-keys: |
pub-${{ runner.os }}-
- name: Print toolchain versions
run: |
flutter --version
dart --version
# ========== 包本体(纯 Dart)/ Package itself (pure Dart) ==========
- name: Install package dependencies
run: dart pub get
- name: Check package formatting
run: dart format --set-exit-if-changed .
- name: Run static analysis on package
run: dart analyze
- name: Run package unit tests
run: dart test
# ========== Example 应用(Flutter)/ Example app (Flutter) ==========
- name: Install example dependencies
working-directory: example
run: flutter pub get
- name: Check example formatting
working-directory: example
run: dart format --set-exit-if-changed lib/ test/
- name: Run static analysis on example
working-directory: example
run: flutter analyze lib/ test/
- name: Test example widget
working-directory: example
run: flutter test
# ========== demo 后端自检(独立并行 job)/ Demo backend check (separate parallel job) ==========
server-check:
name: Demo Backend Check
runs-on: ubuntu-latest
needs: [path-filter]
steps:
- name: Disable autocrlf on runner
run: |
git config --global core.autocrlf false
git config --global core.eol lf
git config --global core.safecrlf false
- name: Checkout repository
uses: actions/checkout@v7
- name: Skip when server is untouched
if: ${{ needs.path-filter.outputs.server != 'true' }}
run: |
echo "server/ unchanged; skipping Demo Backend Check."
exit 0
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
# Keep in sync with the other jobs (flutter-version: '3.41.7').
# 与其他 job 保持一致(flutter-version: '3.41.7')。
flutter-version: '3.41.7'
cache: true
- name: Resolve demo backend dependencies
working-directory: server
run: dart pub get
- name: Check demo backend formatting
working-directory: server
run: dart format --set-exit-if-changed .
- name: Run static analysis on demo backend
working-directory: server
run: dart analyze
# ========== pub.dev 评分自检 / pub.dev score self-check ==========
pana-check:
name: Pana Score Check
runs-on: ubuntu-latest
needs: [analyze-and-test, path-filter]
steps:
- name: Disable autocrlf on runner
run: |
git config --global core.autocrlf false
git config --global core.eol lf
git config --global core.safecrlf false
- name: Checkout repository
uses: actions/checkout@v7
# Non-package changes: exit green to skip slow pana (satisfies required check)
# 非包代码改动直接绿色跳过,避免耗时的 pana 运行(满足分支保护 required check)
- name: Skip on non-code changes
if: ${{ needs.path-filter.outputs.code != 'true' }}
run: |
echo "No package-affecting files changed; skipping Pana Score Check."
exit 0
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
# Keep in sync with the analyze-and-test job (flutter-version: '3.41.7').
# 与 analyze-and-test 保持一致(flutter-version: '3.41.7')。
flutter-version: '3.41.7'
cache: true
- name: Cache pub dependencies
uses: actions/cache@v6
with:
path: ~/.pub-cache
key: pub-${{ runner.os }}-${{ hashFiles('pubspec.lock', 'example/pubspec.lock') }}
restore-keys: |
pub-${{ runner.os }}-
- name: Run pana pub.dev score check
run: |
dart pub global activate pana
# Run pana with set +e so the score can still be parsed and reported
# 用 set +e 防止 GitHub 默认的 set -e 直接终止,确保后续仍能解析并展示分数
set +e
dart pub global run pana --no-warning --json . > pana.json
PANA_EXIT=$?
set -e
if [ $PANA_EXIT -ne 0 ]; then
echo "::error::pana reported warnings/errors (exit code $PANA_EXIT)"
cat pana.json
exit 1
fi
# pana 0.22+ nests the score under the 'scores' object
# pana 0.22+ 将分数嵌套在 scores 对象下:scores.grantedPoints
SCORE=$(python3 -c "import json; d=json.load(open('pana.json')); s=d.get('scores', d); print(s['grantedPoints'])")
MAX=$(python3 -c "import json; d=json.load(open('pana.json')); s=d.get('scores', d); print(s['maxPoints'])")
echo "pana score: $SCORE / $MAX"
if [ "$SCORE" -lt 120 ]; then
echo "::error::pana score ($SCORE/$MAX) is below the 120 threshold"
exit 1
fi
echo "pana score ($SCORE/$MAX) meets the 120 threshold"