GitLab CI/CD: artifacts有効期限をブランチごとに設定する3つの方法
はじめに
GitLab CI/CDにてブランチごとに成果物 (artifacts) の保存期間を変えたいと考え、実現しようとしたところ、いくつかの課題に直面しました。例えば、main
ブランチや develop
ブランチの成果物は長く保持し、フィーチャーブランチのものは短期間で削除したい、といったケースです。
直感的には .gitlab-ci.yml
の artifacts:expire_in
に変数を使えば実現できそうなのですが、残念なことに GitLab CI/CD の現在の仕様 (2025年4月時点) では、expire_in
キーで CI/CD 変数(事前定義変数やカスタム変数)を直接展開することはできません。
本記事では、この制約と、その回避策について情報を共有します。
やりたいこと:ブランチによる Artifacts 有効期限の動的変更
理想としては、以下のように .gitlab-ci.yml
を記述して、ブランチ名に応じて expire_in
の値を動的に変えたいと考えられます。
variables:
# ブランチに応じて有効期限を変えたい(例)
ARTIFACT_EXPIRATION: '1 day' # デフォルトは1日
build_job:
stage: build
script:
- mkdir output
- echo "artifact content" > output/artifact.txt
artifacts:
paths:
- output/
# !!! これは期待通りに動作しない !!!
expire_in: $ARTIFACT_EXPIRATION
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
variables:
ARTIFACT_EXPIRATION: '30 days' # mainブランチなら30日
- when: on_success # それ以外のブランチ (デフォルト値 '1 day' を期待)
問題点:expire_in
では変数が展開されない
上記の YAML を記述しても、GitLab CI/CD は expire_in: $ARTIFACT_EXPIRATION
の部分で変数を展開しません。 $ARTIFACT_EXPIRATION
という 文字列 を期間として解釈しようとするため、無効な値とみなされ、意図した有効期限になりません。
これは、.gitlab-ci.yml
の解析段階で expire_in
の値が静的に決定される必要があるため、あるいは特定の期間フォーマット文字列(例: 1 week
, 30 days
, never
)のみを受け付ける仕様になっているためと考えられます。
回避策
expire_in
で直接変数が使えない以上、別の方法で要件を実現する必要があります。以下に3つの方法を説明します。
1. rules
を使ってジョブ定義を分ける
rules
(または古い only/except
) を使用して、有効期限が異なるジョブをブランチごとに定義します。
# .gitlab-ci.yml
build_feature_branch:
stage: build
script:
- mkdir output && echo "feature artifact" > output/artifact.txt
artifacts:
paths: [output/]
expire_in: 1 day # Featureブランチは1日で失効
rules:
# main と develop 以外の場合に実行
- if: '$CI_COMMIT_BRANCH != "main" && $CI_COMMIT_BRANCH != "develop"'
build_main_or_develop:
stage: build
script:
- mkdir output && echo "main/develop artifact" > output/artifact.txt
artifacts:
paths: [output/]
expire_in: 4 weeks # main/developブランチは4週間保持
rules:
# main または develop の場合に実行
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"'
メリット:
- YAML の中で完結し、わかりやすい。
- GitLab の標準機能のみで実現できる。
デメリット:
- 共通部分が多い場合、ジョブ定義が冗長になる。
- (
extends
で緩和できる。)
- (
2. GitLab API を使ったクリーンアップジョブ
GitLab API を利用して定期的に古いアーティファクトを削除するスケジュールジョブを作成します。
- スケジュールパイプラインを設定: 特定の頻度(例: 毎日深夜)で実行されるパイプラインを作成。
-
API クリーンアップジョブ:
- GitLab API (Project -> Jobs -> Artifacts API など) を呼び出す。
- スクリプト (例: Python, Shell) で、特定の条件に合致するアーティファクトをリストアップし、API 経由で削除。
- API 認証のために、適切な権限を持つトークンが必要。
# 例:スケジュール実行用のクリーンアップジョブ
cleanup_old_artifacts:
stage: cleanup
image: curlimages/curl # または Python イメージなど
script:
# APIを叩くスクリプト (要実装)
- ./scripts/cleanup_artifacts.sh $GITLAB_API_TOKEN $CI_PROJECT_ID
rules:
# スケジュール実行の場合のみ動作
- if: '$CI_PIPELINE_SOURCE == "schedule"'
メリット:
- 柔軟な条件でクリーンアップ可能。
-
expire_in
に依存しない。
デメリット:
- API スクリプトの実装とメンテナンスが必要。
- API トークンの管理が必要。
- 設定が複雑になる。
3. アーティファクト保存専用ジョブを作成する
アーティファクトをダウンロードし、異なる expire_in
を設定して再度アップロードするジョブを定義します。
-
ビルドジョブ: アーティファクトを作成。
expire_in
は短くするか、never
に設定。 -
保存用ジョブ:
- ビルドジョブの完了後に実行されるように
needs
を設定。 - 特定のブランチでのみ実行されるように
rules
を設定。 - ビルドジョブと同じ
paths
を指定。 -
expire_in
に保持したい期間を設定。 -
script
でアーティファクトのダウンロードを確認。
- ビルドジョブの完了後に実行されるように
stages:
- build
- store_artifacts # アーティファクト保存用のステージを追加
build_job:
stage: build
script:
- mkdir output
- echo "artifact content" > output/artifact.txt
artifacts:
paths:
- output/
expire_in: 1 hour
store_artifacts_feature:
stage: store_artifacts
script:
- ls -R # アーティファクトを確認
artifacts:
paths:
- output/
expire_in: 1 day # Featureブランチ用の保存期間
needs:
- job: build_job
artifacts: true
rules:
- if: '$CI_COMMIT_BRANCH != "main" && $CI_COMMIT_BRANCH != "develop"'
store_artifacts_main_develop:
stage: store_artifacts
script:
- ls -R
artifacts:
paths:
- output/
expire_in: 4 weeks # main/developブランチ用の保存期間
needs:
- job: build_job
artifacts: true
rules:
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"'
メリット:
- ビルドと保存ポリシーを分離できる。
- ビルドジョブの YAML が複雑になりにくい。
デメリット:
- ジョブ数が増える。
- ダウンロードと再アップロードのオーバーヘッドがある。
-
needs
の設定が必要。
まとめ
GitLab CI/CD の artifacts:expire_in
では、現時点 (2025年4月時点) で CI/CD 変数を直接利用できません。そのため、ブランチごとにアーティファクトの有効期限を動的に変更するには、以下のいずれかの回避策を検討する必要があります。
-
rules
を使ったジョブ定義の分割 - GitLab API を利用したクリーンアップジョブ
- アーティファクト保存専用ジョブの作成
将来的には GitLab CI/CD の仕様が改善され、expire_in
での変数展開がサポートされることを期待しますが、それまではプロジェクトの状況に合わせて最適な方法を選択してください。
参考
- GitLab CI/CD
artifacts:expire_in
documentation: https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in - GitLab CI/CD
rules
documentation: https://docs.gitlab.com/ee/ci/yaml/#rules - GitLab API documentation: https://docs.gitlab.com/ee/api/