agilelabs-fx-docs main topics/drone-ci.md

Drone CI 配置专题

本页是 AgileLabs 项目使用 Drone 组织 CI/CD 的主题页,重点说明 .drone.yml 的结构、固定 runner 选择、步骤拆分方式,以及多前端 + WebAPI 项目如何从提交触发构建一路走到镜像与部署。它负责讲清楚“应该怎么组织”,更具体的真实示例请继续看参考区页面。

适用场景

  • 项目使用 Drone 作为持续集成与持续部署平台。
  • Git 代码提交后需要自动触发构建、测试、打包或部署。
  • 项目需要固定落到 Windows 64、Mac ARM、Linux amd64 三类 runner 之一。
  • 仓库中同时存在 WebAPI、桌面端、多个前端应用或需要构建发布产物的脚本工程。

配置入口与默认约定

  • 业务项目默认在项目根目录维护 .drone.yml
  • Drone 在收到符合条件的 pushtag 等事件后,按 .drone.yml 中的 pipeline 定义自动执行步骤。
  • 本仓库当前可参考的历史示例分别位于 agilelabs/.drone.ymlagilelabs.aspnet/.drone.yml,它们用于说明已有做法,不改变“项目级配置默认放根目录”的主口径。
  • Linux runner 在本文统一写为 amd64,不再使用容易与 32 位混淆的 “x86” 说法。

固定 runner 标准

场景 platform.os platform.arch node.runner_name 典型用途
Windows 64 windows amd64 win-build Electron Windows 包、需要 PowerShell 或 Windows 工具链的项目
Mac ARM darwin arm64 mac-arm-build macOS 应用打包、签名、需要 Apple Silicon 环境的项目
Linux amd64 linux amd64 cn-build-02 WebAPI、前后端混合仓库、Docker 镜像、Kubernetes 部署

选择 runner 时优先看“构建环境是否必须依赖某个平台”,不要只因为团队熟悉某个 runner 就把所有任务都塞进去。

.drone.yml 最小结构

最小可维护结构至少要包含以下字段:

  • kind: 一般为 pipeline
  • type: 当前团队标准是 exec
  • name: pipeline 名称
  • platform: 指定 osarch
  • node: 指定 runner_name
  • trigger: 说明由哪些事件触发
  • steps: 具体执行步骤

最小骨架示例:

---
kind: pipeline
type: exec
name: default

platform:
  os: linux
  arch: amd64

node:
  runner_name: cn-build-02

trigger:
  event:
    - push
  branch:
    - main

steps:
  - name: build
    commands:
      - bash scripts/ci/build.sh

必须遵守

  • .drone.yml 必须显式声明 platformnode.runner_name,不要依赖“默认跑到哪台机器”这种隐式行为。
  • 示例正文不得写入真实密钥、令牌、仓库账号、镜像仓库地址、命名空间、邮箱、内网域名或其他敏感信息。
  • 复杂构建逻辑必须收敛到 scripts/ci/* 脚本,不要在 YAML 中堆叠大量长命令和复制逻辑。
  • 多步骤之间的依赖必须用 depends_on 写清楚,避免靠步骤顺序猜执行边界。
  • 前端构建步骤只负责生成产物,产物同步应放到单独汇总步骤,不要让并行步骤直接争用同一发布目录。
  • 后端 dotnet publish 与镜像构建应拆开,镜像步骤只消费最终发布目录,不再重新编译源码。

推荐组织方式

推荐把 pipeline 按以下层次组织:

  1. 环境准备
  2. 依赖恢复
  3. 编译与测试
  4. 产物汇总
  5. 打包与发布
  6. 部署

对应到 Drone 步骤时,建议这样理解:

  • 环境准备:验证 Docker、Kubernetes、共享缓存目录、脚本工具是否可用。
  • 依赖恢复:安装 Node 依赖、恢复 NuGet 缓存、准备 SDK。
  • 编译与测试:执行 pnpm buildpnpm testdotnet publish、桌面端打包等。
  • 产物汇总:把多个前端 dist、后端 publish、附加资源同步到最终目录。
  • 打包与发布:构建镜像、上传安装包、生成校验和、推送制品。
  • 部署:kubectl set image、调用部署脚本或其他环境发布动作。

多前端 + WebAPI 仓库的推荐边界

  • 每个前端应用独立一个构建步骤,便于并行和失败定位。
  • dotnet publish 独立成一个后端发布步骤。
  • 多前端产物统一由一个汇总步骤同步到 ClientApp 或发布目录。
  • 镜像打包只使用已经准备好的发布目录,不再读取分散的源码构建状态。

常见配置模板

模板一:Windows 64 单应用构建

适合 Electron、桌面工具或必须依赖 PowerShell/Windows SDK 的项目。

---
kind: pipeline
type: exec
name: desktop-win-release

platform:
  os: windows
  arch: amd64

node:
  runner_name: win-build

trigger:
  event:
    - push
    - tag
  ref:
    - refs/heads/main
    - refs/tags/v*

steps:
  - name: env-info
    commands:
      - powershell -NoProfile -ExecutionPolicy Bypass -File scripts/ci/windows-release.ps1 -Action env-info

  - name: restore-and-build
    environment:
      PNPM_STORE_DIR: C:/drone-cache/pnpm-store
      ELECTRON_CACHE: C:/drone-cache/electron
    commands:
      - powershell -NoProfile -ExecutionPolicy Bypass -File scripts/ci/windows-release.ps1 -Action build

  - name: upload-artifacts
    commands:
      - powershell -NoProfile -ExecutionPolicy Bypass -File scripts/ci/windows-release.ps1 -Action upload

推荐说明:

  • 使用 powershell 脚本统一处理环境打印、构建、上传,YAML 只保留步骤边界。
  • Windows runner 独有的缓存路径应集中在 environment 中,避免和 Linux、Mac 配置混用。
  • 如果项目有子模块,可补一个 git submodule update --init --recursive 步骤。

模板二:Mac ARM 构建与产物上传

适合 macOS 应用、签名流程、需要 Apple Silicon 环境的项目。

---
kind: pipeline
type: exec
name: desktop-mac-release

platform:
  os: darwin
  arch: arm64

node:
  runner_name: mac-arm-build

trigger:
  event:
    - push
    - tag
  ref:
    - refs/heads/main
    - refs/tags/v*

steps:
  - name: env-info
    commands:
      - bash scripts/ci/mac-release.sh env-info

  - name: generate-version-metadata
    commands:
      - bash scripts/ci/mac-release.sh generate-version

  - name: build
    environment:
      PNPM_STORE_DIR: /Users/runner/.pnpm-store
      ELECTRON_CACHE: /Users/runner/.cache/electron
    commands:
      - bash scripts/ci/mac-release.sh build

  - name: upload-artifacts
    commands:
      - bash scripts/ci/mac-release.sh upload

推荐说明:

  • 版本元数据、Git 提交摘要、签名准备等逻辑应继续放到脚本中,不要写成大量内联命令。
  • Mac runner 的路径、证书、签名上下文通常都更敏感,更要避免把真实值写进文档示例。

模板三:Linux amd64 WebAPI + 多 ClientApp + Docker/Kubernetes

适合前后端混合仓库、需要生成统一发布目录并进一步构建镜像的项目。

---
kind: pipeline
type: exec
name: webapi-build-and-deploy

platform:
  os: linux
  arch: amd64

node:
  runner_name: cn-build-02

trigger:
  event:
    - push
  branch:
    - main

steps:
  - name: docker-config
    commands:
      - bash scripts/ci/linux-prepare.sh

  - name: build-portal
    depends_on:
      - docker-config
    commands:
      - bash scripts/ci/build-portal.sh

  - name: build-admin
    depends_on:
      - docker-config
    commands:
      - bash scripts/ci/build-admin.sh

  - name: publish-backend
    depends_on:
      - docker-config
    commands:
      - bash scripts/ci/publish-backend.sh

  - name: sync-clientapp
    depends_on:
      - build-portal
      - build-admin
      - publish-backend
    commands:
      - bash scripts/ci/sync-clientapp.sh

  - name: package-image
    depends_on:
      - sync-clientapp
    commands:
      - bash scripts/ci/package-image.sh

  - name: deploy
    depends_on:
      - package-image
    commands:
      - bash scripts/ci/deploy.sh

推荐说明:

  • Linux runner 适合承接并行前端构建、dotnet publish、Docker 镜像和 Kubernetes 命令。
  • docker-config 只负责环境准备和认证,后续业务步骤都依赖它。
  • sync-clientapp 是多前端仓库的关键边界,负责把多个构建结果收敛到最终发布目录。
  • package-imagedeploy 一定要只依赖已经整理好的产物,不再从源码目录重新拼装。

触发与依赖组织建议

trigger 建议

  • 只做主干持续集成时,优先用 event + branch
  • 需要发布版本时,再增加 tagref 规则。
  • 如果同一仓库存在多条 pipeline,不同平台应根据分支、tag 或命名约定分清触发边界。

depends_on 建议

  • 只为真实依赖建立边界,不要让所有步骤串成一条长链。
  • 前端步骤之间能并行就并行,汇总步骤再统一等待。
  • 同一目录有写入冲突的步骤必须串行或通过中间产物隔离。
  • 如果某一步失败会让后续所有步骤都失效,应尽量把它前置,例如 Docker/Kubernetes 凭据准备。

常见坑

  • runner 选错,导致本该在 Windows 或 Mac 运行的脚本落到 Linux 上直接失败。
  • 把 Linux amd64 写成 “x86”,后续读者误以为是 32 位环境。
  • depends_on 没写清楚,前端汇总先于后端发布执行,最后发布目录缺文件。
  • 多个前端并行构建时直接写同一个 ClientApp 目录,互相覆盖产物。
  • 把共享缓存路径原样复制到其他 runner,结果 Windows、Mac 路径完全不兼容。
  • 把真实镜像仓库、deployment、namespace、项目名当成团队通用默认值照抄。
  • 在文档里只写“根目录 .drone.yml”,却不补充说明本仓库历史示例位于子项目目录,造成读者误解。

与现有框架内容的关系