141 lines
4.4 KiB
YAML
141 lines
4.4 KiB
YAML
# CI 门禁。来源:conti-docs/14-conventions-and-ci-gates.md + 08-build-flavors.md
|
||
#
|
||
# ---------------------------------------------------------------------------
|
||
# 门禁的立法目的(14 §一):**约定只有被机器强制才叫约定**。下面每一条都对应
|
||
# 一条人工评审记不住、也不该由人来记的规则。
|
||
#
|
||
# TODO(ops): 镜像名和 mac runner 的 tag 都是占位符,两项文档自己就列为待确认:
|
||
# - Flutter 镜像:需要一个预装 Flutter 3.44.9 的内网镜像(公网 ghcr 拉不动)
|
||
# - iOS 构建:需要一台 mac runner,目前团队没有
|
||
# ---------------------------------------------------------------------------
|
||
|
||
stages:
|
||
- verify
|
||
- test
|
||
- build
|
||
|
||
default:
|
||
image: $FLUTTER_IMAGE # TODO(ops): 形如 registry.internal/flutter:3.44.9
|
||
tags:
|
||
- docker
|
||
before_script:
|
||
- dart pub global activate melos 8.2.2
|
||
- export PATH="$PATH:$HOME/.pub-cache/bin"
|
||
- melos bootstrap
|
||
|
||
variables:
|
||
# 产物不入库,每一步 CI 都得自己生成一遍(14 §四)。
|
||
PUB_CACHE: "$CI_PROJECT_DIR/.pub-cache"
|
||
|
||
cache:
|
||
key:
|
||
files:
|
||
- pubspec.lock
|
||
paths:
|
||
- .pub-cache
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# verify:不跑测试就能发现的问题,全部拦在这里,因为它最快
|
||
# ---------------------------------------------------------------------------
|
||
format:
|
||
stage: verify
|
||
script:
|
||
- melos run format
|
||
# 格式化不是审美问题:不统一的话每个 PR 的 diff 里都混着大段无关的换行改动,
|
||
# 评审会开始跳过 diff。
|
||
|
||
analyze:
|
||
stage: verify
|
||
script:
|
||
- melos run gen
|
||
- melos run analyze
|
||
# --fatal-infos 在 melos 脚本里。不加等于 lint 形同虚设——绝大部分 riverpod_lint
|
||
# 规则报的是 info 级别。
|
||
|
||
pigeon-consistency:
|
||
stage: verify
|
||
script:
|
||
- melos run gen:pigeon
|
||
# Pigeon 产物是入库的。改了 pigeons/*.dart 却忘了重新生成,是一个编译期
|
||
# 完全看不出来、运行时才炸 MissingPluginException 的经典事故。
|
||
- git diff --exit-code || (echo "Pigeon 产物与 pigeons/ 不一致,请本地跑 melos run gen:pigeon 后提交" && exit 1)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# test
|
||
# ---------------------------------------------------------------------------
|
||
unit-test:
|
||
stage: test
|
||
script:
|
||
- melos run gen
|
||
- melos run test
|
||
coverage: '/lines\.*: \d+\.\d+\%/'
|
||
artifacts:
|
||
when: always
|
||
paths:
|
||
- packages/*/coverage/lcov.info
|
||
expire_in: 1 week
|
||
|
||
# 覆盖率门禁单独一个 job:它会失败得比较频繁,混在 unit-test 里会让人分不清
|
||
# 是"测试挂了"还是"覆盖率不够"。
|
||
coverage-gate:
|
||
stage: test
|
||
needs: [unit-test]
|
||
allow_failure: true # TODO: 骨架期先不卡人,等业务代码进来再改成 false
|
||
script:
|
||
- dart pub global activate coverde
|
||
- melos run coverage
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# build:dev/uat 按分支出包,prod 只认 tag
|
||
# ---------------------------------------------------------------------------
|
||
.android-build: &android-build
|
||
stage: build
|
||
script:
|
||
- melos run gen
|
||
- cd app
|
||
- >
|
||
flutter build apk
|
||
--flavor $FLAVOR
|
||
-t lib/main_$FLAVOR.dart
|
||
--dart-define-from-file=env/$FLAVOR.json
|
||
$EXTRA_ARGS
|
||
artifacts:
|
||
paths:
|
||
- app/build/app/outputs/flutter-apk/*.apk
|
||
expire_in: 1 month
|
||
|
||
android-dev:
|
||
<<: *android-build
|
||
variables:
|
||
FLAVOR: dev
|
||
rules:
|
||
- if: $CI_COMMIT_BRANCH == "develop"
|
||
|
||
android-uat:
|
||
<<: *android-build
|
||
variables:
|
||
FLAVOR: uat
|
||
rules:
|
||
- if: $CI_COMMIT_BRANCH == "main"
|
||
|
||
android-prod:
|
||
<<: *android-build
|
||
variables:
|
||
FLAVOR: prod
|
||
# release 包必须混淆 + 拆符号表,否则 Sentry 上的堆栈是一堆十六进制地址。
|
||
# --split-debug-info 的产物要留着,sentry_dart_plugin 靠它还原堆栈。
|
||
EXTRA_ARGS: --release --obfuscate --split-debug-info=build/symbols
|
||
after_script:
|
||
# SENTRY_AUTH_TOKEN 只从 CI 变量读,仓库里任何文件都不许出现它。
|
||
- cd app && dart run sentry_dart_plugin
|
||
artifacts:
|
||
paths:
|
||
- app/build/app/outputs/flutter-apk/*.apk
|
||
- app/build/symbols
|
||
expire_in: 1 year
|
||
rules:
|
||
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
|
||
|
||
# TODO(ops): iOS 构建需要 mac runner。配置步骤见 app/ios/FLAVORS.md,
|
||
# 在 Scheme 建好并进 git 之前,这个 job 加了也跑不通。
|