清除 GitLab 上所有 CI/CD 的 artifact


GitLab 的 CI/CD 功能在 Heresy 來看,算是相當便利的自動化功能,Heresy 現在不管是在工作,還是私人的東西,都有在透過這東西來做自動化的處理。

不過,前幾天…倒是發現自己之前的「刀劍神域記憶重組 公告變更記錄產生器」幹了件蠢事…

那就是 Heresy 沒有設定 artifact 的過期日,結果這些 artifact 都按照預設值,會保存四周。
而其結果,就是這個專案明明只有不到 400KB,卻佔用了 15GB 的空間…

而實際上,這些資料是完全沒有必要保存這麼久的…

處理方法呢,基本上就是在 .gitlab-ci.yml 中,幫 artifacts 的加上 expire_in 這項參數了(官方文件)。

像下面的設定,就是設定這些 artifacts 會在一天內過期、然後自動被刪除。

artifacts:
  paths:
  - SAOMD-AA
  expire_in: 1 day

但是對於伺服器上既有的 artifacts 該怎麼處理呢?在 GitLab 的網頁介面中,似乎沒有提供相關的刪除選項,所以似乎只能等他過期、被系統自動刪除了。

也或許是早期 GitLab 沒有考慮這點吧?許多一年前的 artifacts,感覺上甚至根本沒有過期的時間,所以看來可能會永遠晾在那了…

雖然對 Heresy 好像沒直接的影響?不過由於放一堆沒用的東西在那邊好像也不好,所以就開始研究該怎麼刪除了。

就個人所知,如果想要手動刪除這些東西的話,應該是需要透過他提供的 Web API 來做操作。(官方文件

以刪除特定工作(job)的 artifacts 來說,可以參考《Remove Gitlab-CI artifacts in batch using the API》這篇文章。

他的 bash 腳本如下:

#!/bin/bash

# project_id, find it here: https://gitlab.com/[organization name]/[repository name]/edit inside the "General project settings" tab
project_id="17159201"

# token, find it here: https://gitlab.com/profile/personal_access_tokens
token="---------------"
server="gitlab.com"

# go to https://gitlab.com/[organization name]/[repository name]/-/jobs
# then open JavaScript console
# copy/paste => copy(_.uniq($('.ci-status').map((x, e) => /([0-9]+)/.exec(e.href)).toArray()).join(' '))
# press enter, and then copy the result here :
# repeat for every page you want
job_ids=(1047296257 1047296259)

for job_id in ${job_ids[@]};
do
  URL=https://$server/api/v4/projects/$project_id/jobs/$job_id/erase
  echo "$URL"
  curl --request POST --header "PRIVATE-TOKEN:${token}" "$URL"
  echo "\n" done

這邊要修改的部分,就是黃底的部分了~

不過,比較麻煩的是,他這邊並沒有透過 API 去取得 Job ID,而是讓使用者自行輸入。而他建議的取得方法,是透過網頁瀏覽器的 JavaScript Console 一頁一頁取得。

而在《Remove all artifact (no expire options)》這串也有一些討論,也有人有提供一些腳本;但是像 remove_gitlab_artifacts.sh 在 Heresy 這邊就不能正常運作…

最後,Heresy 是參考 StackOverflow 上的《Remove artifacts from CI manually》這篇文章中,有人提供的 JavaScript 腳本來修改完成的。

這邊的程式碼基本上如下(檔案):

//Go to: https://gitlab.com/profile/personal_access_tokens
const API_KEY = "-----------------";
 
//You can find project id inside the "General project settings" tab
const PROJECT_ID = 17159201;
const PROJECT_URL = "https://gitlab.com/api/v4/projects/" + PROJECT_ID + "/"
 
const fetch = require('node-fetch');
 
let startpage = 0;
async function listAllJobs() {
  let jobs = [];
  for (let i = startpage, jobs = []; i == startpage || jobs.length > 0; i++) {
    jobs = await sendApiRequest(
      PROJECT_URL + "jobs/?per_page=50&page=" + (i + 1)
    ).then(e => e.json());
 
    let cmdQueue = []
    for (let job of jobs) {
      if (job.artifacts.length > 0 && job.artifacts[0].file_format)
        console.log("Remove artifacts of job " + job.id );
        cmdQueue.push(sendApiRequest(
          PROJECT_URL + "jobs/" + job.id + "/artifacts",
          { method: "DELETE" }
        ));
    }
 
    Promise.all(cmdQueue).then(console.log(" - Finish page " + (i+1)));
  }
}
 
listAllJobs();
 
async function sendApiRequest(url, options = {}) {
  if (!options.headers)
    options.headers = {};
  options.headers["PRIVATE-TOKEN"] = API_KEY;
 
  return fetch(url, options);
}

這個腳本會需要用到 node-fetch(網頁),然後會透過 https://gitlab.com/api/v4/projects/PROJ_ID/jobs/?per_page=50&page=1 這個網頁,以一次 50 個工作的形式,來列出指定專案的所有工作。

然後就可以透過 https://gitlab.com/api/v4/projects/pid/jobs/JOB_ID/artifacts 來刪除指定工作的 artifacts 了。

如果像 Heresy 這邊因為 job 非常多,所以就也得跑非常久了~不過,至少是可以把所有的 artifacts 一口氣清掉了~

對「清除 GitLab 上所有 CI/CD 的 artifact」的想法

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.