DevOps 外掛¶
介紹¶
DevOps 是一個完整的面向 IT 運維的工作流,以 IT 自動化以及持續整合(CI)、持續部署(CD)為基礎,來最佳化程式開發、測試、系統運維等所有環節,現在Meegle基於位元組跳動研發實踐的研發全流程方案,支援研發編碼到釋出的主流程在平臺內完成閉環,落實研發流程規範,提升協作效率及交付質量,沉澱研發過程資料。
- 開發階段:程式碼開發分支基於規則自動建立,在Meegle執行流水線
- 整合階段:在Meegle完成程式碼的整合工作,包括上線單的提交、code review、程式碼合併
- 釋出階段:在Meegle裡執行流水線完成釋出
外掛安裝¶
管理員前往空間配置 → 外掛管理 → 搜尋 DevOps 完成外掛的新增。

外掛配置¶

倉庫配置¶
目前僅支援 GitLab 新建倉庫:點選外掛配置-倉庫配置-新建倉庫
- 獲取倉庫地址:登入 GitLab 後,點選進入對應的倉庫,複製 GitLab 倉庫連結
- 獲取名稱空間:複製 GitLab 倉庫連結中名稱空間部分


- 獲取應用 ID:在 GitLab 裡新建應用(User owned applications、Group owned applications、Instance-wide applications 任選一種即可),Group owned applications 的應用 ID 可參考以下錄屏獲取,其他 applicantions 可參考 GitLab 文件獲取

- 填寫倉庫 Access Token:Token 分為「當前單個倉庫的 token」和「全域性 token」。若填寫了「單個倉庫的 token」,則優先使用「單個倉庫的 token」,否則預設使用「全域性 token」。
- 當前單個倉庫的 token:通常填寫 GitLab 管理員的 Personal access tokens

- 全域性 token:點選倉庫配置-配置 token,通常使用 GitLab 的 Project access tokens 或 Group access tokens,可參考可參考 GitLab 文件獲取


- 配置 webhook
- 在倉庫配置-點選「webhook」,獲取 webhook 連結
- 點選進入對應的 GitLab 倉庫,點選側邊的 Setting → Webhooks 選項;
- 將複製的連結貼上到 GitLab 的 Webhook 中的 URL 選項中,勾選「Merge request events」後點選下方的「Add webhook」完成 webhook 關聯。



流水線配置¶
火山 DevOps流水線配置¶
-
新建流水線 登入火山引擎,點選右上角進入控制檯
-
Accountld:即賬號ID,在控制檯頁面,點選右上角個人資訊-複製賬號ID
- AccessKey:即Access Key ID,在控制檯頁面,點選右上角個人資訊-API訪問金鑰-複製Access Key ID
- SecretKey:即Secret Access Key,在控制檯頁面,點選右上角個人資訊-API訪問金鑰-複製Secret Access Key



- 回撥配置
- 複製流水線 webhook
- 登入火山引擎,進入「持續交付」平臺,點選概覽-選擇對應的工作區
- 進入工作區頁面-點選基本資訊-對應的流水線,點選編輯流水線
- 進入流水線編輯頁面-點選通知提醒-開啟「Webhook 通知」-Webhook 地址選擇「通用模式」-貼上 Webhook 地址




自定義流水線配置¶
配置側¶
介面展示

-
認證令牌、認證值 認證令牌就是token,認證值就是token的具體值(用於認證資訊)
-
流水線介面
- 自定義三個POST請求的https介面
- (使用者)將接收到的header統一入參格式為
- 流水線列表
- 第三方外掛將接收到的入參格式為:
- 需要返回給devops外掛的出參格式為:
- 執行流水線
- 第三方外掛將接收到的入參格式為:
- 需要返回給devops外掛的出參格式為:
- 流水線詳情
- 第三方外掛將接收到的入參格式為:
- 需要返回給devops外掛的出參格式為:
- 釋出配置
- 此處的選擇模板列表資料來源為:流水線介面 → 流水線列表介面

使用側¶
- 手動觸發流水線的資料來源為:流水線介面 → 流水線列表介面

- 確定之後會執行:流水線介面 → 執行流水線介面
- 流水線資訊列表:流水線介面 → 流水線詳情介面(包含時間、狀態等)
回撥地址資料格式¶

Jenkins 流水線配置¶
配置側¶
新建 Jenkins 流水線¶
- 在 Devops 外掛 -> 流水線配置 -> 新建流水線

- 新建 Jenkins 流水線
- 流水線名稱: 填寫相應名稱
- 整合產品: 選擇 Jenkins
- Jenkins URL: 填寫 Jenkins 地址

- 複製回撥地址 例: https://project.feishu.cn/m-api/v1/builtin_app/devops/jenkins/callback?signature=xxxxxxxxxxx

安裝Meegle jenkins 外掛¶
- 下載Meegle jenkins 外掛
- Jenkins 安裝外掛 推薦jenkins版本: 2.414.3 Manage Jenkins -> Plugins

Advanced Settings -> 選擇檔案(FeishuProjectPlugin.hpi) -> Deploy

- 配置 MeegleJenkins外掛 Manage Jenkins -> System

找到 Feishu Project Plugin -> Callback填入流水線Jenkins的回撥地址 -> Save

Jenkins 無法訪問網際網路場景¶
在Jenkins伺服器沒有網際網路訪問出口時, 可以透過反向代理的方式, 進行jenkins回撥

使用301 轉發 使用 proxy_pass 轉發
使用側¶
配置 Jenkins Item¶
- 得到飛書工作項 jenkins標識 點選工作項(如需求) -> 工作項例項(test01) -> ... -> 複製jenkins標識(xxxxxx#story#xxxxxxx)

- 配置jenkins的 Item 選擇相關Item -> Configure

General -> This project is parameterized -> String Parameter

配置String Parameter Name: feishu_project_key (注: 此變數為固定值) Default Value: Meeglejenkins標識(xxxxxx#story#xxxxxxx)

配置Post-build Actions

選擇Feishu Project Deploy Notifier

填加Feishu Project Deploy Notifier後, Save儲存

編譯 Item¶
Build with Parameters -> feishu_project_key(會帶入預設值, 也可進行實際值的填寫) -> Build

輸出日誌¶
feishu model: 向後臺提交的引數 feishu result: 返回結果資訊 feishu error: 返回錯誤資訊

檢視關聯結果¶
點選相關工作項(如需求) -> 工作項例項(test01) -> DevOps -> 流水線資訊

自動關聯分支功能¶
在未填寫"MeegleJenkins標識"時, 外掛可根據編譯的倉庫與分支資訊和工作項例項中程式碼資訊中關聯分支的倉庫與分支資訊相匹配, 如果分支名稱相同, 可對編譯結果與工作項例項進行關聯
- 點選相關工作項(需求) -> 工作項例項(test01) -> DevOps -> 程式碼資訊-> 分支

- Jenkins git 配置 1.倉庫資訊, 2.分支資訊

Pipeline模式支援¶
Meeglejenkins外掛支援pipeline模式 宣告式使用方式 在流水線指令碼中post階段, 條件為always, 加入feishuProjectPost函式 引數為 gitUrl: git倉庫地址 branchName: 程式碼分支 指令碼式使用方式 由於指令碼式語法沒有POST階段, 無法得到執行結果, 需要根據指令碼執行來賦值currentBuild.result
釋出配置¶
- 工作項:不支援配置,目前關聯工作項僅支援「版本」工作項,如果空間沒啟用「版本」工作項,可以在空間配置-工作項管理-版本-啟用
- 配置分支規則:
- 選擇當版本狀態存在屬於xx狀態時
- 選擇在「 」中配置的倉庫名稱和源分支
- 配置釋出分支名稱,命名時支援配置變數:工作項id: {{work_item_id}},節點id:{{node_state_key}},觸發時間{{trigger_time}} ,如release_{{work_item_id}}{{node_state_key}}}
- 配置流水線執行規則:選擇當版本狀態存在屬於xx狀態時,觸發在「 」中配置的流水線
- 如版本流轉到「灰度中」時,觸發版本釋出的流水線
- 新建上線單許可權控制:即什麼時候可以新建上線單
- 如版本封版後不允許新建上線單,可配置當前工作項狀態存在屬於「未啟動」、「開發中」等封版前的狀態
- 配置完成後,記得點選右上角「儲存」按鈕

開發配置¶
新建開發配置
- 規則名稱:命名開發配置規則
- 適用工作項:規則關聯的工作項
- 配置分支規則
- 選擇工作項對應的流程型別-節點名稱
- 配置觸發狀態:當節點狀態變為進行中或已完成
- 選擇在「 」中配置的倉庫名稱和源分支
- 配置開發分支名稱,命名時支援配置變數:工作項id: {{work_item_id}},節點id:{{node_state_key}},觸發時間{{trigger_time}} ,如feat_{{work_item_id}}{{node_state_key}}}

通知配置¶
當編輯或者新增稽核人時,機器人會向稽核人傳送通知
- 進入飛書開放平臺-建立應用


- 複製App ID、App Secret

- 在Meegle-空間配置-外掛管理-Meegle DevOps 外掛-配置-通知配置,貼上App ID、App Secret,點選儲存

上線單控制元件配置¶
在空間配置-工作項關聯-版本-頁面佈局-配置「DevOps上線單資訊」控制元件

外掛使用¶
步驟一:新建版本¶
如已有可用版本,這一步可跳過
- 在空間介面點選右上角的「新建」按鈕;
- 選擇「新建版本」選項(如新建頁無新建版本入口,需檢視空間配置中版本工作項是否啟用並pin到導航欄);
- 需要根據管理員配置的表單內容填寫表單項資訊,必填項必須填寫,否則將無法建立版本;
- 填寫完畢後,點選「建立」建立完成。

步驟二:關聯分支¶
- 完成開發後,選擇需要關聯的工作項(如需求、缺陷),點選詳情頁-devops標籤頁,關聯 裡的程式碼分支
- 如管理員已在 裡配置規則,流轉到對應的節點會自動建立分支



步驟三:執行流水線¶
如未配置流水線或無需執行,可跳過此步驟 完成開發後,如需進行研發自測等流水線,可點選詳情頁-devops標籤頁-執行流水線,選擇 裡關聯的流水規則

步驟四:新增或新建上線單¶
當版本狀態滿足管理員在 中配置的「新建上線單許可權控制」規則時,可將開發分支新增到對應的版本上線單中,搜尋並填寫對應的程式碼稽核人
- 點選對應工作項-「DevOps」標籤頁-程式碼資訊-點選「新增到上線單」
- 選擇上線版本、修改稽核人後點選確定

步驟五:上線單(程式碼)稽核¶
-
程式碼稽核 版本封版前,對應的稽核人,可在版本-「DevOps上線單資訊」控制元件中進行程式碼稽核
-
在版本-「DevOps上線單資訊」控制元件-對應上線任務-點選詳情,可檢視程式碼 Diff、新增評論
- 點選「核准」-「OAuth 授權」,授權後完成審批

- 程式碼合併 稽核完成後,如有多個程式碼任務,可點「全部合併」

步驟六:版本封版¶
- 如果管理員在 中配置新建上線單許可權控制為:版本狀態存在屬於「未啟動」、「開發中」等封版前的狀態
- 當版本負責人將版本流轉到「已封版」時,「新建上線單」按鈕置灰,不允許再新增上線單

步驟七:版本釋出¶
如未配置流水線或無需執行,可跳過此步驟
- 版本封版後,可執行對應的流水線,發版上線
- 如管理員已在 裡配置規則,流轉到對應的狀態會自動執行流水線

Jenkins 無法訪問網際網路場景的解決方法¶
在Jenkins伺服器沒有網際網路訪問出口時, 可以透過反向代理的方式, 進行jenkins回撥

使用301 轉發 使用 proxy_pass 轉發
出口IP地址¶
如需進行IP白名單限制, 可配置如下IP地址 101.126.59.78 101.126.59.79 101.126.59.80 101.126.59.81 101.126.59.82 122.14.241.24 122.14.241.25 122.14.241.26 122.14.241.27 122.14.241.28 36.150.74.83 36.150.74.105 36.150.74.113 111.63.62.149 111.63.62.150 111.63.62.151 111.62.104.5 111.62.104.6 111.62.104.7 36.155.139.138 36.155.139.147 36.155.139.151 36.150.74.41 36.150.74.46 36.150.74.51 58.211.81.112 58.211.81.116 58.211.81.117 111.225.144.178 111.225.144.179 111.225.144.180 49.7.49.5 49.7.49.6 49.7.49.7 61.147.169.232 61.147.169.246 61.147.169.255 58.211.81.33 58.211.81.36 58.211.81.49 120.72.60.85 120.72.60.88 120.72.60.95 120.72.60.104 120.72.60.105 110.249.199.175 110.249.199.176 110.249.199.177 110.249.199.178 110.249.199.179 221.194.168.5 221.194.168.6 221.194.168.7 221.194.168.8 221.194.168.9 122.193.1.4 122.193.1.6 122.193.1.17 122.193.1.18 122.193.1.26 120.72.60.37 120.72.60.42 120.72.60.45 120.72.60.50 120.72.60.57 header key:value // 認證令牌:認證值(認證資訊) body: { "page_no": 1, // 頁碼 "page_size": 10 // 每頁的條數 } { "code": 0, "msg": "success", "data": { "total": 25, "list": [ { "template_id": "pipeline_example_id_123", // 流水線模板id "template_name": "example" // 流水線模板名稱 } ] } } body: { "template_id": "pipeline_example_id_123", // 流水線模板id "template_name": "example", // 流水線模板名稱 "work_item_id": 30124567, // 工作項id "node_key": "doing", // 節點key "operator": "kanghuaisong", // 操作人 "repository": [ { "address":"https://gitlab.com/demo/test", // 倉庫資訊 "branch": "feature/123" // 分支 } ] } { "code": 0, "msg": "success", "data": [ { "template_id": "pipeline_example_id_123", // 流水線模板id "template_name": "example", //流水線模板名稱 "instance_id": "pipeline_runing_id_123", // 流水線執行例項id "instance_name": "pipeline_running_name", // 流水線執行名稱 "status": "Running", // 流水線執行狀態, Pending, Running, Succeed, Failed "created_at": "2024-06-03 12:01:01", // 流水線觸發時間 } ] } body { "template_id": "pipeline_example_id_123", "template_name": "example", "instance_id": "pipeline_running_id" } { "code": 0, "msg": "success", "data": { "template_id": "pipeline_example_id_123", // 流水線模板id "template_name": "example", //流水線模板名稱 "instance_id": "pipeline_runing_id_123", // 流水線執行例項id "instance_name": "pipeline_running_name", // 流水線執行名稱 "status": "Succeed", // 流水線執行狀態 "created_at": "2024-06-03 12:01:01", // 流水線觸發時間 "updated_at": "2024-06-03 12:10:11", // 流水線更新時間 "ref": "http://pipeline.example.com/pipeline/instance/123" // 流水線執行例項連結 } } { "template_id": "tpl-123456", // 流水線模板ID "template_name": "Java構建模板", // 流水線模板名稱 "instance_id": "ins-789012", // 流水線例項ID "instance_name": "V1.0版本構建例項", // 流水線例項名稱 "status": "success", // 流水線例項狀態 "ref": "https://example.com/pipelines/ins-789012", // 流水線例項連結 "created_time": "2025-10-24T08:30:00Z", // 流水線例項建立時間 "updated_time": "2025-10-24T09:15:00Z" // 流水線例項更新時間 } server { listen 8081; # 監聽的埠號 return 301 https://project.feishu.cn/m-api/v1/builtin_app/devops/jenkins/callback; } server { listen 8081; # 監聽的埠號 location / { proxy_pass https://project.feishu.cn/m-api/v1/builtin_app/devops/jenkins/callback; } } pipeline { agent any parameters { gitParameter( branchFilter: 'origin/(.*)', defaultValue: '*/main', name: 'BRANCH', type: 'PT_BRANCH', useRepository: 'https://gitlab.com/xxxxxxx/gitlab-test' ) } stages { stage('Hello') { steps { echo 'Hello World' git branch: "${params.BRANCH}", credentialsId: 'xxxxxxx', url: 'https://gitlab.com/xxxxxx/gitlab-test' // sh "printenv" } } } post { always { //此處加入外掛函式 feishuProjectPost( gitUrl: 'https://gitlab.com/xxxxxx/gitlab-test', branchName: "${params.BRANCH}" ) } } } node { def mvnHome try { stage('run') { // for display purposes echo 'Hello World' currentBuild.result = 'SUCCESS' // 賦值為非給定值都為FAILURE /* * 成功(SUCCESS):任務成功執行並且沒有錯誤。 * 失敗(FAILURE):任務執行過程中出現錯誤或失敗。 * 中斷(ABORTED):任務在執行過程中被中斷或取消。 * 不穩定(UNSTABLE):任務執行完成,但可能存在一些警告或非關鍵錯誤。 * 未構建(NOT_BUILT):任務尚未構建,通常是由於配置問題或其他原因導致任務未開始構建 */ echo manager //報錯演示 } } catch (e) { echo 'ERROR' currentBuild.result = 'FAILURE' } finally { //無論前面失敗還是成功都會執行 stage('Results') { feishuProjectPost( gitUrl: 'https://gitlab.com/vc7841029/gitlab-test', branchName: "${params.BRANCH}" ) } } } server { listen 8081; # 監聽的埠號 return 301 https://project.feishu.cn/m-api/v1/builtin_app/devops/jenkins/callback; } server { listen 8081; # 監聽的埠號 location / { proxy_pass https://project.feishu.cn/m-api/v1/builtin_app/devops/jenkins/callback; } }