Files
2026-08-17 15:29:55 +08:00

141 lines
4.4 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
# ---------------------------------------------------------------------------
# builddev/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 加了也跑不通。