• 使用 Woodpecker 与 Gitea 搭建纯开源的 CI 流程|极限降本


    🌟 最近开源了一个挂机冒险游戏《模拟龙生》,有热心同学不仅帮忙做优化,还连夜在给游戏加页面,泪目。详见文末小结部分。

    一、前言

    image-20240115204716944

    大家好,这里是白泽。这篇文章是《Woodpecker CI 设计分析》的续接,将通过阅读 Woodpecker 和 Gitea 的源代码,解决前一篇文章最后遗留的问题,并最终实现本地部署 Woodpecker 和 Gitea,实现持续集成(CI)全流程使用开源技术,极限降本。

    image-20240115214403769

    遗留问题:

    通过 docker-compose 部署 Woodpecker 并将 GitHub 作为 Forge 平台,模拟 CI 流程的时候,遇到了一个告警:提示创建 webhook 需要一个公共可访问的 Host 地址,本地部署的 Woodpecker 无法通过 webhook 监听 GitHub 中 repo 的变动,也就无法使用持续集成的能力了。

    🌟 因此这里将架构图中的 Forge 部分的 GitHub 源换成 Gitea 源,全部使用开源项目,彻底拥抱开源,极限降本。

    image-20240116173320678

    二、本地部署 Gitea

    访问 Gitea 的官方文档,找到 Installation with Docker 部分的内容:

    version: "3"
    
    networks:
      gitea:
        external: false
    
    services:
      server:
        image: gitea/gitea:main-nightly
        container_name: gitea
        environment:
          - USER_UID=1000
          - USER_GID=1000
        restart: always
        networks:
          - gitea
        volumes:
          - ./gitea:/data
          - /etc/timezone:/etc/timezone:ro
          - /etc/localtime:/etc/localtime:ro
        ports:
          - "3000:3000"
          - "222:22"
    

    通过 docker-compose 部署运行:

    docker-compose up -d
    

    🌟 访问 http://0.0.0.0:3000 后,点击安装,然后注册用户,便可以进入到 Gitea 的使用页面,到现在为止看似没有任何问题

    image-20240120154144766

    三、OAuth 是什么

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

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

    在当前场景中,Woodpecker 为了获得访问 Gitea 的能力(监听仓库变动等),需要在 Gitea 的 Setting 注册一个 Oauth App。

    image-20240120160646053

    这里的 Client IDClient Secret 将用于下一节 Woodpecker 的部署。并且 Redirect URI 设置为 Woodpecker 的授权地址。

    这里涉及到一些配置均是与 OAuth2 授权流程相关的,包括下文部署 Woodpecker 的时候,也会涉及。

    🌟 由于篇幅原因,下一篇文章我将讲解在本地部署成功后,使用 Gitea 用户登录 Woodpecker 平台时,OAuth2 认证的流程,以解释这些配置的作用。这里按下不表,先照着操作即可。

    四、本地部署 Woodpecker

    由于《Woodpecker CI 设计分析》这篇文章已经讲解了如何通过 docker-compose 本地部署,这里不再赘述这种方式,但出于学习目的,这里我们通过项目源代码进行编译运行。

    相比 docker,单步调试能帮助你快速理清楚开源项目的流程。

    4.1 部署 & 运行

    • 克隆项目
    git clone git@github.com:woodpecker-ci/woodpecker.git
    
    • 查看 Woodpecker 的文档,找到 Preparation for local development

    🌟 很多同学学习或者参与开源项目的第一步就被拦住了,如何成功本地编译运行一个开源项目,是成功的一半,接下来跟着白泽一步一步阅读文档,希望你今后也能独立完成启动其他项目的流程。

    1. 要求 Golang >= 1.20 版本。
    2. Install make:make 是一个构建工具,用于自动化项目的编译和构建过程。它通常使用名为 Makefile 的文件来定义一系列规则和依赖关系,以描述如何生成目标文件(通常是可执行文件或库)。
    3. Install Node.js & pnpm:需要 Node 环境,以及 Node 的包管理工具 pnpm,也是按照文档要求安装即可。
    4. 最重要的:在项目根目录创建 .env 文件,存放配置变量,下面是白泽创建的配置列表,照着官方文档的改,除了要修改 HOST 相关变量,还要注意将 GitHub 源切换成 Gitea 源。
    WOODPECKER_OPEN=true
    WOODPECKER_ADMIN=baize
    
    # if you want to test webhooks with an online forge like GitHub this address needs to be accessible from public server
    WOODPECKER_HOST=http://0.0.0.0:8000
    
    # github (sample for a forge config - see /docs/administration/forge/overview for other forges)
    -WOODPECKER_GITHUB=true
    -WOODPECKER_GITHUB_CLIENT=
    -WOODPECKER_GITHUB_SECRET=
    +WOODPECKER_GITEA=true
    +WOODPECKER_GITEA_URL=http://0.0.0.0:3000
    +WOODPECKER_GITEA_CLIENT=
    +WOODPECKER_GITEA_SECRET=
    
    # agent
    WOODPECKER_SERVER=0.0.0.0:9000
    WOODPECKER_AGENT_SECRET=a-long-and-secure-password-used-for-the-local-development-system
    WOODPECKER_MAX_WORKFLOWS=1
    
    # enable if you want to develop the UI
    # WOODPECKER_DEV_WWW_PROXY=http://0.0.0.0:8010
    
    # used so you can login without using a public address
    WOODPECKER_DEV_OAUTH_HOST=http://0.0.0.0:8000
    
    # disable health-checks while debugging (normally not needed while developing)
    WOODPECKER_HEALTHCHECK=false
    
    # WOODPECKER_LOG_LEVEL=debug
    # WOODPECKER_LOG_LEVEL=trace
    
    1. 编译启动项目(前一篇文章已经讲过 Woodpecker 的架构图了,server & agent 的概念不再赘述),当然这篇文章的第二张图片是帮助大家回忆的 Woodpecker 架构图。
    # 启动server服务
    go run ./cmd/server/main.go
    # 启动agent服务
    go run ./cmd/agent/main.go
    

    4.2 使用

    • 访问 http://0.0.0.0:8000 进入 Woodpecker 登录页面,点击 Login 图标。🌟 但是再次返回到这个页面,无法跳转至 Gitea 授权认证页面!

    image-20240120163321446

    4.2.1 docker 运行的弊端

    🌟 还记得这篇文章在通过 docker-compose 部署 Gitea 成功后,白泽提了一句看似没有任何问题

    由于白泽已经踩过坑了,因此上文 Woodpecker 已经是本地编译运行的,也是方便你接下来跟着我单步调试。要是 Woodpecker 也用 docker 部署,一旦遇到问题,看 docker 日志排错效率太低了!

    # 在点击Login未果后,我们在server端的控制台看到了包含这条信息的日志,全局搜索到它的位置,定位到错误日志的打印函数,从而定位到断点应该打在哪里
    cannot authenticate user
    

    image-20240120170445778

    接下来需要你以 debug 的形式启动 Woodpecker Server 以及 Agent,在 ./server/router/router.go#64 行打下断点。

    image-20240120165854326

    重新访问 http://0.0.0.0:8000 点击 Login,然后跟踪 Woodpecker Server 的断点。

    我们发现是 froge.Login() 这个方法运行的到了 err,所以去查看针对 Gitea 的方法实现: server/forge/gitea/gitea.go:119

    🌟 由于 Woodpecker Server 错误日志提示当前 Gitea 的版本是 dev,不由得让白泽联想,莫非是两个开源项目之间有版本依赖的联系!

    带着一些信息,我们打断点到这个函数。

    // code.gitea.io/sdk/gitea@v0.17.1/version.go:91
    func (c *Client) checkServerVersionGreaterThanOrEqual(v *version.Version) error {
    	if c.ignoreVersion {
    		return nil
    	}
        // 向 Gitea 发送 Http 请求,获取 version
    	if err := c.loadServerVersion(); err != nil {
    		return err
    	}
    	// 对比是否大于等于1.11.0(development)无法比较
    	if !c.serverVersion.GreaterThanOrEqual(v) {
    		c.mutex.RLock()
    		url := c.url
    		c.mutex.RUnlock()
    		return fmt.Errorf("gitea server at %s is older than %s", url, v.Original())
    	}
    	return nil
    }
    

    然后就有了日志中的 ErrUnknownVersion development 这个错误。

    由于通过 docker-compose 部署 Gitea 的时候用的是 main 分支的最新内容,在获取 version 的时候,得到了字符串 development 而非一个具体的发布版本号。这里我们查看一下 Gitea 的 main 分支的 version,信息对称。

    🌟 程序员的幸福时刻:这程序如我所愿!

    image-20240120172155074

    解决方案:

    • 本地运行 Gitea,将这个配置改成一个数值型的。
    • 还是通过 docker-compose 部署 Gitea,但是将镜像版本设定为 >= 1.11.0 的发布版,而非开发版即可,比如 image: gitea/gitea:1.21.4 即可。

    4.2.2 用 Gitea 账户登录 Woodpecker

    • 输入 Gitea 用户名密码(需要提前在 Gitea 中注册,当然你能创建 OAuth App 自然已经有了账户)。

    image-20240120163427557

    • 授权 woodpecker-test-app 应用访问 Gitea。

    image-20240120163828839

    • 登录成功,进入 Woodpecker 管理页面,此时显示 Gitea 登录账号的 Repo 列表,空空如也(毕竟 Gitea 都是刚部署的,Repo 还没有创建过)。

    image-20240120172518892

    • Gitea 创建 test-repo

    image-20240120173346401

    image-20240120173834629

    🌟 官方文档:When you activate your repository, Woodpecker automatically adds webhooks to your forge (e.g. GitHub, Gitea, ...).

    所以可以编写 pipeline 配置文件,去触发 webhook 了。

    image-20240120174902046

    4.2.3 Woodpecker + Gitea 实现 CI

    • test-repo 写了一个 hello world 打印函数和一个单元测试。

    image-20240120180606227

    • test-repo 的根目录创建 .woodpecker/build.yaml:内容就打印一句日志。
    steps:
      build:
        image: debian:stable-slim
        commands:
          - echo building
          - sleep 5
    
    • 将代码推送到 Gitea,在 Woodpecker 页面点击 Run pipeline

    image-20240120192034223

    • 提示无法连接到 http://localhost:3000/baize/test-repo.git/ 这个仓库,当然现在我们已经确保的是:Woodpecker 是可以访问到 Gitea 的,毕竟都拉取到了 baize 这个账号创建的 test-repo

    image-20240120192121947

    此时 Woodpecker Server 的日志:

    image-20240120192526574

    此时 Woodpecker Agent 的日志:

    image-20240120192601615

    • 为了解决问题:必须要探究 pipeline 运行函数的实现!毕竟直接看这日志太过抽象,还是得打断点。

    🌟 有了上面打断点调试的经验,这里发生问题我们不用慌乱,休息一下,下篇文章白泽带你解析 Woodpecker 的核心机制:Pipeline 运行逻辑。

    五、小结

    🌟 未完待续,欢迎追更。

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

    最近开源了一个挂机冒险游戏《模拟龙生》,还有热心同学不仅帮忙做优化,还连夜在给游戏加页面,泪目。

    image-20240121103235404

    现在游戏体量只有500-600行代码,感兴趣的同学可以一起来维护。游戏的大致玩法在这篇文章中。后续游戏有阶段性变化功能合入主分支,则会继续通过文章向各位介绍使用的技术和玩法。(学习娱乐两不误)

    下一步的计划是添加本地存档功能,预计今天完成。

    白泽目前正在打造一个氛围良好的行业交流群(游戏交流群),文章的更新也会提前预告,欢迎加入:622383022。

  • 相关阅读:
    vue3 使用语法糖,子父子间的传值以及方法调用
    java 入土--集合详解
    layUI项目之(待开会议&历史会议&所有会议)
    低功耗蓝牙(BLE)开发——Qt
    c++文件读写
    kettle通过java步骤获取汉字首拼
    Linux 内存管理 pt.3
    使用代理绕过网站的反爬机制
    Android 8.1 persisten 应用通过安装方式更新升级
    安信可 ESP_01SWIFI模块的使用 (电脑通过usb转tll模块连接wifi模块进行调试)
  • 原文地址:https://www.cnblogs.com/YLTFY1998/p/17977603