news 2026/10/22 11:53:02

Krita GitLab CI 流水线开发指南:YAML 风格规范与多平台构建实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Krita GitLab CI 流水线开发指南:YAML 风格规范与多平台构建实践
  • 图形学
  • 桌面应用

【免费下载链接】krita

Krita is a free and open source cross-platform application that offers an end-to-end solution for creating digital art files from scratch built on the KDE and Qt frameworks.

项目地址:https://gitcode.com/gh_mirrors/kr/krita
点击查看免费下载

导读

Krita 作为一套横跨 Linux、Windows、macOS 与 Android 的大型 C++ 工程,其持续集成流水线由 GitLab CI 承载,包含 Qt5/Qt6 双线构建、每日构建(nightly)、每周构建(weekly)与发布(release)等多个 job 家族。本文以仓库根目录下的 HACKING.gitlab-ci.md 为骨架,完整解析 Krita 团队为 CI 流水线开发者制定的五条核心规范(缩进、日志、脚本语言、引号策略、布尔值与多行参数),并结合 .gitlab-ci.yml 与 build-tools/ci-scripts 下的真实平台配置文件逐一印证。读完本文,你将掌握一套可直接复用的 Krita 风格 GitLab CI 编写规范,理解KDECI_*/KRITACI_*环境变量的真实作用,以及如何为长耗时构建 job 构建可靠的日志与制品策略。


1. Krita 的 CI 骨架:从 HACKING 文档到流水线实景

HACKING.gitlab-ci.md是 Krita 仓库为维护 CI 流水线本身的开发者(而非为应用功能开发者)准备的短小规范手册。它不讲解功能开发,而是聚焦「如何写出整洁、可维护、跨平台一致的 GitLab CI YAML 与配套脚本」。

该规范在仓库中的落地形态非常清晰:根目录的 .gitlab-ci.yml 负责全局变量、workflow 规则与通用 mixin 定义,并通过include: local:引入四个平台级流水线文件:

include: - local: /build-tools/ci-scripts/linux.yml - local: /build-tools/ci-scripts/windows.yml - local: /build-tools/ci-scripts/android.yml - local: /build-tools/ci-scripts/macos.yml

而 .gitlab-ci.yml 顶部集中声明了跨平台共享的顶层变量,例如各平台依赖分支名(DEPS_BRANCH_NAME_WINDOWS/LINUX/MACOS/ANDROID)、Qt6 迁移分支名(DEPS_QT6_BRANCH_NAME_*)、以及各平台 VM 镜像名(VM_IMAGE_NAME_WINDOWS/LINUX/ANDROID)。这些变量正是下文各条规范反复操作的对象。

接下来,我们逐条展开 HACKING 文档中的五条规则。


2. 规则 0:YAML 缩进统一为 2 空格

Krita 的 C++ 源码遵循 KDE 惯例的 4 空格缩进,但 CI 的 YAML 文件刻意与 C++ 风格区分——统一使用2 空格缩进,理由是跟随系统管理员(Sysadmin)编写脚本的习惯。

HACKING 文档为此给出了 VSCode 的编辑器配置片段,可直接写入 VSCode 的settings.json,确保编辑 YAML 时不会被自动格式化工具擅自改写缩进:

"[yaml]": { "editor.formatOnSave": false, "editor.tabSize": 2, "editor.insertSpaces": true, "editor.detectIndentation": true, "editor.wrappingIndent": "indent", "editor.autoIndent": "full" },

各配置项的含义与价值:

配置项值作用
editor.formatOnSavefalse禁止保存时自动格式化,避免 Prettier/YAML 插件把 2 空格改成 4 空格或制表符
editor.tabSize2一个制表符视作 2 列宽,与渲染宽度对齐
editor.insertSpacestrue按下 Tab 时插入空格而非制表符字符
editor.detectIndentationtrue根据文件已有缩进自动探测,兼容仓库内不同文件
editor.wrappingIndentindent长行折行时按当前缩进层级续行,便于阅读多行变量(见规则 5)
editor.autoIndentfull回车换行时沿用上级缩进,减少手工调整

从仓库实景看,.gitlab-ci.yml 与 build-tools/ci-scripts 下的四个 yml 文件均严格使用 2 空格层级缩进,例如variables:下的每个键名都比上级多两个空格。这与文档规定完全一致,也是 GitLab 解析 YAML 的前提——GitLab Runner 对缩进错误非常敏感,混用 Tab 与空格会直接导致流水线解析失败。


3. 规则 1:为长构建 job 建立日志备份,规避 GitLab 日志上限

GitLab 对单个 job 的日志有约4 MiB的体积限制。当 Krita 这类大型工程的编译日志溢出该上限时,超出部分会被直接丢弃,排障时便无从查起。因此 HACKING 文档规定:凡是可能溢出日志上限的构建 job,每一个 build step 都要将输出同时写入文件:

job-step.py 2>&1 | tee build-step.log

在 job 结束时,将这些.log文件上传为 CI 制品(artifacts)。这样即使 GitLab 在线日志被截断,也能从制品中找回完整日志。

在 Windows 上则使用 PowerShell 风格的等价命令:

job-step.py 2>&1 | Tee-Object -FilePath "build-step.log"

这两条命令的原理一致:2>&1先把 stderr 并入 stdout,再交给tee(Linux)或Tee-Object(Windows PowerShell)同时输出到控制台与文件。

3.1 仓库中的实际运用

该规则在平台流水线中已有直接落地,且日志文件会被制品收集逻辑捕获:

  • Windows:build-tools/ci-scripts/windows.yml 中每一步都使用Tee-Object落盘,分别生成build-krita.log、build-installers.log、installers-publish.log;
  • Linux:build-tools/ci-scripts/linux.yml 中有一段重要注释——GitLab 在处理tee保存日志时曾出现 job 静默挂起的问题,因此 Linux 端刻意不再手动加日志,这是对规范「因地制宜」的例外;
  • 制品收集:.gitlab-ci.yml 的.ci-artifacts-with-packages-mixin将"*.log"及_dmg/*.log(macOS 签名/公证日志)列入artifacts.paths,并设置expire_in: 10 days、when: always,保证日志无论 job 成败都会保留十天。

注意:job-step.py本身并不在本仓库内,它来自 KDE 的ci-utilities/krita-deps-management外部工具仓(平台 yml 的before_script中会克隆这些仓库)。本仓库内的用法是直接调用该工具配合tee。从源码结构看,Android 流水线(build-tools/ci-scripts/android.yml)同样采用| tee build-krita.log的写法,可见这一模式在 KDE 生态中是跨平台通用的。


4. 规则 2:脚本一律优先 Python3,回避 Windows Batch

Krita 的 CI 脚本被要求优先使用 Python3 编写(只要目标平台支持),并尽量避免使用 Windows Batch(.cmd/.bat)脚本。理由是 Batch 脚本众所周知的不可移植性:它在消费级 Windows 与 Windows Server 上的行为差异巨大,极易在 CI 环境中产生难以排查的偶发问题。

从仓库实景可以印证这一原则:

  • build-tools/ci-scripts 下的辅助脚本全部为 Python3 实现,例如upload-nightly-packages.py、merge-libs-xml.py、move-signing-logs.py、rename-signed-apk-packages.py、show-updates-status.py;
  • 各平台 yml 中大量直接调用python3 -u xxx.py,且-u参数保证 stdout 无缓冲、日志实时可见;
  • Windows 构建链在 build-tools/ci-scripts/windows.yml 中先以BOOTSTRAP_PYTHON_EXE_WINDOWS(如C:\tools\Python-3.13\python.exe)创建 venv,后续统一使用python -u调用脚本——即连 Windows 上也坚持 Python 而不是 Batch;
  • 平台差异仅通过条件判断收敛在少数地方,例如 android.yml 中if [ "$KRITACI_ANDROID_PACKAGE_TYPE" == "nightly" ]这类 shell 条件,而不是写成多份平台专属脚本。

从源码结构可以推断:Krita 团队把「跨平台行为一致性」视为 CI 脚本的首要目标,Python3 + 集中式 Python 工具链是达成该目标的核心手段。


5. 规则 3:YAML 字符串的引号策略——默认不引,特殊情况才引

HACKING 文档对 yml 文件中的字符串给出明确约定:

所有字符串默认不加引号;仅当字符串包含通配符(如*)或 YAML 控制字符(如 Windows 路径中的:)时,才用引号包裹。

文档自带的对照示例:

windows-build: variables: KDECI_BUILD_TYPE: Release # simple string -> unquoted KDECI_EXTRA_CMAKE_ARGS: -DHIDE_SAFE_ASSERTS=OFF # simple string -> unquoted KDECI_CC_CACHE: "C:\\Gitlab\\Caches\\krita-windows" # Windows path -> quoted linux-build: variables: KDECI_CC_CACHE: /mnt/caches/krita-appimage/ # Linux path -> unquoted

这条规范在平台 yml 中得到了忠实执行:

  • Windows(build-tools/ci-scripts/windows.yml):
    KDECI_CC_CACHE: "Z:\\krita-windows\\caches" KDECI_CACHE_PATH: "Z:\\krita-windows\\artifacts"

    因为Z:\...中的冒号:是 YAML 的键值分隔符/控制字符,Windows 路径又含反斜杠转义,所以必须双引号包裹(注意反斜杠需写成\\转义);

  • Linux/macOS(build-tools/ci-scripts/linux.yml):
    KDECI_CC_CACHE: /mnt/krita-appimage/caches/ KDECI_CACHE_PATH: /mnt/krita-appimage/artifacts/

    纯路径不含特殊字符,直接不加引号;

  • 此外,MACOSX_DEPLOYMENT_TARGET: "10.15"(build-tools/ci-scripts/macos.yml)被引号包裹,因为裸10.15会被 YAML 解析为浮点数而非字符串——这也属于「必须加引号」的隐含场景。

推论:加不加引号的判断标准是「解析安全性」。一旦字符串可能被 YAML 误解析(数字、时间、:、*通配、特殊符号),就加引号;其余一律裸写,保证文件简洁且 diff 干净。


6. 规则 4:传给 CI 脚本的布尔值必须是非引号的 True / False

Krita 的 CI 脚本通过环境变量接收开关参数,HACKING 文档规定这些布尔开关必须写为不带引号的字符串True/False(注意首字母大写):

windows-build: variables: KDECI_COMPRESS_PACKAGES_ON_DOWNLOAD: False KRITACI_SKIP_UPLOAD_NIGHTLY_PACKAGE: True

为什么刻意强调「不带引号」?因为加了引号后 YAML 会保留'False'的字面字符串,而下游脚本(多为 Python)如果按"False"字符串做真值判断,容易与 YAML 原生布尔语义混淆。统一裸写True/False字符串,语义唯一、跨平台稳定。

仓库中的实际使用非常密集,例如:

  • build-tools/ci-scripts/linux.yml:KDECI_COMPRESS_PACKAGES_ON_DOWNLOAD: False、KRITACI_SKIP_UPLOAD_NIGHTLY_PACKAGE: True;
  • build-tools/ci-scripts/windows.yml:KDECI_COMPRESS_PACKAGES_ON_DOWNLOAD: False、KDECI_SIGN_BINARIES: False(注释说明只对 nightly 与 release 包签名);
  • .gitlab-ci.yml 的.upload-packages-to-cdn-base-mixin:KDECI_ONLY_BUILD: True、KRITACI_SKIP_DEBUG_PACKAGE: False、KRITACI_SKIP_UPLOAD_NIGHTLY_PACKAGE: False、KRITACI_BUILD_INSTALLERS: True;
  • 也有个别键值使用带引号的"True"(如 linux.yml 中KDECI_ONLY_BUILD: "True"),从源码结构看这属于历史写法残留,新代码应以文档规定的裸写形式为准。

常见开关含义速查(依据仓库变量命名与使用位置归纳):

变量常见取值作用
KDECI_ONLY_BUILDTrue/False仅构建不运行测试(macOS 当前因日志泛滥临时启用,见 build-tools/ci-scripts/macos.yml 的 TODO 注释)
KDECI_BUILD_TYPERelease/RelWithDebInfo/DebugCMake 构建类型;发布与 nightly 常为RelWithDebInfo
KDECI_SIGN_BINARIESTrue/False是否对二进制签名(仅 nightly/release 打开)
KRITACI_SKIP_UPLOAD_NIGHTLY_PACKAGETrue/False是否跳过向 CDN 上传 nightly 包
KRITACI_BUILD_INSTALLERSTrue/False是否构建安装程序(Windows 的 release job 为True)
KRITACI_SKIP_DEBUG_PACKAGETrue/False是否跳过调试包生成
KRITACI_PARALLEL_JOBS整数并行 job 数;ASAN 构建降为1以避免 OOM(build-tools/ci-scripts/linux.yml)

7. 规则 5:多行 CMake 参数用>折叠

当通过环境变量向 CI 脚本传递多个 CMake 选项时,HACKING 文档规定使用 YAML 的块折叠标量>把参数拆成多行,提升可读性与 git diff 的可追踪性:

linux-nightly: variables: KDECI_EXTRA_CMAKE_ARGS: > -DHIDE_SAFE_ASSERTS=OFF -DBUILD_TESTING=OFF

>会把后续缩进块中的换行折叠为单个空格,最终环境变量值等价于-DHIDE_SAFE_ASSERTS=OFF -DBUILD_TESTING=OFF。

仓库中的典型用法(含 Qt6 双线构建)来自 build-tools/ci-scripts/linux.yml:

KDECI_EXTRA_CMAKE_ARGS: > -DHIDE_SAFE_ASSERTS=OFF -DBUILD_TESTING=ON -DBUILD_WITH_QT6=ON -DALLOW_UNSTABLE=QT6

同类写法还出现在:

  • build-tools/ci-scripts/linux.yml 的 nightly job:-DHIDE_SAFE_ASSERTS=OFF -DBUILD_TESTING=OFF;
  • build-tools/ci-scripts/linux.yml 的 ASAN weekly job:追加-DECM_ENABLE_SANITIZERS=address -DENABLE_UPDATERS=OFF;
  • build-tools/ci-scripts/windows.yml、build-tools/ci-scripts/android.yml、build-tools/ci-scripts/macos.yml 中均有同款折叠。

由此可以看出一个隐含的工程习惯:KDECI_EXTRA_CMAKE_ARGS是向 Krita 的 CMake 构建注入选项的唯一入口,将-DBUILD_WITH_QT6=ON、-DALLOW_UNSTABLE=QT6等关键开关集中放在一处并逐行书写,正是为了 code review 时能一眼看到每个开关的增删。


8. 从规范到流水线:mixin 复用与 job 组合实战

读懂五条规则后,再看 Krita 如何用它们组织出整个流水线,会更有整体感。.gitlab-ci.yml 中定义了大量以.开头的mixin(隐藏 job 模板),通过extends组合复用,这正是规则 0(2 空格缩进)能长期稳定运行的组织基础:

Mixin作用
.nightly-job-mixin定时流水线(schedule)中KRITACI_SCHEDULED_JOB_NAME == "nightly"时运行
.weekly-job-mixinschedule 中weekly时运行
.ci-manual-job-mixinschedule 与 release 分支永不自动运行,仅手动触发
.ci-always-job-mixin排除 schedule 与 release 分支后始终运行(普通 MR/分支流水线)
.ci-release-job-mixin仅在release/*分支 push 时手动触发,且interruptible: false(不可被新提交抢占)
.ci-artifacts-with-packages-mixin定义制品与 JUnit/覆盖率报告,包含安装包产物
.ci-artifacts-without-packages-mixinnightly 专用,包已上传 CDN,不再重复存制品
.upload-packages-to-cdn-base-mixin组合以上两者,设置KRITACI_ONLY_BUILD等上传相关开关

组合示例(build-tools/ci-scripts/linux.yml):

linux-build-qt6-nightly: extends: - .linux-qt6-base - .nightly-job-mixin - .upload-packages-to-cdn-base-mixin variables: KDECI_EXTRA_CMAKE_ARGS: > -DHIDE_SAFE_ASSERTS=OFF -DBUILD_TESTING=OFF -DBUILD_WITH_QT6=ON -DALLOW_UNSTABLE=QT6

这一小段同时示范了规则 3(KDECI_BUILD_TYPE: Release裸写)、规则 4(布尔值裸写True/False)与规则 5(>折叠多行参数)。各平台作业矩阵如下:

  • Linux:linux-build-qt5/qt6、linux-build-qt5/qt6-nightly、linux-qt5-debug-weekly、linux-qt5-asan-weekly/manual、linux-release-qt5/qt6;
  • Windows:build-tools/ci-scripts/windows.yml 中windows-build-qt5/qt6、windows-build-qt5/qt6-nightly、windows-qt5-asan-weekly、windows-release-qt5/qt6,release 包还打开KRITACI_RELEASE_PACKAGE_NAMING: True;
  • Android:build-tools/ci-scripts/android.yml 针对x86_64、arm64-v8a、armeabi-v7a三个 ABI 各派生 build/nightly/release 三档 job,并由android-build-appbundle(-release)汇总打 AAB 包;
  • macOS:build-tools/ci-scripts/macos.yml 走完整的「构建 → 打包 .app → 签名 → 公证 → 打包 .dmg → 再签名 → 再公证 → 上传」链路,每一步都配tee日志(对应规则 1)。

9. 总结

HACKING.gitlab-ci.md虽然只有短短六条规则,却是理解 Krita CI 全貌的钥匙。把五条规范与仓库实景对应起来,可以得到一套可复用的工程结论:

  1. 缩进即纪律:YAML 一律 2 空格,与 C++ 代码刻意区分,用编辑器配置(formatOnSave: false)守住它;
  2. 日志即证据:长 job 必须tee落盘并作为制品保留,Windows 用Tee-Object,同时要留意 Linux 上 GitLab 对tee的已知挂起问题(build-tools/ci-scripts/linux.yml);
  3. 脚本即语言:优先 Python3,用-u保证日志实时,彻底回避 Batch;
  4. 字符串引号按需:默认裸写,仅在含:、*、数字语义等解析风险时加引号(Windows 路径"Z:\\..."是标准反面教材式示例);
  5. 布尔与多行有固定写法:布尔裸写True/False,多行 CMake 参数用>折叠并经KDECI_EXTRA_CMAKE_ARGS注入。

当你为 Krita(或同类 KDE 生态项目)新增一个 CI job 时,只需照此约定:用 2 空格写出 mixin 组合,按需声明KDECI_*/KRITACI_*变量,把每一步包进tee日志,并让脚本与参数写法严格遵循上述五条规则——这既是 Krita 团队内部的可读性要求,也是让 CI 问题可定位、可追溯、跨平台可复现的最短路径。

进一步查阅材料:流水线入口 .gitlab-ci.yml、平台作业定义 build-tools/ci-scripts/linux.yml、build-tools/ci-scripts/windows.yml、build-tools/ci-scripts/android.yml、build-tools/ci-scripts/macos.yml,以及规范原文 HACKING.gitlab-ci.md。

  • 图形学
  • 桌面应用

【免费下载链接】krita

Krita is a free and open source cross-platform application that offers an end-to-end solution for creating digital art files from scratch built on the KDE and Qt frameworks.

项目地址:https://gitcode.com/gh_mirrors/kr/krita
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 11:52:26

游戏测试岗实习面试全复盘:从笔试到HR面的实战经验与避坑指南

1. 从简历筛选到终面:一场测试岗实习面试的完整复盘每年三四月份,游戏公司的暑期实习招聘就会陆续启动。测试工程师这个岗位,在很多同学眼里是个“门槛不高”的备选项,觉得不就是点点点找bug吗。但真正走完一整轮面试流程之后&…

作者头像 李华
网站建设 2026/10/22 11:52:31

WiFi上下行速度测试全攻略:原理、工具与排查优化实践

1. 为什么我要自己动手做WiFi上下行速度测试家里宽带明明办的是500M,为什么看视频还是转圈?这个问题我身边至少十个朋友问过。每次我都让他们先别急着骂运营商,先做一次完整的WiFi上行下行速度测试再说。结果十次里有六次,问题根本…

作者头像 李华
网站建设 2026/10/14 15:53:51

Eclipse MAT实战:Java OOM堆转储与内存泄漏根因定位指南

简介:Eclipse MAT(Memory Analyzer Tool)完整软件包,适用于Java开发与性能优化人员,用于解析JVM堆转储文件,定位内存泄漏、分析对象引用关系。压缩包共5442个文件,约133.56MB,以HTML…

作者头像 李华
网站建设 2026/10/15 5:29:04

双色球历史开奖数据导入MySQL与Excel分析实战:从建表到数据校验

简介:双色球自2003年2月23日首期开售至2025年4月15日全部3287期开奖记录,已按时间顺序完整整理为一份轻量数据包,面向需要批量获取历史号码的趋势分析、频次统计或预测建模用户,能有效省去手工收集与清洗校验的繁琐环节。压缩包共…

作者头像 李华
网站建设 2026/10/19 17:13:25

Oracle AWR报告实战:关键指标解读与避坑指南

简介:这份PDF由黄伟波撰写,主题为Oracle数据库AWR报告分析,是面向数据库管理员、性能优化工程师及初学者的实用指南。内容从AWR基本概念讲起,涵盖统计信息分类、STATISTICS_LEVEL参数、报告核心组成与维护进程;AWR作为…

作者头像 李华