TL;DR: クイックフィックス
Robocopyは通常のルールに従いません。ほとんどのツールは成功時に0を、失敗時にそれ以外を返しますが、Robocopyはファイルのコピーに成功すると1を返します。GitHub ActionsやAzure DevOpsなどのほとんどのCI/CDプラットフォームは、その1を見て即座にビルドを終了させてしまいます。
これを修正するには、終了コードをインターセプトする必要があります。値が8未満の場合は、パイプラインに成功として扱うよう指示します。
robocopy source destination /options
if %ERRORLEVEL% LEQ 1 exit 0
なぜパイプラインが失敗するのか
標準的なCLIツールはバイナリ形式です。0は成功、1は失敗を意味します。CI/CDランナーは、0以外の終了コードを検出した瞬間にビルドを停止するように設計されています。しかし、Robocopyはビットマスクシステムを使用した詳細なロギング用に設計されており、同期中に何が起こったかを正確に伝えるために終了コードを使用します。
Robocopyの戻り値の内訳は以下の通りです。
- 0: ファイルはコピーされませんでした。コピー元とコピー先はすでに同一でした。
- 1: 成功。1つ以上のファイルがコピー先に正常にコピーされました。
- 2: コピー元には存在しない余分なファイルがコピー先に存在します。
- 4: 一致しないファイルまたはディレクトリが検出されました。
- 8: 失敗。いくつかのファイルをコピーできませんでした。
- 16: 致命的なエラー。通常、ディスクがいっぱいであるか、アクセスが拒否されたか、ネットワークパスが消失したことを意味します。
1は0よりも大きいため、ランナーはROBOCOPY : Exit : 1 (0x01)を見て最悪の事態を想定します。たとえ500MBのプロダクションアセットのアップロードが完璧に完了したばかりであっても、失敗のフラグを立ててしまいます。
終了コードロジックの修正
方法1:バッチスクリプトによるラップ
バッチスクリプトは、WindowsランナーでRobocopyを実行する最も一般的な方法です。.batまたは.cmdファイルを使用している場合は、コマンドの直後にチェックを追加します。これにより、スクリプトがランナーに正常な0を返すようになります。
robocopy "C:\build\artifacts" "\\deploy\server" /E /Z /R:5 /W:5
:: コードが0から7の間であれば、ビルドがパスするように強制的に0にします
if %ERRORLEVEL% LSS 8 exit /b 0
方法2:PowerShellでの処理
PowerShellは、多くの現代的なWindowsランナーのデフォルトシェルです。$LASTEXITCODE変数で最後の終了コードを追跡します。この値を手動でリセットすることで、パイプラインを継続させることができます。
robocopy "source" "destination" /MIR
if ($LASTEXITCODE -lt 8) {
$global:LASTEXITCODE = 0
}
このアプローチは、自動デプロイにおいてより安全です。実際の例外(コード8または16)が発生した場合には失敗させつつ、軽微な警告(余分なファイルを示す終了コード2など)を許容できます。
方法3:GitHub Actions YAMLでの修正
main.yml内でRobocopyを直接呼び出す場合は、コマンドをチェーンさせることができます。これは、個別のスクリプトファイルを作成せずにロジックを処理する最もクリーンな方法です。
- name: Deploy via Robocopy
shell: cmd
run: |
robocopy "src" "dest" /E /NP
if %ERRORLEVEL% LEQ 1 exit 0
修正の確認方法
これらの変更を適用した後、パイプラインのログを確認してください。テキスト出力には依然としてROBOCOPY : Exit : 1が表示されますが、ステップ自体には緑色のチェックマークが表示されるはずです。
- 手動ビルドをトリガーします。
- ログ内のRobocopyタスクを探します。
- パイプラインが停止せずに次のステップに進むことを確認します。
- コピー先のフォルダをスポットチェックして、10枚の画像であれ1,000個のDLLであれ、ファイルが実際に届いていることを確認します。
実際に重要なコードはどれか?
すべてのエラーを無視しないでください。Robocopyが8または16を返した場合、パイプラインは失敗すべきです。これらのコードは、Access Denied(アクセス拒否)やInsufficient Disk Space(ディスク空き容量不足)などの深刻な問題を示しています。LSS 8(8未満)のロジックを使用することで、デプロイを実際に中断させるエラーを捕捉しつつ、役立つ「ファイルコピー完了」の通知を無視することができます。

