⌛
タイムアウトと手動キャンセルを区別したかった [GitHub Actions]
概要
if: cancelled()
でタイムアウトと手動キャンセルを区別したかったのですが、結論から言うと完全に区別はできなさそうです。
Actions タブの UI 上は区別できるのですが(下記画像の×がタイムアウト、!が手動キャンセル)、フィルタで Status: timed out を指定しても何も引っかからないので公式対応待ちです。
それでもなんとなく区別する方法を以下に記載しておきます。
ワークフロー
.github/workflows/timeout.yml
name: Timeout
on:
push:
paths:
- .github/workflows/timeout.yml
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-20.04
timeout-minutes: 1
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
steps:
- run: sleep 60
- run: |
timeout_seconds=$(gh workflow view "$GITHUB_WORKFLOW" --yaml \
| yq '.jobs.build.timeout-minutes * 60')
created_at=$(gh run view $GITHUB_RUN_ID --json createdAt,updatedAt \
--jq '.createdAt | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime')
now=$(date '+%s')
if ((now > created_at + timeout_seconds)); then
echo 'timed out'
fi
if: cancelled()
ワークフローの設定からタイムアウトの時間を取得して開始時刻と現在時刻の差から実行時間を計算しています。
上のコードに残骸が残っていますが updatedAt
ではうまく判定できませんでした。
ただし中断処理にそこそこ時間がかかるようで完全には判定できません。
タイムアウト直前に手動キャンセルするとタイムアウトとして判定されてしまいます。
実行中でなければアノテーションからも判断可能
実行が終わった後でなら以下のように情報が取得できます。
$ gh run view $GITHUB_RUN_ID
X main Self workflow · 1886051801
Triggered via push about 2 minutes ago
JOBS
X build in 1m6s (ID 5300127467)
ANNOTATIONS
X The job running on runner Hosted Agent has exceeded the maximum execution time of 1 minute.
build: .github#1
X The operation was canceled.
build: .github#1
To see what failed, try: gh run view 1886051801 --log-failed
View this run on GitHub: https://github.com/SnowCait/actions-sandbox/actions/runs/1886051801
全体の YAML は省略しますがこういう形で判定できると思います。
実行中にアノテーションは取得できなかったので別ワークフローで判定する場合にのみ使用可能です。
タイムアウト
if gh run view $GITHUB_RUN_ID | grep 'has exceeded the maximum execution time of'; then
echo 'timed out'
fi
手動キャンセル以外
if ! gh run view $GITHUB_RUN_ID | grep 'The run was canceled by'; then
echo 'timed out'
fi
API をたどることもできます。
> gh api -X GET repos/SnowCait/actions-sandbox/actions/runs/1885921685 --jq '.check_suite_url'
https://api.github.com/repos/SnowCait/actions-sandbox/check-suites/5412681253
> gh api -X GET repos/SnowCait/actions-sandbox/check-suites/5412681253 --jq '.check_runs_url'
https://api.github.com/repos/SnowCait/actions-sandbox/check-suites/5412681253/check-runs
> gh api -X GET repos/SnowCait/actions-sandbox/check-suites/5412681253/check-runs --jq '.check_runs[].output.annotations_url'
https://api.github.com/repos/SnowCait/actions-sandbox/check-runs/5299800073/annotations
> gh api -X GET repos/SnowCait/actions-sandbox/check-runs/5299800073/annotations --jq '.[].message'
The run was canceled by @SnowCait.
The operation was canceled.
ただしここの文言も将来的に変更される可能性が高いので完全とは言えません。
実際 canceled
を cancelled
に統一する PR があります。
Discussion