内容
GitHub Actionsのcache(actions/cache
)とartifact(actions/upload-artifact
, actions/download-artifact
)の用途、有効範囲について記載する
cache
actions/cache
1個で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機能がある
以下のようにワークフローの依存関係のキャッシングについてに記載されているだけの種類がある
以下のように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されていることがわかる
別途同じworkflowを実行すると、以下のようにcacheのrestoreに成功し、Create cache file
はスキップされ、
Read cache file
で作成したファイルの読み出し、すでにcacheが存在するためsaveは実行されない
cacheはworkflowを超えて参照することができるため、それを考慮してcacheのkey
は設定する必要がある
キャッシュキーの作成にあるようにhashFiles('**/lockfiles')
や、github.sha
を使用する
artifact
actions/upload-artifact
、actions/download-artifact
を使って、artifactをアップロード/ダウンロードすることができる
artifactの用途
artifactとしてアップロードすることで、workflow内のjob間でデータを共有することができる
また、そのartifactはworkflow終了後にユーザによってダウンロードすることができる
artifactの有効範囲
以下の複数artifactをアップロード/ダウンロードする例を使って、artifactの有効範囲を確認する
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"));
以下、実行結果
以下のようにworkflowのSummaryにArtifactsとして表示されていることがわかる、ダウンロードも可能
この結果からartifactはworkflowに紐づいていることがわかる
ただし、パラメータrepository
、run-id
を使うことでrepository、workflowを超えて参照することもできる
artifactは基本的にworkflow内で参照するもののため、artifactのname
はworkflow内で一意であればよい
同名のartifactのアップロードは上書きとなる
ちなみにworkflowをRe-runすると、ArtifactsはLatestのみとなる
別途artifactのダウンロードのみを行うworkflowを実行しても以下のようにダウンロードはできない