Woodpecker CI 设计分析|一个 Go 编写的开源持续集成引擎

一、前言

大家好,这里是白泽。随着 Go 语言在云原生领域大放异彩,开发者逐渐将目光转移到了这门语言上,而容器则是云原生时代最核心的载体。

《Woodpecker CI 设计分析》系列文章将分析开源 CI 引擎 Woodpecker 的架构设计,探究 Go 协程是如何支持由 Workflow 定义的大量 Task 的频繁创建和调度。

Task 的一切活动都将在容器内进行。因此这个系列的文章也是帮助你开拓 Go 云原生领域编程的一柄利剑。

这是《Woodpecker CI 设计分析》系列的第一篇文章,主要讲解 Woodpecker 的整体架构设计和体验部署使用,后续文章将讲解核心组件源码设计,并从0开始仿写 Woodpecker 核心组件,欢迎追更~

公众号 「白泽talk」,白泽目前正在打造一个氛围良好的行业交流群,文章的更新也会提前预告,欢迎加入:622383022。

我也开源了一个 Go 学习仓库:包含 Go 各阶段学习文章、读书笔记、电子书、简历模板等,欢迎 star。

二、CI 配置前瞻

🌟 为了帮助理解,本文在讲述知识点时会对比 Woodpecker 和 GitHub Actions 两种持续集成方案,下文 Pipeline 和 Workflow 两个概念在不同的语境下有时可以当作相同语意,注意不要教条

🌟 关于 CD 这里不展开论述,因为 CD 与 CI 的不同点是业务关注点不同,关注的是 Pipeline 的不同的阶段,对于一个 CI Engine 来说,其实都是可以完成的,换句话说:CI 的阶段能构建镜像,自然也能发布镜像。

接下来对 GitHub 自带的持续集成(GitHub Actions)和 Woodpecker CI 展开介绍与对比,让你对 CI 有一个大致概念。

2.1 GitHub Actions Workflow for CI

GitHub 本身也是支持持续集成(CI)的,可以通过在项目 .github/workflows/ 路径下创建配置文件定制 Pipeline。

GitHub Actions Workflow 在每次推送到 main 分支时触发。它设置一个 Go 环境,构建应用程序,运行测试,最后部署。

yaml 复制代码
# .github/workflows/main.yml
name: CI
​
on:
  push:
    branches:
      - main
​
jobs:
  build:
    runs-on: ubuntu-latest
​
    steps:
    - name: Checkout Code
      uses: actions/checkout@v2
​
    - name: Set up Go
      uses: actions/setup-go@v2
      with:
        go-version: 1.17
      id: go
​
    - name: Build
      run: |
        # 在这里执行构建命令
        go build
​
    - name: Unit Tests
      run: |
        # 在这里执行单元测试命令
        go test ./...
​
    - name: Deploy
      run: |
        # 在这里执行部署命令
        echo "Deployment steps go here"

2.2 Woodpecker Pipeline for CI

Woodpecker 也是类似的,有一个 Woodpecker 管道配置文件,实现了与 GitHub Actions 相同的 CI 流程。

yaml 复制代码
# .woodpecker.yml
pipelines:
  main:
    trigger:
      branches:
        - main
​
    steps:
      - name: Checkout Code
        image: docker://alpine
        commands:
          - git clone $CI_REPOSITORY_URL $CI_WORKSPACE
​
      - name: Set up Go
        image: docker://golang:1.17
        commands:
          - cd $CI_WORKSPACE
          - go build
​
      - name: Unit Tests
        image: docker://golang:1.17
        commands:
          - cd $CI_WORKSPACE
          - go test ./...
​
      - name: Deploy
        image: docker://alpine
        commands:
          - echo "Deployment steps go here"

2.3 对比

GitHub Actions 提供有限的免费套餐,但对于较大或需要更多资源的项目,需要购买付费套餐。

🌟 Woodpecker 作为开源项目,通常可以在自己的服务器上自行部署和扩展,用户可以按照 Woodpecker 的文档或项目说明进行设置。

三、术语

看完第二节后,引入了不少 CI/CD 流程中的术语,这里以 Woodpecker 和 GitHub Actions 为例进行对比讲解。

  • CI: 持续集成是一种软件开发实践,旨在通过将代码集成到共享存储库中,然后自动构建和测试代码,来频繁地检测和解决集成问题。
  • CD: 是一种软件开发实践,旨在确保软件随时都能够通过自动化流程进行交付,但并不一定立即部署到生产环境。持续交付的目标是使软件交付的过程更加可靠和可重复,以便在需要时能够迅速进行部署。
  • Pipeline:

    • Woodpecker: 一个 Pipeline 是一系列有序的操作步骤,这些步骤按照定义的顺序执行。Pipeline 可以包含一个或多个 Workflow。
    • GitHub Actions: 一个 GitHub Actions Workflow 也可以看作是一个 Pipeline。在 GitHub Actions 中,Workflow 是 CI/CD 的基本单元。
  • Workflow:

    • Woodpecker: Workflow 是一组相关的步骤,通常代表了一个完整的 CI/CD 流程。在 Workflow 中,可以定义触发条件、环境变量和步骤顺序。
    • GitHub Actions: GitHub Actions Workflow 是 CI/CD 流程的定义,由一系列 jobs 和 steps 组成。Workflow 可以根据事件触发,例如 push、pull request 等。
  • Step:

    • Woodpecker: Step 是 Workflow 或 Pipeline 中的一个单一操作单元。每个 Step 代表了一个执行的任务,例如构建、测试或部署。
    • GitHub Actions: GitHub Actions 也使用 Step 的概念,每个 Step 包含一个或多个指令,用于执行特定的操作,例如运行脚本、调用 API 或使用预定义的 action。
  • 语法和配置:

    • Woodpecker: Woodpecker 使用 YAML 格式的配置文件定义 Pipeline 和 Workflow。配置文件包含了触发条件、步骤的定义以及其他设置。
    • GitHub Actions: GitHub Actions 同样使用 YAML 格式的配置文件,其中定义了 Workflow、Job 和 Step 的结构。GitHub Actions 还支持通过 UI 可视化配置。
  • 触发条件:

    • Woodpecker: 您可以定义 Workflow 的触发条件,例如当代码推送到特定分支时触发 Workflow。
    • GitHub Actions: 支持多种触发条件,例如 push、pull request、定时触发等。

四、Woodpecker 架构

🌟 在 Woodpecker 中,"Server"、"Forge" 和 "Agent" 是三个关键组件,它们各自承担不同的角色和功能:

  • Server:

    • 含义: Woodpecker Server 是整个 CI/CD 系统的核心组件,负责协调和管理整个构建和部署流程。
    • 功能:

      • 处理用户请求和操作,提供 Web 界面和 API。
      • 管理构建和部署的任务队列。
      • 与 Forge 和 Agent 进行通信,协调任务的执行。
  • Forge:

    • 含义: Forge 是与外部代码仓库集成的组件(GitHub、Gitea 等),负责从代码仓库拉取源代码、触发构建,并将构建结果反馈给 Woodpecker Server。
    • 功能:

      • 与代码仓库进行集成,监听代码变更并触发构建。
      • 将构建任务推送到 Woodpecker Server 的任务队列。
      • 向 Woodpecker Server 报告构建结果。
  • Agent:

    • 含义: Agent 是运行在构建和部署节点上的代理程序,负责执行具体的构建和部署任务。
    • 功能:

      • 从 Woodpecker Server 获取任务并执行。
      • 将任务执行的结果报告给 Woodpecker Server。
      • 与构建环境进行交互,执行构建脚本、部署应用等操作。

这三个组件协同工作,构成了 Woodpecker CI/CD 系统的基础架构。用户通过 Woodpecker Server 进行配置和管理,Forge 负责与代码仓库集成,Agent 负责执行实际的构建和部署任务。这种分工让 Woodpecker 可以支持多种代码仓库和构建环境,实现灵活的 CI/CD 流程。

🤔 思考几个问题:

  1. Agent 是如何从 Server 获取需要执行的 Step 的?(Agent 通过 Grpc 注册到 Server,调用 RPC 方法获取下一个待执行任务)
  2. 运行 Step 的环境是什么(每个 Step 都将启动一个 Container)
  3. 一个有多个 Step 的 Workflow 在 Server 上如何存放 Step?(Work Queue)
  4. 同时有多个项目 Repo 的 Pipeline 同时被 Server 调度运行时,多个 Workflow 分属不同的 Pipeline,而每个 Workflow 又拥有多个 Step,这些 Step 在 Server 的工作队列中是如何被并发调度的?(多协程 )

🌟 这些问题会在后续分析 Woodpecker 核心组件设计实现的文章中一一解答,同时我们也会手写自己的 Woodpecker。

五、Woodpecker 部署

官方部署文档中提供了多种部署方式,这里使用 docker-compose 部署。docker 的前置知识这里不再赘述。

🌟 往期收藏过百的 Docker 学习文章

docker | jenkins 实现自动化部署项目,后端躺着把运维的钱挣了!(上)

docker | jenkins 自动化CI/CD,后端躺着把运维的钱挣了!(下)

5.1 配置文件

  1. 创建 docker-compose.yml 配置文件。
yaml 复制代码
version: '3'
​
services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    ports:
      - 8000:8000
    volumes:
      - woodpecker-server-data:/var/lib/woodpecker/
    environment:
      - WOODPECKER_OPEN=true
      - WOODPECKER_HOST=${WOODPECKER_HOST}
      - WOODPECKER_GITHUB=true
      - WOODPECKER_GITHUB_CLIENT=${WOODPECKER_GITHUB_CLIENT}
      - WOODPECKER_GITHUB_SECRET=${WOODPECKER_GITHUB_SECRET}
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
​
  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    command: agent
    restart: always
    depends_on:
      - woodpecker-server
    volumes:
      - woodpecker-agent-config:/etc/woodpecker
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
​
volumes:
  woodpecker-server-data:
  woodpecker-agent-config:
  1. 创建同目录下创建 .env 环境变量文件。
shell 复制代码
WOODPECKER_HOST=http://localhost:8000
WOODPECKER_AGENT_SECRET=e61a65af26d998aa303a7b4ce4015ecde83d3caaa3354a91a1120a09e961269e
WOODPECKER_GITHUB_CLIENT=在GitHub生成
WOODPECKER_GITHUB_SECRET=在GitHub生成

5.2 OAuth App

🌟 OAuth App 是什么:

在 GitHub 的上下文中,OAuth App 是一种允许开发者使用 GitHub 用户帐户进行身份验证和访问的应用程序。开发者可以创建自己的 OAuth App,并通过 GitHub 的 OAuth 流程获得对用户帐户的有限访问权限。

OAuth App 在 GitHub 上注册后,会获得一个客户端 ID 和一个客户端密钥(Client Secret)。这些凭据用于在用户授权后获取访问令牌,以便应用程序可以代表用户执行某些操作。

在当前场景中,Woodpecker 为了获得访问 GitHub 的能力(监听仓库变动等),需要在 GitHub 开发者配置中心注册为一个 Oauth App。

🌟 创建 OAuth App:

获取 WOODPECKER_GITHUB_CLIENTWOODPECKER_GITHUB_SECRET 的值通常涉及在 GitHub 上创建 OAuth App。以下是如何获取这两个值的步骤:

  1. 登录到您的 GitHub 帐户。
  2. 转到 GitHub Developer Settings
  3. 单击右上角的 "New OAuth App"。
  4. 在 "Application name" 中输入应用程序的名称。
  5. 在 "Homepage URL" 中输入应用程序的主页 URL。这可以是任何有效的 URL,因为我是本地部署,因此填入http://localhost:8000 作为占位符。
  6. 在 "Authorization callback URL" 中输入授权回调 URL。这是 GitHub 在用户授权后将用户重定向回您的应用程序的 URL。如果在本地测试,可以使用 http://localhost:8000/authorize 作为占位符。
  1. 单击 "Register application"。
  1. 您将在页面上看到生成的 "Client ID" 和 "Client Secret"。将它们分别赋值给 .env 文件的 WOODPECKER_GITHUB_CLIENTWOODPECKER_GITHUB_SECRET
shell 复制代码
# .env
WOODPECKER_GITHUB_CLIENT=<Your Client ID>
WOODPECKER_GITHUB_SECRET=<Your Client Secret>

5.3 部署与登录

运行 docker-compose up -d 命令后将于本机 docker 上成功部署 woodpecker。

  • 访问 http://localhost:8000/ 点击 Login。
  • 跳转至 OAuth 授权页面完成授权登录。
  • 自动跳转至 Repo 管理页面。

5.4 体验持续集成(CI)

  • 点击页面上 Add repository 可以看到 OAuth 关联账号拥有的仓库列表,查找一个事先准备好的 test-repo。
  • 点击 Enable 提示报错。

🌟 查看 docker 日志分析原因,提示创建 webhook 需要一个公共可访问的 Host 地址,"localhost" 不满足。

复制代码
docker logs woodpecker_woodpecker-server_1
  • 代替方案

    1. 将上述部署行为放到一台可以被公共访问的服务器上进行。
    1. 🌟 将 GitHub 替换为 Gitea,同样部署在 localhost 进行测试。(这里选择这种方案)

5.5 本地部署 Gitea 代替 GitHub

Gitea 是一个轻量级的、自助的 Git 服务。它是一个开源的、基于 Go 语言的项目,提供了类似于 GitHub、GitLab 等平台的版本控制仓库管理功能。Gitea 允许您在自己的服务器上架设一个 Git 服务,以便团队或个人能够方便地进行代码托管、协作和版本控制。(GitHub 🌟 Star 40k+)

白泽曾经在 Gitea 有过一段时间的实习,后续可以给大家分享一下~

🌟 在本地部署 Gitea 之后,白泽在继续这个 CI 体验流程时遇到了 Woodpecker 和 Gitea 本地通信时一个访问授权 BUG,事后,我发现整个流程也十分值得记录分享。

所以下一篇文章白泽将讲解解决 BUG 的流程,过程中会配合阅读 Gitea & Woodpecker 的代码。为大家梳理使用开源软件遇到问题时的解决思路和步骤。

六、小结

🌟 未完待续,欢迎追更。

公众号 「白泽talk」,白泽目前正在打造一个氛围良好的行业交流群,文章的更新也会提前预告,欢迎加入:622383022。

我也开源了一个 Go 学习仓库:包含 Go 各阶段学习文章、读书笔记、电子书、简历模板等,欢迎 star。

相关推荐
小小张说故事2 分钟前
BeautifulSoup:Python网页解析的优雅利器
后端·爬虫·python
怒放吧德德3 分钟前
后端 Mock 实战:Spring Boot 3 实现入站 & 出站接口模拟
java·后端·设计
biyezuopinvip15 分钟前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
UrbanJazzerati16 分钟前
Python编程基础:类(class)和构造函数
后端·面试
一只大侠的侠32 分钟前
Flutter开源鸿蒙跨平台训练营 Day11从零开发商品详情页面
flutter·开源·harmonyos
楚兴33 分钟前
MacBook M1 安装 OpenClaw 完整指南
人工智能·后端
一只大侠的侠1 小时前
React Native开源鸿蒙跨平台训练营 Day18自定义useForm表单管理实战实现
flutter·开源·harmonyos
一只大侠的侠1 小时前
React Native开源鸿蒙跨平台训练营 Day20自定义 useValidator 实现高性能表单验证
flutter·开源·harmonyos
Java编程爱好者1 小时前
2026版Java面试八股文总结(春招+秋招+社招),建议收藏。
后端
朱昆鹏1 小时前
开源 Claude Code + Codex + 面板 的未来vibecoding平台
前端·后端·github