研发协同平台持续集成Jenkins作业设计演进
源寶導讀:Jenkins作為一個開源的持續集成工具,被大家廣泛使用。本文將分享,Jenkins在明源云研發協同平臺中的運用,以及在其作業設計方面的演進歷程。
一、作業設計1.0
? ? 起初,為了盡快推出研發協同平臺v1.0,我們運用Jenkins工具,快速實現了站點的部署、配套服務的安裝、以及文件打包等功能。
? ? 使用過程包括以下簡單的幾個步驟:
1、定義Jenkins Job模板
? ? 參照Jenkins Job的config.xml結構,定義出Job模板,以及相關業務對應的子模板。
2、替換業務參數
? ? 依據業務場景,選擇使用不同的子模板,替換對應的業務參數與子模板,生成最終的Jenkins Job配置文件。
3、調用Jenkins API
? ? 通過直接調用Jenkins Api完成Job的創建與Build。
4、輪詢監控job狀態
? ? 通過不停的輪詢監控已出發build的job,獲取其當前執行狀態,得到最終執行結果。
? ? 剛開始為了快速實現業務需求,采用最簡單直接的方式引入了Jenkins,并快速的完成了相關業務功能的實現。
二、作業設計1.x
? ? 隨著相關業務需求的不斷遞增,起初的代碼結構也慢慢顯露出其弊端,主要體現在:
子模板難以維護:數量不斷增加,子模板的相似度也在不斷增加;
參數變量追溯困難:為應對各種不同場景,使用了多種多樣的業務參數變量;
Job狀態不一致問題:業務數據狀態與job實際執行狀態出現不一致;
接入新作業代碼冗余:每接入一個新的Job作業,都需要定義過多的與Jenkins相關的內容。
? ? 為解決上述問題,我們對Jenkins作業的設計進行了不斷的改進,改進主要分為2個方向。
2.1、業務抽象
? ? 我們將不同的業務進行了劃分,站點部署、配套服務、打包等,并且提取統一的Job構造器,避免業務代碼與功能代碼相混淆。
? ? 除此之外還對Job的執行、狀態監控、失敗重試等功能性業務托管到Jenkins調度服務,并通過消息通知實現了解耦。
2.2、Jenkins SDK
? ? 為了更方便的操作Jenkins相關功能,提取了針對Jenkins的SDK,避免直接與Jenkins進行交互,該SDK也是Jenkins調度服務的底層工具。
? ? 最終設計結構如下圖所示:
三、作業設計2.0
? ? 在完成作業設計1.x的落地后,已經能很好的支撐當時的持續集成業務,但是在后續的業務發展中,不足之處也逐漸顯現:
Job作業的模板組裝不夠靈活,當原有業務發生變化時,不太容易靈活的調整。
當有新產品類型的持續構建需求時,需要重新定義新的模板和作業。
Job和業務的耦合度較高。
? ? 從設計的角度來看,主要是擴展性和配置的靈活性不足。
? ? 一次持續集成,也就是一組Jenkins作業按照一定的順序組成,而一個作業里面實際上都是在執行一個一個的命令,基于此, 我們設計了作業2.0的基礎模型:管道、作業、命令。
? ? 本次作業設計的演進充分利用了Jenkins的插件功能,并且取代了之前的Jenkins調度服務
? ? 總體設計圖如下:
管道:一個持續集成管道由一系列持續集成作業組成; 不同功能的作業組合成不同功能的管道; 持續集成管道中的作業可以是串行,也可以是并行
作業: 管道中的作業由一組命令組成; 不同的命令組合成不同功能的作業
命令:命令是持續集成中的最小功能單元;研發協同平臺內置了一批命令集
Jenkins執行器:專門負責執行管道作業,利用Jenkins SDK與Jenkins進行交互;
Job狀態回調管道:這里運用了Jenkins的Notification插件,Jenkins Job執行過程中的狀態會通過該插件即時回調;
3.1、類設計圖
服務
ServiceDomainService:服務調用的場景類,負責統一調度執行服務。
BaseService:服務基類,所有服務都繼承與該類進行擴展。
? ? 若有新的服務,只需通過繼承BaseService進行擴展即可。
/// <summary> /// 服務 /// </summary> public abstract class BaseService : ITransientDependency {/// <summary>/// 服務類型/// </summary>public virtual ServiceType ServiceType { get; set; } = ServiceType.Other;/// <summary>/// 執行操作/// </summary>/// <param name="args"></param>/// <returns></returns>public abstract Task Execute(BaseServiceArgs args);/// <summary>/// 執行器/// </summary>internal ICiExecutor CiExecutor { get; }/// <summary>/// 構造函數/// </summary>/// <param name="ciExecutor"></param>public BaseService(ICiExecutor ciExecutor){CiExecutor = ciExecutor;} }管道與作業
BaseCiPipeline:管道抽象類,其中定義了管道作業的的構建動作。
Job:單個作業對象,包含Jenkins Job 必須的屬性。
? ? 若新服務需要構造新的執行管道,需要通過BaseCiPipeline抽象類進行派生。
/// <summary> /// CI流水線 /// </summary> public abstract class BaseCiPipeline : ITransientDependency {/// <summary>/// 構建Jenkins Job 集合/// </summary>/// <param name="args">CI流水線參數</param>/// <returns></returns>internal abstract Task<List<Job>> StructureJobs(CiPipelineArgs args); } /// <summary> /// JenkinsJob定義 /// </summary> public class Job {/// <summary>/// Job執行順序編號/// </summary>public int JobIndex { get; set; }/// <summary>/// 執行步驟/// </summary>public List<CiAction> ActionList { get; set; }/// <summary>/// Job參數/// </summary>public Dictionary<string, string> BuildParams { get; set; } = new Dictionary<string, string>();/// <summary>/// 執行節點/// </summary>public string AssignedNode { get; set; }/// <summary>/// 工作空間/// </summary>public string BaseJobName { get; set; }/// <summary>/// 當前JobName/// </summary>public string JobName { get; set; }/// <summary>/// Job目錄地址/// </summary>public string JobPath { get; set; }/// <summary>/// 業務回調參數/// </summary>public string Notes { get; set; } }命令
CiAction:命令基類,定義了命令的基本屬性與動作。
? ? 每個新增的命令只需要實現自己的變化點即可。
/// <summary> /// 操作 /// </summary> public abstract class CiAction {/// <summary>/// 操作類型/// </summary>public virtual ActionTypeEnum ActionType { get; set; } = ActionTypeEnum.BatchFile;/// <summary>/// 操作說明/// </summary>internal string _actionName { get; set; }/// <summary>/// 模板/// </summary>/// <returns></returns>internal abstract string Template();/// <summary>/// 參數/// </summary>/// <returns></returns>internal abstract Dictionary<string, string> BuildParams();/// <summary>/// 生成Action內容/// </summary>/// <returns></returns>public string Build(){var result = this.Template();var pars = this.BuildParams();if (pars != null && pars.Count > 0){foreach (var item in pars){result = result.Replace(item.Key, item.Value, StringComparison.OrdinalIgnoreCase);}}return result;} }執行器
ICiExecutor:執行器接口,該接口定義了執行器的動作以及對外擴展的回調事件。
JenkinsExecutor:是基于Jenkins 實現的執行器,通過解析管道作業,獲得最終的Job并與Jenkins進行交互。
? ? 這里只實現了Jenkins的執行器,若將來擴展了新的持續集成工具可以直接擴展新的執行器。
/// <summary> /// 執行器 /// </summary> public interface ICiExecutor {/// <summary>/// 開始構建/// </summary>event EventHandler<CiPipelineArgs> Started;/// <summary>/// 構建失敗/// </summary>event EventHandler<CiPipelineArgs> Failed;/// <summary>/// 構建成功/// </summary>event EventHandler<CiPipelineArgs> Succeed;/// <summary>/// 執行流水線/// </summary>/// <param name="ciPipeline">流水線</param>/// <param name="args">參數對象</param>Task Execute(BaseCiPipeline ciPipeline, CiPipelineArgs args);/// <summary>/// 觸發構建事件/// </summary>/// <param name="args">業務參數對象</param>/// <returns></returns>Task InvokeStarted(CiPipelineArgs args);/// <summary>/// 觸發構建失敗事件/// </summary>/// <param name="args">業務參數對象</param>/// <returns></returns>Task InvokeFailed(CiPipelineArgs args);/// <summary>/// 觸發構建成功事件/// </summary>/// <param name="args">業務參數對象</param>/// <returns></returns>Task InvokeSucceed(CiPipelineArgs args); }回調管道
BaseServiceCallbackHandler:回調處理基類,所有的回調處理都應集成與該類。
? ? 每個回調處理,可以通過定義 ServiceTypes去偵聽自己所關心的回調事件,并做相應的業務處理。
/// <summary> /// 服務回調處理 /// </summary> public abstract class BaseServiceCallbackHandler {/// <summary>/// 處理的服務類型/// </summary>public virtual ServiceType[] ServiceTypes { get; set; }/// <summary>/// 執行器/// </summary>public ICiExecutor CiExecutor { get; }public BaseServiceCallbackHandler(ICiExecutor ciExecutor){CiExecutor?=?ciExecutor;?} }作業運行流程
執行流程:客戶端通過調用服務場景,指定需要執行的具體服務,服務定義了其對應的管道作業,最終交由執行器進行執行。
回調流程:回調場景主要用于接收Jenkins的回調請求,通過分析請求類型進而觸發相應的處理事件。
3.2、本次演進主要帶來的好處包括:
1、可擴展性
實現個性化功能,只需自定義命令。
對于不同的業務場景,只需定義不同的持續集成管道。
2、靈活性
? ? 通過原子性的命令定義,可以自由組合出各種想要的作業,進一步定義出各種功能的持續集成管道,從而滿足業務多樣化的需求。
3、解耦
? ? 通過抽象出Jenkins執行器,來實現業務和Jenkins管道之間的解耦,從而較小業務對Jenkins管道的影響。
四、展望未來
? ? 目前的作業設計已經具備了一定的靈活性和擴展性,在下階段我們還會對作業設計做更進一步的優化,通過封裝標準的作業步驟(Action)、統一的CI流程,進而提供可視化的流水線定制功能。由之前的代碼業務驅動改為數據驅動,最終實現作業的全面可定制與可配置。
------ END ------
作者簡介
朱同學:?研發工程師,目前負責RDC研發協同平臺的設計與開發工作。
也許您還想看
研發協同平臺持續交付之代理服務實踐
研發協同平臺持續集成2.0架構演進
研發協同平臺持續集成實踐
招商城科走進武漢研發中心,現場編碼解鎖平臺內核技術
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的研发协同平台持续集成Jenkins作业设计演进的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一张大图了解ASP.NET Core 3
- 下一篇: 一切都要从华为云 CloudIDE 酷似