基於 Docker 構建輕量級 CI 系統:Gitea 與 Woodpecker CI 集成

WoodpeckerCI 是一個由社區維護的 DroneCI 分支,使用 Apache License 2.0 許可證發布。社區版進一步擴展了 pipeline 的功能特性、支援對文件路徑設置 pipeline 執行條件,並且可以與 Gitea 實現緊密集成。不同的是,DroneCI 的配置文件是 .drone.yml,WoodpeckerCI 重命名為了 .woodpecker.yml。好在 WoodpeckerCI 也兼容 DroneCI 的配置文件,遷移起來並不會太麻煩。

下面,我們以 try.gitea.io 伺服器為例,實現 Gitea 與 WoodpeckerCI 的系統集成。

系統結構

  • Gitea : VCS,程式碼倉庫。
  • Server : 中心伺服器,負責任務調度。
  • Agent : 邊緣節點,執行 Pipeline 的具體任務。

用戶將程式碼推送到 Gitea 時觸發 Webhook,調動 WoodpeckerCI 從 Gitea 拉取最新的程式碼並根據 .woodpecker.yml 描述文件執行 CI 流水線。

網路結構

由於 CI 任務的特殊性,工作繁忙時會佔用較多的系統資源,因此為了提高系統整體可靠性,不建議將 Gitea、WoodpeckerCI Server 和 Agent 安裝在同一台伺服器上。

  • 在本地區域網搭建時應該確保以上服務可以通過域名、IP 互相訪問。例如:
    gitea.example.com -> 192.168.3.10
    ci.example.com    -> 192.168.3.20
    agent.example.com -> 192.168.3.30
    
  • 如需使用 docker compose 在本地開發環境搭建整套系統,可以閱讀參考官方手冊:
    //woodpecker-ci.org/docs/administration/setup

準備工作

在 Gitea 上創建 OAuth2 應用程式

在本例中,WoodpeckerCI 基於 OAuth2 認證授權訪問您的 Gitea API。您可以創建一個專用於 CI 的帳號,並將該帳號添加為程式碼倉庫協作者或者組織管理員。

首先,登錄一個您要用於集成 WoodpeckerCI 的 Gitea 帳號,進入 設置 – 應用,創建一個 Gitea OAuth2 應用程式。

  • 應用名稱 : 您可以任取一個名字,此案例中我們填寫 WoodpeckerCI
  • 重定向 URL : 授權回調 URL,例如 //<host>/authorize

修改 Gitea 伺服器的 Webhook 白名單

出於安全考慮,Gitea 默認禁止觸發外部主機的 Webhook。您可以將外部主機添加到 webhook.ALLOWED_HOST_LIST 白名單來解除這一限制。請參考文檔 Webhook 了解具體方法。

修改配置時,打開 conf/app.ini,添加 ALLOWED_HOST_LIST = *[webhook] 欄目中,並重啟 Gitea 伺服器。例如:

[webhook]
ALLOWED_HOST_LIST = *

創建共享密鑰

共享密鑰用於 WoodpeckerCI Server 和 Agent 之間的通訊認證。記錄下您創建的共享密鑰,稍後在安裝 WoodpeckerCI Server 和 Agent 時將使用此密鑰填充環境變數 WOODPECKER_AGENT_SECRET

您可以使用 OpenSSL 生成隨機的長度為 32 位的十六進位共享密鑰:

$ openssl rand -hex 32
c5704bc389f1e3d47f1c4751d1295c86

使用 Docker 安裝 WoodpeckerCI 伺服器和 Agent

WoodpeckerCI 伺服器是一個輕量級的 Docker 容器,使用 SQLite 作為默認資料庫,支援通過環境變數動態設定運行參數。有關配置參數的完整列表,請參閱 WoodpeckerCI 伺服器配置文檔

環境變數

  • WOODPECKER_OPEN : 默認 false。是否開放註冊。
  • WOODPECKER_HOST : 默認空。設置伺服器訪問地址,例如 //ci.example.com
  • WOODPECKER_GITEA : 默認 false。啟用 Gitea 驅動。
  • WOODPECKER_GITEA_UR : 默認 //try.gitea.io。配置 Gitea 伺服器地址。
  • OODPECKER_GITEA_CLIENT : 默認空。配置 Gitea OAuth 客戶端 ID
  • WOODPECKER_GITEA_SECRE : 默認空。配置 Gitea OAuth 客戶端密鑰
  • WOODPECKER_GITEA_SKIP_VERIFY : 默認 false。不驗證 SSL 證書有效性。
  • WOODPECKER_SERVER : 默認空。WoodpeckerCI 主伺服器地址。
  • WOODPECKER_AGENT_SECRET : 默認空。WoodpeckerCI 伺服器之間的共享密鑰。可以使用命令 openssl rand -hex 32 生成。

啟動伺服器

為了便於修改容器參數,我們創建一個 docker-compose.yml 模板來配置 WoodpeckerCI 伺服器容器。

根據下面的 Docker Compose 模板,使用命令 docker compose up -d 啟動 WoodpeckerCI 伺服器。

# docker-compose.yml
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_GITEA=true
      - WOODPECKER_GITEA_URL=${WOODPECKER_GITEA_URL}
      - WOODPECKER_GITEA_CLIENT=${WOODPECKER_GITEA_CLIENT}
      - WOODPECKER_GITEA_SECRET=${WOODPECKER_GITEA_SECRET}
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    command: agent
    restart: always
    depends_on:
      - woodpecker-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:9000
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}

volumes:
  woodpecker-server-data:

初始化 WoodpeckerCI

登錄 WoodpeckerCI 網頁面板,//<host>:8000,點擊 login 跳轉到 Gitea 授權頁面,點擊應用授權

注意:如果出現 Unregistered Redirect URI,表示您設置的重定向 URI與 WoodpeckerCI 不匹配,請重新檢查。

CI 實操:創建 .woodpecker.yml 驗證 Pipeline

WoodpeckerCI 基於 Docker 實現了對各種程式語言和包管理工具的流水線支援。這部分在官方的使用說明中有完整詳細的介紹:

//woodpecker-ci.org/docs/usage/intro

這裡我們以 Golang + Node.js 的項目為例,在 Gitea 倉庫根目錄創建一個 .woodpecker.yml 作為我們自定義的流水線。示範:

# .woodpecker.yml
pipeline:
  backend:
    image: golang
    commands:
      - go build
      - go test
  frontend:
    image: node
    commands:
      - npm install
      - npm run test
      - npm run build

在 WoodpeckerCI 面板上激活倉庫後提交程式碼到 Gitea 倉庫,隨即觸發 Pipeline 任務。

回到 Gitea 可以看到構建完成後顯示的消息:

✔ ci/woodpecker/push/woodpecker Build is passing