Github Actionsで定期実行バッチを作る【404チェッカー】

この記事は[弥生 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/yayoi)の7日目エントリーです。

## やりたいこと
- 404チェックを毎日実行したい
- でも面倒くさいのはイヤ :cry:
  （AWS Lambdaで書いて、EventBridgeで定期実行して、SNSで通知…とかは重い）

→ Github Actionsでペライチでサクッと書けます！という記事です
　（たぶん色々なバッチに応用できると思います）

## 結論
「毎日9時に404チェック実行」を行うコードです。
こちらのコードをGithubのリポジトリに突っ込むと動きます。（非公開でもOK）

```/.github/workflows/404check.yml
name: 404check

on: 
  schedule:
    - cron: "0 0 * * *"

env:
  TARGET_URL: www.altoa.jp

jobs:
  check:
    runs-on: ubuntu-latest

    container:
      image: python:3.11  
      # ここたぶんいらないなって記事書いてて思いましたが
      # 消して動作確認してないので残しておきます

    steps: 
      - name: wget-spider
        id: wget-spider
        continue-on-error: true
        run: |
          # wgetで404チェック
          wget \
             --spider \
             --recursive \
             --level=2 \
             --no-verbose \
             --execute robots=off \
             --span-hosts \
             --random-wait \
             $TARGET_URL
```

これでリンク切れが見つかるとwgetがエラーを吐くので、
Workflowが失敗になり、Githubに登録したアドレスにメールが届くようになります。

## 解説
### 1. cronで定期実行できる
Github Actionsでは、`on: push`など、
`push`時や`merge`時に実行されるCI/CD的な印象が強いですが、実はスケジュール起動もできます。
```yml
on: 
  schedule:
    - cron: "0 0 * * *"
```
「毎日9時に実行する」というコードです。
（タイムゾーンはUTCなので0が9時）

`"0 0 * * *"`は、
`0分 0時 毎日 毎月　毎曜日`という意味になります。

### 2. wget で404チェック
実はLinux標準コマンドの`wget`で404をチェックできます。
```yml
        run: |
          # wgetで404チェック
          wget \
             --spider \
             --recursive \
             --level=2 \
             --no-verbose \
             --execute robots=off \
             --span-hosts \
             --random-wait \
             $TARGET_URL
```

| オプション                | 説明                                                         |
| ------------------------- | ------------------------------------------------------------ |
| --spider                  | スパイダーモード。wgetの結果をダウンロードしない。           |
| --recursive               | 再帰的に巡回                                                 |
| --level=2                 | 2階層の深さまで巡回。内部リンクなどを全部見たいときは`inf`にすると便利です |
| --no-verbose              | 簡易ログ表示                                                 |
| --execute robots=off      | robots.txtを無視する                                         |
| --span-hosts              | 外部リンクもチェックしたいときは入れる。levelをinfにするととんでもないことになるのでやめましょう |
| --random-wait             | 0~2秒間のランダム待機                                          |

外部リンクのリンク切れが一番確認したいところなので、`--span-hosts`は必須です。
ただし、サーバーに負荷をかけないよう、`--random-wait`や`level`の設定は忘れないようにしましょう。

なお、wgetはmacOSでも実行できるので、
ローカルサーバーにも404チェックを簡単に行なえます。

…
これで毎日404チェックを行ってくれるバッチが書けました！✨🍰✨

## ただし通知は自分にしか来ない :sob:
Github Actionsの通知は、次のいずれかの1人にしか届きません。（[参考](https://docs.github.com/ja/actions/monitoring-and-troubleshooting-workflows/notifications-for-workflow-runs)）

- `on: push`などのイベント系
    - そのイベントを起こした人に通知
- `on: schedule`
    - 最後にcron文を更新した人に通知

このため、自分が開発担当でなくなった場合にメンテできなくなりますので、このままだと丁寧な仕事とは言えません。
楽したくてGithub Actionsにしようと思ったら…逆に面倒な運用になりそうです:cry:

## Github Actionsでできる簡単な通知
そこで、Slack通知が簡単に実装できておすすめです。
（GithubのTeam全員にメール通知とかしてくれると一番いいんですが…そんな機能はないっぽい）

最後に以下の一文を差し込むだけです。
```yml
      - name: Slack Notification
        if: ${{ failure() }}  # workflowが失敗したときに実行
        uses: rtCamp/action-slack-notify@v2
        env:
          # 対象
          SLACK_CHANNEL: general  
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}  # 事前に対象のwebhookのURLを取得してsecretsに入れておく

          # 任意のテキスト、色、アイコンを設定
          SLACK_USERNAME: 404checker
          SLACK_TITLE: 404 Check Failure www.altoa.jp
          SLACK_COLOR: danger
          SLACK_ICON: https://www.altoa.jp/img/favicon.ico
```
こちらのactionを使用：

https://github.com/rtCamp/action-slack-notify


これで失敗時のみ、slack通知が届くようになりました。やったー！

## おわり✨🍰✨
アドベントカレンダー書くのずっと後回しにしてたら前日になってしまい、
当初の予定と全く違う内容をサクッと書いたわけでは決してございません。
でも結構便利だと思うので許してください。

アルトア株式会社 システム開発部
一ノ関（WEBとセキュリティ、最近の趣味はValorant）の[弥生 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/yayoi)の7日目でした！