GitHub Actions で、外部のサービスに記事を下書きとして投稿するワークフローを動かしています。drafts/ に置いた記事を定期実行で投稿し、終わったら posted/ に移してコミットする作りです。
ある日、投稿はできていたのに、そのあとでデバッグ用のスクリーンショットを Artifact に保存するステップが失敗していました。ログにはこう出ていました。
Failed to CreateArtifact: Artifact storage quota has been hit. Unable to upload any new artifacts. Usage is recalculated every 6-12 hours.
Artifact の保存が失敗したせいで、後に続くステップが動かず、不具合が起きていました。 古い Artifact を消し、保存のステップに continue-on-error: true と retention-days を付けて直しました。
解決方法
1. 古い Artifact を消す
まず、リポジトリにどれだけ Artifact が残っているかを見ます。
gh api repos/<owner>/<repo>/actions/artifacts --paginate \
--jq '.artifacts[] | [.id, .name, (.size_in_bytes/1048576*100|round/100|tostring)+" MB", .created_at, (.expired|tostring)] | @tsv' \
| sort -t$'\t' -k4 -r
ID・名前・サイズ・作成日時・期限切れかどうかが、新しい順に並びます。今回は、デバッグ用のスクリーンショットと HTML が 103件、約590MB たまっていて、どれも期限切れになっていませんでした。
消しても困らないものだったので、全部消しました。
gh api repos/<owner>/<repo>/actions/artifacts --paginate --jq '.artifacts[].id' | while read id; do gh api -X DELETE repos/<owner>/<repo>/actions/artifacts/$id; done
このコマンドはリポジトリの Artifact をすべて消します。調査に使いたいものが残っているときは、一覧を見てから ID を選んで消すほうが安全です。
消しても、すぐには保存できるようになりません。 エラー文のとおり、使用量の再計算には時間がかかります。GitHub のドキュメントにもこう書かれています。
GitHub updates your artifact storage usage within 6 to 12 hours. (GitHub は Artifact のストレージ使用量を6〜12時間以内に更新します)
実際に、消してから約6時間半後の実行では、まだ同じエラーが出ていました。次に Artifact を保存した約1日後の実行では、保存できていました。
2. 保存のステップに continue-on-error と retention-days を付ける
デバッグ用の保存のステップに、2行を足しました(差分の抜粋)。
- name: Upload debug artifacts
if: always() && steps.select.outputs.found == 'true'
uses: actions/upload-artifact@v4
+ continue-on-error: true
with:
...
if-no-files-found: ignore
+ retention-days: 7
continue-on-error: true:このステップが失敗しても、ジョブを失敗にせず、後のステップに進みます。デバッグ用の保存は、失敗しても投稿の結果には関係ないので、ジョブを止めないようにしましたretention-days: 7:Artifact の保存期間です。指定しないと、リポジトリの設定の期間(既定は90日)になります。調査には直近の数日分があれば足りるので、7日にしました
同じ保存のステップを持つほかのワークフローにも、同じ2行を足しました。
起きたこと
失敗した実行の、ステップごとの結果はこうでした。
| ステップ | 結果 |
|---|---|
| 記事を選ぶ | success |
| 記事を投稿する | success |
| デバッグ用の Artifact を保存する | failure |
posted/ へ移してコミットする |
skipped |
投稿は成功しているのに、後に続く posted/ へ移すステップは、失敗ではなくスキップされていました。
原因
後片付けのステップが飛ばされた理由
2つのステップの if: は、こうなっていました。
# デバッグ用の Artifact を保存する
if: always() && steps.select.outputs.found == 'true'
# posted/ へ移してコミットする
if: steps.select.outputs.found == 'true'
保存のステップには always() が付いているので、前のステップが失敗しても動きます。一方、posted/ へ移すステップには、always() や failure() のような状態を見る関数がありません。GitHub のドキュメントには、こう書かれています。
A default status check of
success()is applied unless you include one of these functions. (これらの関数を含めない限り、既定でsuccess()の状態チェックが適用されます)
つまり、移すステップの条件は、実際には「success() かつ対象の記事がある」になります。その前のどこかのステップが1つでも失敗すると、if: に書いた条件を満たしていてもスキップされます。 今回は、保存のステップの失敗がこれに当たりました。
容量を超えた理由
Artifact のストレージには上限があります。無料プラン(GitHub Free)の個人アカウントでは 500MB で、GitHub Packages と同じ枠を、アカウントのすべてのリポジトリで分け合います。
Actions artifacts and GitHub Packages storage share the same pooled allowance (Actions の Artifact と GitHub Packages のストレージは、同じ枠を共有します)
このワークフローは、投稿のたびにスクリーンショットと HTML を保存していました。保存期間を指定していなかったので、既定の90日が過ぎるまで1件も消えず、2か月分で約590MB になっていました。このリポジトリだけで 500MB を超えていたことになります。同じ作りのほかのリポジトリにも、合わせて100MBほど残っていました。
continue-on-error の注意点
直したあとの最初の実行では、上に書いたとおり、まだ容量超過のエラーが出ていました。それでも、保存のステップの結果は success になり、posted/ へ移すステップも動いて、ジョブは成功で終わりました。直したかった動きのとおりです。
その代わり、保存が失敗しても、ログを開かない限り気づけなくなります。 デバッグ用の保存なら、これで困らないと思います。結果を後で使うステップに付けると失敗が見えなくなるので、付けるのは「失敗しても本来の処理に関係ないステップ」だけにしています。
後片付けのステップの if: に always() を付けて直すこともできます。ただ、それだと投稿そのものが失敗したときにも posted/ へ移してしまうので、この作りには向いていないと思います。
確かめた環境
- GitHub Actions(
ubuntu-latest) actions/upload-artifact@v4- 無料プラン(GitHub Free)の個人アカウント
まとめ
Artifact storage quota has been hitは、アカウント全体の Artifact(と Packages)のストレージが上限に達したときのエラー- 古い Artifact を消しても、使用量の再計算には6〜12時間かかる。今回は約6時間半後でもまだ保存できなかった
if:に状態を見る関数がないステップにはsuccess()が付くので、前のステップが1つ失敗するとスキップされる- デバッグ用の保存には
continue-on-error: trueを付けて、失敗してもジョブを止めないようにした retention-daysを指定しないと90日残るので、毎回保存するものは短くした
定期実行で Artifact を毎回保存しているワークフローがあれば、一度 retention-days と、後片付けのステップの if: を見ておくと安心かなと思います。
参考
- Expressions – GitHub Docs(
success()・always()の説明) - GitHub Actions の課金(GitHub Docs)(ストレージの枠と、使用量の更新のタイミング)
- actions/upload-artifact(
retention-daysの説明)
