GitHub Actionsのartifactでdotfileが欠けるとき、隠しファイル除外とsecret安全性を確認する

GitHub Actions Artifactでdotfileが欠ける原因を調べ、必要な隠しファイルだけを安全に含める方法を解説します。

AIものさし編集部

GitHub ActionsのArtifactをダウンロードした後に「設定ファイルだけない」と気づいたら、まずビルド成果物にそのファイルが存在したか、upload-artifactの対象pathに含まれていたか、使用したActionのversionで隠しファイルが除外されるかを分けて確認します。2024年8月30日公開のupload-artifact v4.4.0から、隠しファイルと隠しディレクトリは既定でartifactに含まれなくなりました。v4.4.0以降のREADMEでも既定値はfalseです。必要なdotfileを含める設定はありますが、最初から隠しファイルをまとめて許可するのではなく、対象を絞り、秘密情報を除外した後に使うのが安全です。

まず「生成されなかった」と「uploadされなかった」を分ける

見つからないファイルを直ちにupload設定の問題と判断すると、調べる範囲を誤ります。例えば、アプリの設定処理が.build内へファイルをコピーしなかった場合と、Artifactが隠しファイルを除外した場合では、修正する工程が異なります。次の三つの地点で同じ相対pathを確認してください。

表は横にスクロールできます

確認地点確認するものここに無いときの主な疑い
ビルド直後Runner上の生成物に対象ファイルがあるかbuild script、生成条件、環境変数、コピー先
upload直前upload-artifactのpathがそのファイルを含むか相対path、workspace、glob、除外pattern
ダウンロード後Artifact内の相対pathとファイル名hidden-file既定除外、wildcardの階層、別artifactの取得

実行環境を保持できる場合は、upload直前の一覧を一時ログやmanifestに出し、期待pathと比較します。設定値だけを見ても、実際のworking directoryや生成場所が違えば対象に入りません。Runnerログには秘密値を出さず、ファイル名と相対path、必要ならサイズやハッシュだけを記録します。ディレクトリ一覧を公開ログへ出すと、秘密を含む名前や構成が漏れる環境では、許可されたprivate logに限定してください。

Actionのversionを固定してから挙動を読む

workflowで指定したusesのversionを確認します。GitHub公式のv4.4.0 release noteは、このversionで隠しファイルを既定で含めなくなったことと、継続して含めるためのinclude-hidden-filesオプションが追加されたことを明記しています。現在のupload-artifact READMEも、include-hidden-filesの既定値をfalseとし、隠しファイルは既定で無視されると説明しています。

そのため、「GitHub Actionsはdotfileを常に除外する」とは書けません。Actionのversionや、組織が利用するGitHub Enterprise Server環境、workflow内の実際の設定で挙動を判断します。特に古いversionを使用している場合、現行READMEだけではその実行時の挙動を確定できません。workflowのuses行、依存関係の固定方法、実行ログを一緒に確認し、該当versionのrelease noteまたはREADMEで確かめます。

GitHubの公式リポジトリでは、v4.4.0以降にhidden filesを含めるにはinclude-hidden-filesを明示する例が示されています。またpathへ複数のパターンや除外patternを指定できます。ワイルドカードを使用した場合にartifact内の階層がどう残るかは、指定pathの共通部分や最初のwildcard位置に影響されます。ファイルが入っていても想定と違う場所へ展開されているケースを見逃さないでください。

必要なdotfileだけを選んで含める

すべてのhidden fileを含めるのではなく、必要なファイルを明示して対象を狭めます。例えば、静的サイトの公開用成果物に必要なwell-known設定が問題なら、そのファイルまたはその公開ディレクトリを対象にします。プロジェクト全体の「.」から始まるファイルをまとめてartifactに含めると、ローカル開発用設定、認証情報、履歴など本来配布しないファイルが混ざる可能性があります。

設定変更前に、まずupload対象を一覧化します。次に、秘密情報の候補をdenylistだけでなく、成果物を構成するディレクトリのallowlistでも管理します。例えば、公開配布に必要な .well-known/apple-app-site-association は許可する一方、.env、.npmrcに含まれるtoken、cloud credential、private key、.git以下は除外するという形です。これは例示であり、実際に含めるファイル名と秘密の保管場所は、プロジェクトの構成に合わせて確認してください。

include-hidden-filesを有効にする場合は、同じ設定内でpathを限定し、不要なファイルを除外します。ただし、exclude patternが秘密情報の唯一の防御にならないようにしてください。想定外のファイルが成果物のディレクトリへ生成されない構成にし、upload直前の一覧検査でも許可対象との一致を確認します。設定例を採用する前に、使っているAction versionがそのinputをサポートすることも確認します。

pathとglobの見直し順

対象ファイルがrunnerにはあるのにartifactにないときは、以下の順番で調べると原因を切り分けやすくなります。

  1. workflowの該当jobが実行するbranch・commit・matrixを特定する。別のrunや別jobのartifactをダウンロードしていないか確認する。

  2. build stepのworking-directoryと出力先を確認する。相対pathは、workflowを実行する現在のdirectoryを基準に解釈されます。

  3. upload-artifactのpathを確認する。ディレクトリ、単一ファイル、globのどれを指定したか、除外patternが対象を外していないかを確認する。

  4. uploadの直前に、対象ファイルの存在と相対pathを確認する。存在しない場合はupload設定ではなくbuild/copy工程を修正する。

  5. 対象の最初の文字がピリオドか、親ディレクトリにピリオドで始まる名前があるかを確認する。v4.4.0以降では親ディレクトリがhiddenの場合も除外対象になり得ます。

  6. 実行ログでuploadされたファイルのパスを確認し、ダウンロード後にはartifactを展開して期待pathと比較する。

  7. 必要なhidden fileだけを明示的に許可し、再実行後に他のファイルが混入していないことも確認する。

ここで重要なのは、「対象を含むglob」と「ディレクトリを丸ごと指定する方法」を使い分けることです。複数パスを組み合わせると、Artifact内で保持されるrootやディレクトリ構造が変わる場合があります。単にファイル数が合うかではなく、展開後に必要な相対pathが保たれているかを確認してください。

含めてよいファイルかを先に判定する

hidden fileが欠けることは、常に直すべき障害ではありません。CI artifactを後続jobで使うための一時設定なのか、公開用のstatic siteへ配置するためのファイルなのか、ローカル開発用なのかで必要性が異なります。以下の基準で判断します。

表は横にスクロールできます

区分例方針
公開成果物として必要.well-known配下の公開設定など許可対象を限定し、内容を確認して含める
後続jobの処理に必要テストfixtureや生成時設定利用job・保持期間・閲覧権限を確認
実行環境固有で秘密を含む.env、秘密鍵、クラウド認証情報Artifactへ入れない。秘密はGitHub Secrets等の適切な保管経路から実行時に渡す
用途が不明古い設定やdotfileownerと利用箇所を確認するまで除外する

.envという名前だけで中身を推定したり、ファイル名が公開用に見えるから安全と決めたりしてはいけません。秘密値そのものはworkflow logへ表示せず、機密情報を出さずにfile path・設定責任者・利用箇所を確認します。Artifactは後続のjobや権限を持つ利用者から取得され得るため、最小限のファイルだけを含める考え方が重要です。組織のアクセス設定やartifact保持条件も、公開範囲と運用目的に照らして確認してください。

失敗ケースと安全な戻し方

よくある失敗は、欠けたファイルを直そうとしてinclude-hidden-filesを有効にした後、.envや.gitまでArtifactへ入れてしまうことです。この変更を急いでmergeせず、まず差分のworkflow設定と生成物一覧を確認します。すでに秘密値を含むArtifactを作成し、権限のない人が取得できた可能性がある場合は、ファイルを消すだけでは漏えい対応になりません。該当credentialの発行元で無効化・ローテーションし、取得可能だった範囲や共有先を管理者と調査します。秘密を含むArtifactの削除やrunの扱いは、保持・監査要件を確認したうえで権限者が決めてください。

もう一つの失敗は、workflowのglobを広げたために必要ファイルは入ったが、別のディレクトリ構造や生成物まで含まれたケースです。Artifactの中身をダウンロードし、ファイル一覧、階層、容量、意図しない拡張子の有無を比較します。ファイル数が期待どおりでも、secretが混ざっていない保証にはなりません。許可されたファイル名の集合と比較する検査を置くと、再発を見つけやすくなります。

Actionをversion pinしていない場合は、アップデートで既定挙動や機能が変わる可能性があります。GitHubの依存更新方針に従って変更をレビューし、version変更時にはArtifactの中身を確認するテストを含めます。現象が古いrunで起きているなら、その時点のworkflow revisionとAction versionを調べます。現在のmain branchの設定だけから過去のrunの挙動を推測しないでください。

再現テストと合格条件

設定の調整は、秘密のないテスト用fixtureで行います。公開してよい .well-known/sample.txt と、公開してはいけない .env.exampleではないテスト用の秘密ファイルを別ディレクトリに置くのではなく、機密値を持たないダミーfixtureで除外確認を行う方法を選びます。実secretをテストfixtureにコピーしてはいけません。テスト用のhidden fileを含む小さなディレクトリを作り、対象Action versionとpath設定を固定したrunを実行します。

確認表は次のように作れます。

表は横にスクロールできます

試験期待結果実際の確認
upload前に許可dotfileが生成される指定pathに存在job logでpathと存在のみ確認
hidden除外を有効のまま実行fixtureが入らないdownloaded artifactのfile list
許可したhidden pathを指定必要fileだけ入る展開後の相対pathとsha256
除外対象の秘密fixture入らないartifact一覧に存在しない
wildcardを使う階層が想定どおり展開後にpathを照合
workflow更新後余計なfileが増えないallowlistとの集合差分

合格条件は、必要ファイルが正しい相対pathに存在し、秘密ファイルやGit履歴が含まれず、他の公開成果物が欠落していないことです。uploadログの成功だけでは内容検証になりません。後続jobがArtifactを使う場合は、download stepでも同じファイル構成を確認します。再現テストを実施していない場合、設定手順を提示しただけで「動作確認済み」と書かず、利用者が実行する確認として残します。

次にすること

対象runのworkflow revisionとusesで固定されたupload-artifact versionを一つ開き、実際のbuild output、upload path、除外patternを並べてください。次に欠けたファイルを含むことの必要性をownerと確認し、必要なら秘密を含まないfixtureで再現します。include-hidden-filesを使うと決めた場合は、対象ディレクトリを狭くし、秘密候補のfile listと除外結果をチェックしてからArtifactを作成します。公開用設定が見つからない問題と、機密情報がArtifactへ入った可能性は、同じ「dotfileの問題」として扱わず別の対応として記録してください。

この手順を終えたら、記事には「どのAction versionで何が欠けたか」「どのpathを許可したか」「秘密を含めずに取得後の中身をどう検証したか」を記録します。具体的なCI runやrepositoryへアクセスしていない場合は、実際に発生した原因を特定したとは書かず、読者が自分のrunで確認できる診断手順として扱います。

出典と確認範囲

公式READMEとrelease noteを2026-10-15に確認しました。v4.4.0からのhidden file既定除外とinclude-hidden-filesの利用、現在のREADMEで示されるpath・除外patternの考え方を確認しています。古いversionや利用環境の具体的な挙動は、実際のworkflowで指定されたversionの資料とrun結果で確認してください。この記事ではGitHub repository上のworkflowを実行しておらず、Reader向けの切り分け手順を記載しています。