自從去年用上了 Jenkins 進行 CI/CD 之後,工作效率高了不少,摸魚的時間更多了。不過 Jenkins 好是好,但在功夫網的影響下,插件就是經常更新不成功的,就像下面這樣子:

然而并沒有什麼卵用,隻是擷取插件清單從這個地方擷取而已,安裝/更新插件的時候該炸還是得炸。
作為一個有代碼潔癖的人,看着有插件更新不了那感覺就像有屎拉不出的難受。于是乎這幾個月以來一直是通過上面圖中的手動上傳插件來進行更新的。可是效率實在是低,一兩個插件還好,有時候一堆插件有更新,那一個個上傳是真的煩。
最近幾天又相對閑了點,察覺到 Jenkins 是有個 REST API 的,那麼能不能通過程式化來解決問題呢。嘗試了下,算是有個比較滿意的解決方案了。
首先,要用 Jenkins REST API 是需要權限的,并不是說随便來個人都可以調用。Jenkins REST API 是通過 token 進行驗證的。預設是沒有 token 的,需要手動添加。
登入 Jenkins 管理面闆,進入管理使用者
這樣就為這個使用者添加了一個 REST API 的 token 了,後續調用 REST API 帶上這個 token 就是了
以 C# 的 HttpClient 為例:
var httpClient = new HttpClient();
httpClient.SetBasicAuthentication("username", "apiToken");
這樣寫就行了,SetBasicAuthentication 方法來自 IdentityModel 這個 nuget 包。(https://www.nuget.org/packages/IdentityModel/)
接下來我們要先擷取哪些插件是有更新的。
在浏覽器中來到 /pluginManager/api/ 這個頁面,點開 JSON API。
理論上會得到這麼個 JSON:
一堆空白?再看一下文檔,加上 depth 參數就好了。加上 depth=1,再次請求 /pluginManager/api/json?pretty=true&depth=1
目前安裝的所有插件的資訊都傳回了。而且這裡還傳回了 hasUpdate 代表這個插件是否有更新。
用 C# 稍微建個模好了
public class JenkinsPlugin
{
[JsonProperty("hasUpdate")]
public bool HasUpdate { get; set; }
[JsonProperty("shortName")]
public string ShortName { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("version")]
public string Version { get; set; }
}
接下來假如某個插件有更新的話,那麼就下載下傳這個插件的新版本好了,打開清華大學 Jenkins 的鏡像頁,并轉到插件目錄 https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/
以 git 插件為例,最新版本的下載下傳位址如下:
https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/git/latest/git.hpi
也就是說某個插件的最新版本在清華大學鏡像站的下載下傳位址是
https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/{plugin.shortName}/git/lastest/{plugin.shortName}.hpi
用 C# 撸個下載下傳代碼好了:
public class TsinghuaClient
{
private static readonly HttpClient Client = new HttpClient();
public async Task<byte[]> DownloadPluginAsync(string pluginName)
{
var url = $"https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/{pluginName}/latest/{pluginName}.hpi";
var bytes = await Client.GetByteArrayAsync(url);
return bytes;
}
}
接下來就是把這個傳到 Jenkins 上。
以 C# 代碼為例就是
using (var content = new MultipartFormDataContent())
{
content.Add(new ByteArrayContent(plugin), "name", fileName);// plugin 為 byte[]
var response = await client.PostAsync("/pluginManager/uploadPlugin", content);
response.EnsureSuccessStatusCode();
}
上傳成功的話,狀态碼是 200 OK。
最後就是要讓 Jenkins 安裝新版本的插件了,這個隻需要重新開機一下 Jenkins 即可。在浏覽器中打開 /api 路徑,并滾動到最底部
左邊那個是強制重新開機,右邊那個是等待到沒任務時再重新開機。我們用右邊那個。
代碼撸一下:
public async Task RestartAsync()
{
var response = await client.PostAsync("/safeRestart", null);
Debug.Assert(response.StatusCode == HttpStatusCode.ServiceUnavailable);
}
重新開機指令發送成功後會傳回 503 Service Unavailable 的。
總結一下流程就是:
擷取已安裝插件清單 –> 篩選有更新的插件 –> 到清華大學鏡像站下載下傳插件最新版本 –> 上傳到 Jenkins –> 重新開機 Jenkins
順手撸了個 WPF 的 app,也把源碼傳上來好了
https://files.cnblogs.com/files/h82258652/JenkinsUpdator.zip
使用的時候注意配置 app.config