Krita GitLab CI 流水线开发指南:YAML 风格规范与多平台构建实践
图形学桌面应用【免费下载链接】kritaKrita 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. 规则 0YAML 缩进统一为 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长行折行时按当前缩进层级续行便于阅读多行变量见规则 5editor.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 21 | tee build-step.log在 job 结束时将这些.log文件上传为 CI 制品artifacts。这样即使 GitLab 在线日志被截断也能从制品中找回完整日志。在 Windows 上则使用 PowerShell 风格的等价命令job-step.py 21 | Tee-Object -FilePath build-step.log这两条命令的原理一致21先把 stderr 并入 stdout再交给teeLinux或Tee-ObjectWindows PowerShell同时输出到控制台与文件。3.1 仓库中的实际运用该规则在平台流水线中已有直接落地且日志文件会被制品收集逻辑捕获Windowsbuild-tools/ci-scripts/windows.yml 中每一步都使用Tee-Object落盘分别生成build-krita.log、build-installers.log、installers-publish.logLinuxbuild-tools/ci-scripts/linux.yml 中有一段重要注释——GitLab 在处理tee保存日志时曾出现 job 静默挂起的问题因此 Linux 端刻意不再手动加日志这是对规范「因地制宜」的例外制品收集.gitlab-ci.yml 的.ci-artifacts-with-packages-mixin将*.log及_dmg/*.logmacOS 签名/公证日志列入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 BatchKrita 的 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. 规则 3YAML 字符串的引号策略——默认不引特殊情况才引HACKING 文档对 yml 文件中的字符串给出明确约定所有字符串默认不加引号仅当字符串包含通配符如*或 YAML 控制字符如 Windows 路径中的:时才用引号包裹。文档自带的对照示例windows-build: variables: KDECI_BUILD_TYPE: Release # simple string - unquoted KDECI_EXTRA_CMAKE_ARGS: -DHIDE_SAFE_ASSERTSOFF # 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 中得到了忠实执行Windowsbuild-tools/ci-scripts/windows.ymlKDECI_CC_CACHE: Z:\\krita-windows\\caches KDECI_CACHE_PATH: Z:\\krita-windows\\artifacts因为Z:\...中的冒号:是 YAML 的键值分隔符/控制字符Windows 路径又含反斜杠转义所以必须双引号包裹注意反斜杠需写成\\转义Linux/macOSbuild-tools/ci-scripts/linux.ymlKDECI_CC_CACHE: /mnt/krita-appimage/caches/ KDECI_CACHE_PATH: /mnt/krita-appimage/artifacts/纯路径不含特殊字符直接不加引号此外MACOSX_DEPLOYMENT_TARGET: 10.15build-tools/ci-scripts/macos.yml被引号包裹因为裸10.15会被 YAML 解析为浮点数而非字符串——这也属于「必须加引号」的隐含场景。推论加不加引号的判断标准是「解析安全性」。一旦字符串可能被 YAML 误解析数字、时间、:、*通配、特殊符号就加引号其余一律裸写保证文件简洁且 diff 干净。6. 规则 4传给 CI 脚本的布尔值必须是非引号的 True / FalseKrita 的 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.ymlKDECI_COMPRESS_PACKAGES_ON_DOWNLOAD: False、KRITACI_SKIP_UPLOAD_NIGHTLY_PACKAGE: Truebuild-tools/ci-scripts/windows.ymlKDECI_COMPRESS_PACKAGES_ON_DOWNLOAD: False、KDECI_SIGN_BINARIES: False注释说明只对 nightly 与 release 包签名.gitlab-ci.yml 的.upload-packages-to-cdn-base-mixinKDECI_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 常为RelWithDebInfoKDECI_SIGN_BINARIESTrue/False是否对二进制签名仅 nightly/release 打开KRITACI_SKIP_UPLOAD_NIGHTLY_PACKAGETrue/False是否跳过向 CDN 上传 nightly 包KRITACI_BUILD_INSTALLERSTrue/False是否构建安装程序Windows 的 release job 为TrueKRITACI_SKIP_DEBUG_PACKAGETrue/False是否跳过调试包生成KRITACI_PARALLEL_JOBS整数并行 job 数ASAN 构建降为1以避免 OOMbuild-tools/ci-scripts/linux.yml7. 规则 5多行 CMake 参数用折叠当通过环境变量向 CI 脚本传递多个 CMake 选项时HACKING 文档规定使用 YAML 的块折叠标量把参数拆成多行提升可读性与 git diff 的可追踪性linux-nightly: variables: KDECI_EXTRA_CMAKE_ARGS: -DHIDE_SAFE_ASSERTSOFF -DBUILD_TESTINGOFF会把后续缩进块中的换行折叠为单个空格最终环境变量值等价于-DHIDE_SAFE_ASSERTSOFF -DBUILD_TESTINGOFF。仓库中的典型用法含 Qt6 双线构建来自 build-tools/ci-scripts/linux.ymlKDECI_EXTRA_CMAKE_ARGS: -DHIDE_SAFE_ASSERTSOFF -DBUILD_TESTINGON -DBUILD_WITH_QT6ON -DALLOW_UNSTABLEQT6同类写法还出现在build-tools/ci-scripts/linux.yml 的 nightly job-DHIDE_SAFE_ASSERTSOFF -DBUILD_TESTINGOFFbuild-tools/ci-scripts/linux.yml 的 ASAN weekly job追加-DECM_ENABLE_SANITIZERSaddress -DENABLE_UPDATERSOFFbuild-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_QT6ON、-DALLOW_UNSTABLEQT6等关键开关集中放在一处并逐行书写正是为了 code review 时能一眼看到每个开关的增删。8. 从规范到流水线mixin 复用与 job 组合实战读懂五条规则后再看 Krita 如何用它们组织出整个流水线会更有整体感。.gitlab-ci.yml 中定义了大量以.开头的mixin隐藏 job 模板通过extends组合复用这正是规则 02 空格缩进能长期稳定运行的组织基础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.ymllinux-build-qt6-nightly: extends: - .linux-qt6-base - .nightly-job-mixin - .upload-packages-to-cdn-base-mixin variables: KDECI_EXTRA_CMAKE_ARGS: -DHIDE_SAFE_ASSERTSOFF -DBUILD_TESTINGOFF -DBUILD_WITH_QT6ON -DALLOW_UNSTABLEQT6这一小段同时示范了规则 3KDECI_BUILD_TYPE: Release裸写、规则 4布尔值裸写True/False与规则 5折叠多行参数。各平台作业矩阵如下Linuxlinux-build-qt5/qt6、linux-build-qt5/qt6-nightly、linux-qt5-debug-weekly、linux-qt5-asan-weekly/manual、linux-release-qt5/qt6Windowsbuild-tools/ci-scripts/windows.yml 中windows-build-qt5/qt6、windows-build-qt5/qt6-nightly、windows-qt5-asan-weekly、windows-release-qt5/qt6release 包还打开KRITACI_RELEASE_PACKAGE_NAMING: TrueAndroidbuild-tools/ci-scripts/android.yml 针对x86_64、arm64-v8a、armeabi-v7a三个 ABI 各派生 build/nightly/release 三档 job并由android-build-appbundle(-release)汇总打 AAB 包macOSbuild-tools/ci-scripts/macos.yml 走完整的「构建 → 打包 .app → 签名 → 公证 → 打包 .dmg → 再签名 → 再公证 → 上传」链路每一步都配tee日志对应规则 1。9. 总结HACKING.gitlab-ci.md虽然只有短短六条规则却是理解 Krita CI 全貌的钥匙。把五条规范与仓库实景对应起来可以得到一套可复用的工程结论缩进即纪律YAML 一律 2 空格与 C 代码刻意区分用编辑器配置formatOnSave: false守住它日志即证据长 job 必须tee落盘并作为制品保留Windows 用Tee-Object同时要留意 Linux 上 GitLab 对tee的已知挂起问题build-tools/ci-scripts/linux.yml脚本即语言优先 Python3用-u保证日志实时彻底回避 Batch字符串引号按需默认裸写仅在含:、*、数字语义等解析风险时加引号Windows 路径Z:\\...是标准反面教材式示例布尔与多行有固定写法布尔裸写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。赞分享图形学桌面应用【免费下载链接】kritaKrita 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点击查看免费下载相关推荐Flame多平台构建CI/CD流水线自动化Flame多平台构建CI/CD流水线自动化 概述 Flame作为基于Flutter的游戏引擎支持多平台构建是其核心优势之一。本文将深入探讨如何为Flame项游戏开发图形学终极指南OpenCore Legacy Patcher让老款Mac完美运行最新macOS系统终极指南OpenCore Legacy Patcher让老款Mac完美运行最新macOS系统 还在为老款Mac无法升级最新macOS而烦恼吗当你的设备提示操作系统固件驱动开发突破架构壁垒GitLab CIbuildx打造跨平台Docker镜像构建流水线突破架构壁垒GitLab CIbuildx打造跨平台Docker镜像构建流水线 你是否还在为多架构Docker镜像构建烦恼手动适配不同CPU架构、重复编写云原生DevOps创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考