1
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?

GitHub Actions - cacheとartifact

Last updated at Posted at 2025-01-02

内容

GitHub Actionsのcache(actions/cache)とartifact(actions/upload-artifact, actions/download-artifact)の用途、有効範囲について記載する

cache

actions/cache1個でcacheのsave/restoreする方法と、
actions/cache/save, actions/cache/restoreでcacheのsave/restoreする方法がある
本記事では前者について記載する

cacheのパラメータpath, keyや、actions/cache/save, actions/cache/restoreを使った実装例はGitHub Actions - cache参照

cacheの用途

job、workflowはそれぞれ実行環境が異なるため、毎回依存関係をインストールする必要がある
cacheによりインストールした依存関係の再利用することができる

ツールのcache

npm、pip等、代表的な各種ツールのcache例はExamples参照

その他、例えばpoetryをインストールするsnok/install-poetryは、ubuntuでのcache方法がCaching the Poetry installationに記載されている

また、ツールのインストールactionにcache機能が備わっているものもある
例えば、taskをインストールするarduino/setup-taskで、Readmeでは特に触れられていないが、
実装を見ると、@actions/tool-cacheを使ったcache処理が実装されていることがわかる

  // look if the binary is cached
  let toolPath: string;
  toolPath = tc.find("task", targetVersion);

  // if not: download, extract and cache
  if (!toolPath) {
    toolPath = await downloadRelease(targetVersion);
    core.debug(`Task cached under ${toolPath}`);
  }

setup-* actionによるツールのcache

Github管理のsetup-node等のツールセットアップActionにはcache機能がある
以下のようにワークフローの依存関係のキャッシングについてに記載されているだけの種類がある

2025-01-02-14-37-46.png

以下のようにcacheオプションを指定することでcacheが有効になる
node_modulesフォルダがcacheされるわけではない

steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: 'npm'

cacheのsaveタイミングと有効範囲

主なcacheの使用用途はツールのcacheと思われるが、
以下のファイルをcacheする例を使って、cacheのsaveタイミングと有効範囲を確認する

name: cache save test

on:
  workflow_call:
jobs:
  cache_save:
    name: cache save
    runs-on: ubuntu-latest
    env:
      cache_key: cache_2025_01_01  # ※ 本来このような適当なkeyは使用しない
      cache_dir: cache_test
    steps:
      - name: Cache restore/save
        id: cache_restore
        uses: actions/cache@v4
        with:
          path: ${{ env.cache_dir }}
          key: ${{ env.cache_key }}

      - name: Create cache file  # cacheするファイルの作成
        if: steps.cache_restore.outputs.cache-hit != 'true'  # cacheがなかった(restoreに失敗した)場合に実行
        uses: actions/github-script@v7
        with:
          result-encoding: string
          script: |
            const fs = require('fs');
            fs.mkdirSync("${{ env.cache_dir }}");
            fs.writeFileSync( "${{ env.cache_dir }}/cache_test_1.txt", "123456789" );
            fs.writeFileSync( "${{ env.cache_dir }}/cache_test_2.txt", "987654321" );

      - name: Read cache file  # cacheファイルの読込
        uses: actions/github-script@v7
        with:
          result-encoding: string
          script: |
            const fs = require('fs');
            const messages = [];
            const caches = fs.readdirSync("${{ env.cache_dir }}");
            console.log(`caches: ${caches}`);

            for (const cache of caches) {
              messages.push(fs.readFileSync(`${{ env.cache_dir }}/${cache}`, 'utf8'));
            }
            console.log(messages.join("\n"));

以下、初回実行時の結果
Cache restore/saveでcacheをrestoreするが、cacheがないためCreate cache fileでcacheするファイルを作成、
Read cache fileで作成したファイルの読み出し、全てのstep終了後にPost Cache restore/saveでcacheがsaveされていることがわかる

2025-01-02-14-25-15.png

別途同じworkflowを実行すると、以下のようにcacheのrestoreに成功し、Create cache fileはスキップされ、
Read cache fileで作成したファイルの読み出し、すでにcacheが存在するためsaveは実行されない

2025-01-02-14-25-48.png

cacheはworkflowを超えて参照することができるため、それを考慮してcacheのkeyは設定する必要がある
キャッシュキーの作成にあるようにhashFiles('**/lockfiles')や、github.shaを使用する

artifact

actions/upload-artifactactions/download-artifactを使って、artifactをアップロード/ダウンロードすることができる

artifactの用途

artifactとしてアップロードすることで、workflow内のjob間でデータを共有することができる
また、そのartifactはworkflow終了後にユーザによってダウンロードすることができる

artifactの有効範囲

以下の複数artifactをアップロード/ダウンロードする例を使って、artifactの有効範囲を確認する

./.github/workflows/reuse_artifact_create.yml
name: create artifact  # 指定した文字列からテキストファイルのartifactを作成するreusable-workflow

on:
  workflow_call:
    inputs:
      name:  # artifactの名前
        required: true
        type: string
      contents:  # テキストファイルのartifactに書き込む内容
        required: true
        type: string
jobs:
  create_artifact:
    name: create artifact
    runs-on: ubuntu-latest
    steps:
      - name: Create artifact
        uses: actions/github-script@v7
        with:
          result-encoding: string
          script: |
            const fs = require('fs');
            const contents = "${{ inputs.contents }}";
            fs.writeFileSync( "${{ inputs.name }}.txt", contents );
  
      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ inputs.name }}
          path: ${{ inputs.name }}.txt
          retention-days: 1
name: artifact test

on:
  workflow_call:
    inputs:
      artifact_prefix:
        required: false
        type: string
        default: test-artifact
jobs:
  create_artifact_1:  # 適当なartifactをアップロードする
    name: create artifact 1
    uses: ./.github/workflows/reuse_artifact_create.yml
    secrets: inherit
    with:
      name: ${{ inputs.artifact_prefix }}-1
      contents: "ABCDE"

  create_artifact_2:  # 適当なartifactをアップロードする
    name: create artifact 2
    uses: ./.github/workflows/reuse_artifact_create.yml
    secrets: inherit
    with:
      name: ${{ inputs.artifact_prefix }}-2
      contents: "12345"

  download_artifact:  # artifactをダウンロードする
    name: download artifact
    runs-on: ubuntu-latest
    needs: [create_artifact_1, create_artifact_2]
    env:
      artifacts_path: artifacts
    steps:
      - name: Download All Artifacts
        uses: actions/download-artifact@v4
        with:
          path: ${{ env.artifacts_path }}  # artifactのダウンロード先
          pattern: ${{ inputs.artifact_prefix }}*  # フィルターで複数artifactを指定する
          merge-multiple: true

      - name: test result
        uses: actions/github-script@v7
        with:
          result-encoding: string
          script: |
            const fs = require('fs');
            const messages = [];
            const artifacts = fs.readdirSync("${{ env.artifacts_path }}");
            console.log(`artifacts: ${artifacts}`);

            for (const artifact of artifacts) {
              messages.push(fs.readFileSync(`${{ env.artifacts_path }}/${artifact}`, 'utf8'));
            }
            console.log(messages.join("\n"));

以下、実行結果

2025-01-02-14-31-53.png

以下のようにworkflowのSummaryにArtifactsとして表示されていることがわかる、ダウンロードも可能
この結果からartifactはworkflowに紐づいていることがわかる

ただし、パラメータrepositoryrun-idを使うことでrepository、workflowを超えて参照することもできる

artifactは基本的にworkflow内で参照するもののため、artifactのnameはworkflow内で一意であればよい
同名のartifactのアップロードは上書きとなる

2025-01-02-16-58-49.png

ちなみにworkflowをRe-runすると、ArtifactsはLatestのみとなる

2.png

1.png

別途artifactのダウンロードのみを行うworkflowを実行しても以下のようにダウンロードはできない

2025-01-02-14-30-29.png

1
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
1
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?