基於 Docker 構建輕量級 CI 系統:Gitea 與 Woodpecker CI 整合

2022-11-04 18:01:05

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 在本地開發環境搭建整套系統,可以閱讀參考官方手冊:
    https://woodpecker-ci.org/docs/administration/setup

準備工作

在 Gitea 上建立 OAuth2 應用程式

在本例中,WoodpeckerCI 基於 OAuth2 認證授權存取您的 Gitea API。您可以建立一個專用於 CI 的賬號,並將該賬號新增為程式碼倉庫共同作業者或者組織管理員。

首先,登入一個您要用於整合 WoodpeckerCI 的 Gitea 賬號,進入 設定 - 應用,建立一個 Gitea OAuth2 應用程式。

  • 應用名稱 : 您可以任取一個名字,此案例中我們填寫 WoodpeckerCI
  • 重定向 URL : 授權回撥 URL,例如 https://<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 : 預設空。設定伺服器存取地址,例如 http://ci.example.com
  • WOODPECKER_GITEA : 預設 false。啟用 Gitea 驅動。
  • WOODPECKER_GITEA_UR : 預設 https://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 網頁面板,http://<host>:8000,點選 login 跳轉到 Gitea 授權頁面,點選應用授權

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

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

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

https://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