0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitLab CI/CD: artifacts:expire_inで変数が使えずブランチごとに有効期限を変えられない件とその回避策

Last updated at Posted at 2025-04-13

GitLab CI/CD: artifacts有効期限をブランチごとに設定する3つの方法

はじめに

GitLab CI/CDにてブランチごとに成果物 (artifacts) の保存期間を変えたいと考え、実現しようとしたところ、いくつかの課題に直面しました。例えば、main ブランチや develop ブランチの成果物は長く保持し、フィーチャーブランチのものは短期間で削除したい、といったケースです。

直感的には .gitlab-ci.ymlartifacts: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 を利用して定期的に古いアーティファクトを削除するスケジュールジョブを作成します。

  1. スケジュールパイプラインを設定: 特定の頻度(例: 毎日深夜)で実行されるパイプラインを作成。
  2. 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 を設定して再度アップロードするジョブを定義します。

  1. ビルドジョブ: アーティファクトを作成。expire_in は短くするか、never に設定。
  2. 保存用ジョブ:
    • ビルドジョブの完了後に実行されるように 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 変数を直接利用できません。そのため、ブランチごとにアーティファクトの有効期限を動的に変更するには、以下のいずれかの回避策を検討する必要があります。

  1. rules を使ったジョブ定義の分割
  2. GitLab API を利用したクリーンアップジョブ
  3. アーティファクト保存専用ジョブの作成

将来的には GitLab CI/CD の仕様が改善され、expire_in での変数展開がサポートされることを期待しますが、それまではプロジェクトの状況に合わせて最適な方法を選択してください。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?