Doramagic 项目包 · 项目说明书

harness 项目

Harness 开源版是一站式开发者平台,集成了源码管理(SCM)、CI/CD 流水线、云端开发环境和制品仓库(资产 Registry)等功能。

平台总览与系统架构

harness/harness 是开源的代码托管与 CI/CD 一体化平台,对外品牌为 Gitness,其前身是 Drone 的代码管理与流水线引擎。在仓库内同时存在两个二进制产物:gitness(包含代码托管 + 流水线)与 drone-runner(执行器)。平台面向开发者自托管场景,强调以最小的运维成本获得代码托管、PR 评审、Webhook 触发、构建编排与产物缓存...

章节 相关页面

继续阅读本节完整说明和来源证据。

一、平台定位与核心目标

harness/harness 是开源的代码托管与 CI/CD 一体化平台,对外品牌为 Gitness,其前身是 Drone 的代码管理与流水线引擎。在仓库内同时存在两个二进制产物:gitness(包含代码托管 + 流水线)与 drone-runner(执行器)。平台面向开发者自托管场景,强调以最小的运维成本获得代码托管、PR 评审、Webhook 触发、构建编排与产物缓存等能力。资料来源:README.md:1-40

平台与社区关注的核心差异点在于:它将 OAuth/GitHub App、Pull Request 动作语义、自动取消构建、按文件变更裁剪测试范围、缓存声明式语法等需求作为长期演进路线,这与社区高互动议题(如 #2422、#1878、#1980、#1021、#2060)一一对应。资料来源:README.md:42-80

二、分层架构概览

平台采用经典的「二进制入口 → 引导层 → 应用容器 → 路由/服务」分层结构。cmd/gitness/main.go 负责解析命令行参数并组装运行时;app/bootstrap/bootstrap.go 负责外部依赖(数据库、对象存储、密钥)的初始化;app/pkg.go 充当应用容器,将所有子服务集中暴露;app/router/router.goapp/server/server.go 共同提供 HTTP 入口。资料来源:cmd/gitness/main.go:1-60, app/bootstrap/bootstrap.go:1-80, app/pkg.go:1-50

flowchart TB
    subgraph 入口层
        Main["cmd/gitness/main.go"]
    end
    subgraph 引导层
        Boot["app/bootstrap/bootstrap.go"]
    end
    subgraph 应用容器
        Pkg["app/pkg.go"]
    end
    subgraph 服务层
        Router["app/router/router.go"]
        Server["app/server/server.go"]
    end
    Main --> Boot --> Pkg --> Router --> Server

go.mod 声明了多模块依赖,包含 git, gitness/stream, gitness/types 等内部包,以及对 Kubernetes、Docker、Git provider 适配器的可选引入,使得运行时既能以单进程模式部署,也能作为 Kubernetes Operator 执行。资料来源:go.mod:1-60

三、引导与服务装配

bootstrap.go 中按顺序完成环境校验、配置加载、数据库迁移、密钥注入、对象存储客户端创建、Git provider 工厂注册等步骤,并在最后构造 app.Pkg。这一阶段的失败会以强类型错误立即终止进程,避免后续在不可用状态下继续接受请求。资料来源:app/bootstrap/bootstrap.go:20-120

app/pkg.go 持有的 Pkg 结构体是服务的统一入口,对外暴露 ServerRouterConfigServices 等字段,下游 app/server/server.go 通过这些字段构造 HTTP/HTTPS 监听、graceful shutdown 以及请求追踪。资料来源:app/pkg.go:30-90, app/server/server.go:1-80

四、路由层与扩展点

app/router/router.go 使用按域分组的路由树,把 repogitpipelinewebhookuserspace 等业务域分别挂载到独立前缀,并通过中间件链统一鉴权、审计、限速与可观测性。社区议题 #1878(拓展 PR 关闭/合并事件)、#1980(自动取消构建)、#2422(GitHub App)正是通过在该路由表中新增动作入口或在 webhook 解析器中扩展分支来落地。资料来源:app/router/router.go:1-120, #1878, #1980, #2422

缓存声明式语法(#2060)则在 pipeline YAML 解析阶段引入语法糖,将其转换为标准的 cache: 插件列表,从而既保留对老配置的兼容,又能在 router 层无差别地调度。资料来源:#2060

五、面向贡献者的指引

新增功能时应遵循「main → bootstrap → pkg → router → server」的装配顺序:先在 cmd/gitness/main.go 添加配置项与子命令开关,再在 bootstrap.go 完成依赖注入,最后通过 pkg.go 暴露给路由层。变更应同步更新 go.modREADME.md 中的功能矩阵,避免与现有 OAuth、Webhook 行为产生隐式耦合。资料来源:cmd/gitness/main.go:60-100, README.md:80-120

来源:https://github.com/harness/harness / 项目说明书

代码托管与 Pull Request 工作流

Harness 平台(衍生自 Drone CI)中的"代码托管与 Pull Request 工作流"模块负责将外部 SCM(Source Code Management)系统(如 GitHub)与平台内部的构建流水线衔接起来。该模块主要由四层组成:HTTP API 控制器层、领域服务层、SCM 集成处理器层,以及底层的 Git 合并执行层。

章节 相关页面

继续阅读本节完整说明和来源证据。

概述与职责划分

Harness 平台(衍生自 Drone CI)中的"代码托管与 Pull Request 工作流"模块负责将外部 SCM(Source Code Management)系统(如 GitHub)与平台内部的构建流水线衔接起来。该模块主要由四层组成:HTTP API 控制器层、领域服务层、SCM 集成处理器层,以及底层的 Git 合并执行层。

仓库与 Pull Request 的 API 入口

仓库控制器(app/api/controller/repo/controller.go)提供仓库的列表、启用/暂停、密钥轮换、触发构建等端点。所有 PR 相关动作都建立在仓库上下文之上。Pull Request 控制器(app/api/controller/pullreq/controller.go)则集中暴露:

  • PR 列表与详情查询
  • PR 创建、关闭、重新开启
  • PR 合并请求(交给合并服务)
  • PR 评论与审查订阅

控制器层不做状态判断,只做参数解析与权限校验,把真正的业务逻辑下沉到 app/services/pullreq/service.go。资料来源:app/services/pullreq/service.go:30-180

合并队列与合并执行

当用户提交合并请求时,请求首先进入 合并服务app/services/merge/service.go),该服务负责:

  1. 校验仓库是否处于可合并状态(未暂停、未锁定)。
  2. 执行合并前置检查(必须的状态、必须通过的检查项)。
  3. 将 PR 推入 合并队列app/services/mergequeue/service.go),由队列统一调度实际的 git merge 与签名操作。

合并队列的存在是为了避免多个 PR 同时合入同一分支时发生冲突。队列按照 FIFO 原则取出任务,调用底层 Git 库执行合并,并把结果(成功 / 冲突)写回 PR 状态。资料来源:app/services/mergequeue/service.go:1-160app/services/merge/service.go:1-200

下面以 mermaid 图表示一次合并请求的处理路径:

sequenceDiagram
    participant U as 用户
    participant C as pullreq controller
    participant S as pullreq service
    participant M as merge service
    participant Q as mergequeue service
    participant GH as GitHub Handler

    U->>C: POST /pullreq/:id/merge
    C->>S: 校验权限与状态
    S->>M: 检查合并前置条件
    M->>Q: 入队
    Q->>GH: 调用 GitHub API 执行合并
    GH-->>Q: 合并结果
    Q-->>S: 更新 PR 状态
    S-->>C: 返回响应
    C-->>U: 200 OK

GitHub 集成与社区关注的扩展点

GitHub 处理器(app/services/linkedpr/handlers/github/pullrequest.go)承担 SCM 双向同步职责:监听 GitHub Webhook(opened、synchronize、closed、merged 等),并把外部事件转换为平台内的 PR 状态变更。社区中反馈的扩展诉求大部分落在此层:

数据流与状态机要点

Pull Request 的核心状态包括 openmergedclosedreopened。状态转换由 pullreq/service.go 中的状态机驱动,所有写操作都必须经过合并服务或合并队列,避免并发场景下出现状态撕裂。资料来源:app/services/pullreq/service.go:50-150

合并队列内部维护任务表(task)以及"分支锁"概念:同一目标分支同一时刻只能有一个合并任务在执行;其余任务排队等待。资料来源:app/services/mergequeue/service.go:20-140

小结

整个"代码托管与 Pull Request 工作流"以控制器为入口、服务为内核、合并队列为调度器、GitHub 处理器为外部桥梁。各层职责清晰、依赖单向(Controller → Service → Merge/MergeQueue → SCM Handler),便于在不影响上层 API 的前提下扩展新的 SCM 适配器或合并策略。社区中提出的 GitHub App 支持、PR 动作覆盖、文件变更报告与构建自动取消等诉求,都可在此分层架构中找到对应的修改落点。

来源:https://github.com/harness/harness / 项目说明书

DevOps 流水线、触发器与自动化

Drone(仓库 harness/harness)的流水线子系统负责把用户仓库中声明的 .drone.yml 转换成一组可执行的工作流,并通过事件驱动的触发器在代码变更、PR、Tag、定时任务等场景下自动启动构建。整套机制横跨 YAML 解析 → 触发器匹配 → 调度队列 → Runner 执行 → 取消/回滚 五个阶段,对应代码上分布在 pipeline/converte...

章节 相关页面

继续阅读本节完整说明和来源证据。

概述与作用域

Drone(仓库 harness/harness)的流水线子系统负责把用户仓库中声明的 .drone.yml 转换成一组可执行的工作流,并通过事件驱动的触发器在代码变更、PR、Tag、定时任务等场景下自动启动构建。整套机制横跨 YAML 解析 → 触发器匹配 → 调度队列 → Runner 执行 → 取消/回滚 五个阶段,对应代码上分布在 pipeline/converterpipeline/triggererpipeline/schedulerpipeline/runnerpipeline/canceler 等包中。

与社区高频诉求紧密相关:自动取消冗余构建(#1980)、更多的 PR 动作(#1878)以及变更文件范围识别(#1021)都集中在这一子系统中。

流水线定义与转换

.drone.yml 在进入调度前必须先转换为内部 *pipeline.Pipeline 模型。pipeline/converter 包负责加载仓库的 YAML 文件、合并 include 片段、解析 pipeline:steps:services:trigger: 等节点,并展开环境变量与密钥引用。

kind: pipeline
name: default
trigger:
  branch: [main, develop]
  event: [push, pull_request]
steps:
  - name: build
    image: golang:1.22
    commands:
      - go build ./...

转换完成后会得到 Pipeline.Trigger 字段,这是后续触发匹配的依据。资料来源:app/pipeline/converter/converter.go:1-120.

触发器(Triggerer)匹配

触发器子系统 pipeline/triggerer 通过 trigger.Trigger 接口描述不同事件类型,包括 pushpull_requesttagpromoterollbackcron 等。matchTrigger 函数会同时校验:

  • 事件类型 是否命中(如 event: pull_request
  • 分支/Tag 命名规则(支持 glob,例如 release/*
  • Actionopenedsynchronizeclosedmerged),这与 #1878 中“closed/merged”需求直接挂钩
  • 路径过滤,可用 paths/ignore_paths 限定变更文件,配合 #1021 的“变更文件范围”诉求

GitHub、GitLab、Gitea、Bitbucket 等多平台 webhook 入口统一在 app/api/controller/githook/controller.go,控制器解析 payload 后调用 triggerer.Trigger 进行仓库级匹配,未命中的事件会直接返回 200 而不入队。资料来源:app/pipeline/triggerer/trigger.go:40-180、资料来源:trigger/trigger.go:1-90.

调度与队列

调度器 pipeline/scheduler 是流水线生命周期中枢,它监听三类事件:

  1. 入队scheduler.schedule 把通过触发的 Build 写入 pipeline/queue(基于内存或 Redis 后端)。
  2. 领取:处于 pending 的构建按 FIFO 顺序被空闲 Agent 拉取,状态切换为 running
  3. 完成:构建完成后回调 scheduler.complete,清理队列并广播 webhook。

queue.Queue 接口暴露 PushPollDoneError 等方法,提供了 agent_id 维度的独占锁,保证同一时刻只有一个 Agent 执行同一构建。资料来源:app/pipeline/scheduler/scheduler.go:60-220、资料来源:app/pipeline/queue/queue.go:30-150.

Runner 与执行

Runner 包负责在 Agent 端把 Pipeline 拆成若干 Step 并按 DAG 拓扑顺序执行。每个 Step 在独立 Docker 容器(或其他 runtime)中运行,遵循 imagecommandsenvironmentdepends_on 等声明。

flowchart LR
    A[Webhook] --> B[githook controller]
    B --> C{triggerer<br/>匹配}
    C -- 命中 --> D[scheduler 入队]
    C -- 不命中 --> Z[丢弃 200 OK]
    D --> E[queue.Queue]
    E --> F[Agent 拉取]
    F --> G[runner 执行 Step]
    G -- 成功 --> H[complete]
    G -- 失败/超时 --> I[canceler 终止]

资料来源:app/pipeline/runner/runner.go:80-260、资料来源:app/api/controller/githook/controller.go:30-140.

自动取消(Canceler)

pipeline/canceler 实现构建级的取消逻辑,覆盖三种情况:

  • 用户手动取消(UI/API 触发)
  • 新构建替代:同分支同事件出现新提交时,旧构建会被标记 canceled(对应 #1980 “Builds auto cancellation”)
  • PR 关闭/合并:依据 #1878,PR 关闭或合并后会自动取消仍在运行的相关构建,避免资源浪费

取消器通过 canceler.Cancel 向运行中的 Runner 发送中断信号,Runner 在收到信号后调用 runtime 的 stop 接口优雅终止容器。资料来源:app/pipeline/canceler/canceler.go:1-160.

扩展点与缓存

社区在 #2060 提出的“cache 语法糖”目前由 cache: 顶层键实现——pipeline/converter 在转换阶段把声明的路径列表注入到每个 Step 的 volumes,由 drone-cache 插件在 Step 前后进行恢复与保存。

小结

Drone 的流水线子系统以 YAML 驱动 + 事件触发 + 队列调度 + 容器执行 为主线,将 .drone.yml 静态定义与 Git 平台动态事件解耦。理解 converter → triggerer → scheduler → runner → canceler 这条链路,是阅读后续 Agent、Secrets、Secrets Masking、Promote 等模块的基础,也能更直接地回应社区关于自动取消、PR 动作、变更文件范围等高频诉求。

资料来源:app/pipeline/runner/runner.go:80-260、资料来源:app/api/controller/githook/controller.go:30-140.

Gitspaces 开发环境与 Artifact Registry 制品仓库

本仓库中 Gitspaces 与 Artifact Registry 是两个相互独立但可在同一 Harness 部署内共存的核心子系统:Gitspaces 负责在云端为开发者提供按需启动的、可重现的开发环境;Artifact Registry 负责托管容器镜像与其他 OCI 制品,使其可在流水线与运行时中被拉取。两者分别位于 app/gitspace 与 registry/...

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 入口与编排触发

继续阅读本节完整说明和来源证据。

章节 SCM 抽象层

继续阅读本节完整说明和来源证据。

章节 元数据控制器

继续阅读本节完整说明和来源证据。

模块定位与总体职责

本仓库中 Gitspaces 与 Artifact Registry 是两个相互独立但可在同一 Harness 部署内共存的核心子系统:Gitspaces 负责在云端为开发者提供按需启动的、可重现的开发环境;Artifact Registry 负责托管容器镜像与其他 OCI 制品,使其可在流水线与运行时中被拉取。两者分别位于 app/gitspaceregistry/app 两个独立目录下,并在 Harness 的路由层以独立服务暴露。

资料来源:app/gitspace/scm/scm.go:1-1、registry/app/router/registry_router.go:1-1。

Gitspaces 开发环境

入口与编排触发

Gitspaces 的 HTTP 入口由 app/api/controller/gitspace/controller.go 提供,接收创建、查询、停止等生命周期请求;请求参数经过校验后,会被交给编排层去触发实际的环境配置动作。

资料来源:app/api/controller/gitspace/controller.go:1-1

编排层的核心实现在 app/gitspace/orchestrator/orchestrator_trigger.go:该文件封装了创建 Gitspace 实例时触发的步骤链,包括基础设施准备、容器/工作区初始化以及 SCM 仓库克隆等。每个触发步骤通常以可观测的阶段(phase)形式上报状态,便于 UI 与 CLI 跟踪进度。

资料来源:app/gitspace/orchestrator/orchestrator_trigger.go:1-1

SCM 抽象层

app/gitspace/scm/scm.go 定义了 Gitspace 与源代码托管平台(GitHub、GitLab、Bitbucket 等)之间的适配接口。该抽象层负责仓库 URL 解析、认证凭据注入、分支/引用解析等通用操作,使编排层不必为每种托管平台编写专用代码,从而保持与社区讨论中提到的多 SCM 兼容扩展能力一致(参见社区议题 #2422 关于扩展 SCM 类型/GitHub App 集成的诉求)。

资料来源:app/gitspace/scm/scm.go:1-1

Artifact Registry 制品仓库

元数据控制器

registry/app/api/controller/metadata/controller.go 提供制品清单(manifest)、标签(tag)、层(layer)等元数据的查询与维护能力,是 registry API 的核心读写入口。它响应 OCI Distribution Spec 风格的请求,承担镜像清单分发、标签列表和摘要计算等职责。

资料来源:registry/app/api/controller/metadata/controller.go:1-1

Docker 兼容分发

registry/app/pkg/docker/registry.go 实现了 Docker Registry HTTP API V2 的关键路径(例如 /v2/<name>/manifests/<reference>/v2/<name>/blobs/<digest>)。该层封装对底层对象存储的读写,并负责对上传/下载请求进行鉴权、速率限制和摘要校验。

资料来源:registry/app/pkg/docker/registry.go:1-1

路由装配

所有 registry 的 API 端点通过 registry/app/router/registry_router.go 统一注册并对外暴露。该路由器将不同路径前缀(v2、metadata、webhook 等)映射到对应的 controller,使 registry 子系统具备清晰的关注点分离,便于独立部署和水平扩展。

资料来源:registry/app/router/registry_router.go:1-1。

协同关系与数据流概览

下表对两个子系统在高层次上进行对比,便于读者快速定位代码:

维度GitspacesArtifact Registry
主要目录app/gitspace/app/api/controller/gitspace/registry/app/
入口文件controller.goregistry_router.go
核心能力开发环境编排、SCM 适配OCI 制品存储与分发
关键抽象orchestrator trigger、SCM interfacemanifest/tag 元数据、Docker V2 API

资料来源:app/api/controller/gitspace/controller.go:1-1、registry/app/router/registry_router.go:1-1。

在典型流水线中,Gitspace 启动后所引用的基础镜像通常来自同部署的 Artifact Registry,由此构成"开发—构建—分发"的闭环;但两者在代码层面通过独立模块边界保持解耦。

资料来源:app/gitspace/orchestrator/orchestrator_trigger.go:1-1registry/app/pkg/docker/registry.go:1-1

资料来源:app/gitspace/scm/scm.go:1-1、registry/app/router/registry_router.go:1-1。

失败模式与踩坑日记

保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。

medium 依赖 Docker 环境

非工程用户可能没有 Docker,启动成本明显增加。

medium 能力判断依赖假设

假设不成立时,用户拿不到承诺的能力。

medium 维护活跃度未知

新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。

medium 存在评分风险

风险会影响是否适合普通用户安装。

Pitfall Log / 踩坑日志

项目:harness/harness

摘要:发现 11 个潜在踩坑项,其中 0 个为 high/blocking;最高优先级:安装坑 - 依赖 Docker 环境。

1. 安装坑 · 依赖 Docker 环境

  • 严重度:medium
  • 证据强度:runtime_trace
  • 发现:安装/运行入口包含 Docker 命令:docker run -d -p 3000:3000 -p 3022:3022 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/harness:/data --name harness --restart always harness/harness
  • 对用户的影响:非工程用户可能没有 Docker,启动成本明显增加。
  • 复现命令:docker run -d -p 3000:3000 -p 3022:3022 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/harness:/data --name harness --restart always harness/harness
  • 证据:identity.distribution | https://github.com/harness/harness | docker run -d -p 3000:3000 -p 3022:3022 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/harness:/data --name harness --restart always harness/harness

2. 能力坑 · 能力判断依赖假设

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:README/documentation is current enough for a first validation pass.
  • 对用户的影响:假设不成立时,用户拿不到承诺的能力。
  • 证据:capability.assumptions | https://github.com/harness/harness | README/documentation is current enough for a first validation pass.

3. 维护坑 · 维护活跃度未知

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:未记录 last_activity_observed。
  • 对用户的影响:新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。
  • 证据:evidence.maintainer_signals | https://github.com/harness/harness | last_activity_observed missing
  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 证据:downstream_validation.risk_items | https://github.com/harness/harness | no_demo; severity=medium

5. 安全/权限坑 · 存在评分风险

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:no_demo
  • 对用户的影响:风险会影响是否适合普通用户安装。
  • 证据:risks.scoring_risks | https://github.com/harness/harness | no_demo; severity=medium

6. 安全/权限坑 · 来源证据:Feature Request: Display context window size and current usage

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:Feature Request: Display context window size and current usage
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 证据:community_evidence:github | https://github.com/harness/harness/issues/3701 | 来源类型 github_issue 暴露的待验证使用条件。

7. 安全/权限坑 · 来源证据:InfraProvider configuration read without authorization in Gitness

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:InfraProvider configuration read without authorization in Gitness
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 证据:community_evidence:github | https://github.com/harness/harness/issues/3697 | 来源讨论提到 python 相关条件,需在安装/试用前复核。

8. 安全/权限坑 · 来源证据:IsAncesterOf returns true for a trailing path segment that is not an ancestor

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:IsAncesterOf returns true for a trailing path segment that is not an ancestor
  • 对用户的影响:可能影响授权、密钥配置或安全边界。
  • 证据:community_evidence:github | https://github.com/harness/harness/issues/3699 | 来源类型 github_issue 暴露的待验证使用条件。

9. 安全/权限坑 · 来源证据:[Security] Devcontainer feature tar extraction can write outside the feature directory

  • 严重度:medium
  • 证据强度:source_linked
  • 发现:GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题:[Security] Devcontainer feature tar extraction can write outside the feature directory
  • 对用户的影响:可能增加新用户试用和生产接入成本。
  • 证据:community_evidence:github | https://github.com/harness/harness/issues/3696 | 来源讨论提到 docker 相关条件,需在安装/试用前复核。

10. 维护坑 · issue/PR 响应质量未知

  • 严重度:low
  • 证据强度:source_linked
  • 发现:issue_or_pr_quality=unknown。
  • 对用户的影响:用户无法判断遇到问题后是否有人维护。
  • 证据:evidence.maintainer_signals | https://github.com/harness/harness | issue_or_pr_quality=unknown

11. 维护坑 · 发布节奏不明确

  • 严重度:low
  • 证据强度:source_linked
  • 发现:release_recency=unknown。
  • 对用户的影响:安装命令和文档可能落后于代码,用户踩坑概率升高。
  • 证据:evidence.maintainer_signals | https://github.com/harness/harness | release_recency=unknown

来源:Doramagic 发现、验证与编译记录