GitHub Actionsでビルドしたdistや実行ファイルが次のジョブに存在しない場合、原因はジョブ間で作業フォルダーが自動共有されないことです。生成側のジョブでactions/upload-artifactを使って成果物を保存し、受取側のジョブでactions/download-artifactを使って取得します。
受取側にはneedsも指定します。ただし、needsが制御するのはジョブの実行順序であり、ファイル自体をコピーする機能ではありません。また、依存ライブラリを再利用するキャッシュと、デプロイ対象を受け渡すワークフローアーティファクトは用途が異なります。([GitHub Docs][1])
GitHub Actionsの別ジョブで生成ファイルが見つからない理由
同じジョブ内のステップは同じ作業環境を使うため、前のステップで作成したファイルを後続ステップから参照できます。
一方、別のジョブに移ると、前のジョブで使っていた作業フォルダーは引き継がれません。たとえば、次のような構成ではdeployジョブにdistは存在しません。
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
deploy:
runs-on: ubuntu-latest
steps:
- run: ls dist
actions/checkoutをdeployジョブでも実行したとしても、取得できるのはリポジトリに登録されたソースコードです。buildジョブが実行中に生成したdistまでは復元されません。
ファイルを別ジョブへ渡すには、次の流れを明示的に作ります。
buildジョブ
↓ ビルド
dist/
↓ upload-artifact
GitHub上のワークフローアーティファクト
↓ download-artifact
deployジョブのrelease/
↓
デプロイ
アーティファクトとキャッシュは使い分ける
GitHub Actionsにはファイルを保存する仕組みとして、アーティファクトとキャッシュがあります。しかし、両者は置き換え可能な機能ではありません。
| 項目 | ワークフローアーティファクト | キャッシュ |
|---|---|---|
| 主な目的 | ジョブが生成したファイルの保存・受け渡し | ワークフローの高速化 |
| 代表例 | dist、実行ファイル、パッケージ、テスト結果 | npm、Maven、Gradleなどの依存ファイル |
| 取得方法 | 名前や実行IDを指定して明示的にダウンロード | キャッシュキーを照合して復元 |
| 見つからない場合 | 必要な成果物がなければ処理を失敗させるべき | 再ダウンロードや再生成できる設計にする |
| デプロイ対象への適性 | 適している | 適していない |
キャッシュは、見つからなくても依存ファイルを再取得できることが前提です。反対に、デプロイするファイルは「このビルドで生成したもの」を確実に使う必要があります。そのため、distやバイナリの受け渡しにはアーティファクトを使用します。([GitHub Docs][2])
同一ワークフロー内で成果物を受け渡す設定例
以下は、Node.jsプロジェクトでnpm run buildを実行するとdistが生成される場合の例です。
アクションのメジャーバージョンは更新されるため、実際に導入するときは各アクションの公式READMEと使用中のランナー環境を確認してください。次の例では、公式READMEに掲載されているGitHub.com向けのバージョンを使用しています。
name: Build and deploy
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Verify build output
shell: bash
run: |
test -d dist
find dist -maxdepth 2 -type f -print
- name: Upload build artifact
uses: actions/upload-artifact@v7
with:
name: web-dist
path: dist/
if-no-files-found: error
retention-days: 7
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout deployment scripts
uses: actions/checkout@v6
- name: Download build artifact
uses: actions/download-artifact@v8
with:
name: web-dist
path: release/
- name: Verify downloaded files
shell: bash
run: |
test -d release
find release -maxdepth 2 -type f -print
- name: Deploy
run: ./scripts/deploy.sh release/
最後の./scripts/deploy.sh release/は説明用です。実際には、利用しているクラウドサービスやサーバーに応じたデプロイコマンドへ置き換えます。
生成側ではnameとpathを正確に指定する
upload-artifactで特に重要なのは、nameとpathです。
- name: Upload build artifact
uses: actions/upload-artifact@v7
with:
name: web-dist
path: dist/
if-no-files-found: error
nameは受け渡し用の識別名
nameは、受取側が目的のアーティファクトを指定するときに使用します。
name: web-dist
ダウンロード側にも、同じ名前を指定します。
name: web-dist
web-distとweb_distのように表記が異なれば、別の名前として扱われます。環境名やビルド対象を含める場合も、アップロード側とダウンロード側で完全に一致させてください。
マトリックスビルドでは、複数ジョブが同じ名前へアップロードしないようにします。
name: app-${{ matrix.os }}-${{ matrix.arch }}
現在のアーティファクトアクションでは、同じ名前のアーティファクトへ複数ジョブから追記する設計は避け、ジョブごとに一意な名前を付ける必要があります。
pathは実際の出力先に合わせる
ビルドツールによって出力フォルダーは異なります。
| ツールや構成の例 | よくある出力先 |
|---|---|
| Vite | dist/ |
| Create React App | build/ |
| Next.jsの静的出力 | out/ |
| .NETの発行処理 | 指定したpublish/など |
| Javaのビルド | target/またはbuild/libs/ |
思い込みでdist/を指定せず、ビルド直後に実際のパスを確認します。
- name: Inspect build output
run: |
pwd
find . -maxdepth 3 -type f -print
本番運用ではログが長くなりすぎないよう、確認範囲を出力フォルダー周辺に絞ります。
ファイルがない場合は警告ではなく失敗させる
upload-artifactは、指定したパスにファイルがない場合の動作をif-no-files-foundで変更できます。
if-no-files-found: error
デプロイ用アーティファクトでは、空の成果物を残して処理を継続するより、ビルドジョブをその場で失敗させたほうが原因を特定しやすくなります。公式READMEではwarn、error、ignoreが用意されています。
機密ファイルをアーティファクトへ含めない
アップロード対象をリポジトリ全体の.にすると、意図しないファイルまで保存される可能性があります。次のようなファイルは含めないでください。
.envや環境別の設定ファイル- SSH秘密鍵
- クラウドサービスの認証キー
- サービスアカウントのJSONファイル
- 認証情報を含む
.npmrc - デプロイ用アクセストークン
- データベースの接続情報
デプロイに必要な認証情報はアーティファクトへ埋め込まず、GitHub ActionsのSecretsやEnvironmentから実行時に渡します。
複数のパスや除外パターンも指定できます。
- name: Upload files
uses: actions/upload-artifact@v7
with:
name: web-dist
path: |
dist/
!dist/**/*.map
ただし、ソースマップが障害調査に必要な構成もあります。機械的に除外するのではなく、公開範囲や保管先を考えて判断してください。
現在のupload-artifactには隠しファイルの包含を制御する設定がありますが、デフォルトの除外動作だけを機密情報対策にしないことが重要です。アップロード対象を必要最小限のフォルダーへ絞ってください。
受取側はneedsと同じアーティファクト名を指定する
受取側のジョブには、生成側への依存関係を指定します。
deploy:
needs: build
これにより、deployはbuildの正常終了後に開始されます。needsがない場合、両方のジョブが並行して開始される可能性があります。
ただし、needsだけではファイルは受け渡されません。別途download-artifactが必要です。
- name: Download build artifact
uses: actions/download-artifact@v8
with:
name: web-dist
path: release/
役割は次のように分かれます。
| 設定 | 役割 |
|---|---|
needs: build | ジョブの実行順序を制御する |
name: web-dist | 取得するアーティファクトを特定する |
path: release/ | ダウンロードしたファイルの展開先を指定する |
ダウンロード後のフォルダー構造を確認する
単一のアーティファクトを名前で指定した場合、その内容はpathで指定したフォルダーへ直接展開されます。
たとえば、次の指定なら、ファイルは原則としてrelease/の直下へ展開されます。
with:
name: web-dist
path: release/
release/web-dist/が自動作成されると思い込むと、デプロイコマンドの参照先を間違えます。
一方、nameを省略して複数のアーティファクトをまとめて取得すると、標準ではアーティファクト名ごとのサブフォルダーが作成されます。
デプロイ処理を追加する前に、一度だけ構造を表示すると安全です。
- name: Inspect downloaded artifact
run: find release -maxdepth 3 -type f -print
確認後は、必要に応じて表示範囲を狭めるか、このステップを削除します。
保存期限はretention-daysで指定する
アーティファクトごとの保存期限は、アップロード時のretention-daysで指定できます。
- uses: actions/upload-artifact@v7
with:
name: web-dist
path: dist/
retention-days: 7
ただし、指定できる日数はリポジトリ、組織、Enterprise側で設定された上限を超えられません。([GitHub Docs][1])
保存期間は、次の基準で決めます。
| 利用目的 | 保存期間の考え方 |
|---|---|
| 同じワークフロー内で直後にデプロイするだけ | 短めでよい |
| 数日後に手動で再デプロイする | 再実行する可能性がある期間を確保する |
| 過去版へのロールバックに利用する | 運用上必要な世代を保持できる期間にする |
| 長期配布する正式版 | アーティファクト以外の保管先も検討する |
ワークフローアーティファクトは永続的な配布場所ではありません。長期保管が必要な実行ファイルやパッケージは、GitHub Releases、GitHub Packages、オブジェクトストレージなど、用途に合った保管先を検討します。
別の実行や別ワークフローから取得する方法
download-artifactは、指定がなければ現在のリポジトリにおける現在のワークフロー実行を対象にします。
別のワークフロー実行から取得する場合は、対象の実行IDと、必要なアクセス権を持つトークンを指定します。
- name: Download artifact from another run
uses: actions/download-artifact@v8
with:
name: web-dist
github-token: ${{ secrets.ARTIFACT_READ_TOKEN }}
repository: example-org/example-repository
run-id: 1234567890
path: release/
各項目の意味は次のとおりです。
| 項目 | 内容 |
|---|---|
github-token | 対象リポジトリのアーティファクトを読み取れるトークン |
repository | 所有者名/リポジトリ名 |
run-id | アーティファクトを生成したワークフロー実行のID |
name | 取得するアーティファクト名 |
path | 展開先 |
run-idはジョブIDや連番表示用のrun_numberではありません。workflow_runイベントから取得する場合は、状況に応じて次の値を利用できます。
run-id: ${{ github.event.workflow_run.id }}
別リポジトリから取得する場合、トークンには対象リポジトリに対するactions:read相当の権限が必要です。非公開リポジトリでは、トークンを発行したユーザーやGitHub App自体が対象リポジトリへアクセスできなければ取得できません。
非公開アーティファクトのアクセス権と有効期限
非公開リポジトリのアーティファクトは、URLを知っているだけで誰でも取得できる公開ファイルではありません。ブラウザから取得する場合はログインとリポジトリへのアクセス権が必要です。
また、次のいずれかに該当すると取得できなくなります。
- 保存期限を過ぎた
- アーティファクトが削除された
- 元のワークフロー実行が削除された
- リポジトリが削除された
- 使用するトークンに読み取り権限がない
アーティファクトURLも、アーティファクト、実行、リポジトリが存在し、必要なアクセス権がある間だけ利用できます。
GitHub.comとGitHub Enterprise Serverで同じ版を使わない
GitHub.comで動作するアクションの最新版が、GitHub Enterprise Serverでもそのまま使えるとは限りません。
現在の公式READMEでは、upload-artifactとdownload-artifactの新しい系列について、GitHub Enterprise Serverでは未対応となる版があることが明記されています。GHESでは、サーバー側が対応する専用の版を選ぶ必要があります。
特に確認する項目は次のとおりです。
- GitHub.comかGitHub Enterprise Serverか
- 使用しているGHESのバージョン
- GitHub-hosted runnerかself-hosted runnerか
- アクションが必要とするNode.jsランタイム
- self-hosted runnerの最低対応バージョン
- 組織側で許可されているアクションとバージョン
GitHub.com向けの記事からYAMLをコピーしただけでは、GHESでUnable to resolve actionやランタイム関連のエラーになることがあります。各アクションのREADMEにある「GHES Support」と、自社環境の管理者向けドキュメントを確認してください。
よくあるエラーと確認ポイント
| 症状 | 主な原因 | 対処 |
|---|---|---|
No files were found with the provided path | ビルド出力先とpathが一致していない | ビルド直後にpwdとfindで確認する |
Artifact not found | nameの不一致、別実行を参照、期限切れ | 名前、run-id、保存期限を確認する |
| ダウンロードは成功したがファイルが見つからない | 展開先の構造を誤認している | ダウンロード直後にfindで確認する |
| デプロイがビルドより先に始まる | needsがない | needs: buildを指定する |
| 別リポジトリから403や404になる | トークンの権限不足 | 対象リポジトリへの読み取り権限を付ける |
| GHESでアクションを解決できない | GitHub.com向けの非対応版を使用している | GHES対応版へ変更する |
| ダウンロード後に実行ファイルを起動できない | 実行権限が保持されていない | chmod +xを実行するか、事前にアーカイブする |
通常の圧縮形式でアップロードした場合、ダウンロード後のファイル権限が元の状態と同じとは限りません。実行権限が必要なスクリプトやバイナリでは、再度chmodするか、権限を保持できる形式にまとめてからアップロードします。
まず修正するべき設定
ビルドしたファイルが次のジョブに存在しない場合は、次の順番で修正します。
- ビルド直後に、実際の出力フォルダーを確認する
upload-artifactで名前とパスを指定するif-no-files-found: errorで空のアップロードを防ぐ- 受取側へ
needs: buildを追加する download-artifactで同じ名前を指定する- ダウンロード先を明示し、直後にファイル構造を確認する
- 別実行から取得する場合だけ、トークンと
run-idを追加する - 保存期限とGitHub.com・GHESの対応版を確認する
基本形は、生成側でアップロードし、依存関係を設定した受取側で同じ名前のアーティファクトをダウンロードすることです。キャッシュで代用せず、ビルド済み成果物を明示的に受け渡せば、デプロイジョブが別のランナーで実行されても同じファイルを利用できます。
[1]: https://docs.github.com/en/actions/tutorials/store-and-share-data “Store and share data with workflow artifacts – GitHub Docs”
[2]: https://docs.github.com/en/actions/concepts/workflows-and-actions/dependency-caching “Dependency caching – GitHub Docs”

コメント