JavaScriptを有効にしてください

[Hugo]自動投稿したい4(自動コミット)

 ·  ☕ 5 分で読めます

今回やること

  • 日付更新処理で行った変更をmainブランチに反映する
  • ストック数をslackに通知する

前提

  • ワークフロー用のファイルが作成されている
  • slackのIncoming Webhookが使用できる状態になっている
  • 変更内容が意図したものかはフロー中では確認しない

差分があるか確認する

git diffで差分を確認する。
差分があるときだけコミットするステップに進む。

以下のステップを追加する

1
2
3
4
      - name: Check diff
        continue-on-error: true
        id: diff
        run: git diff --exit-code

git diff

--exit-codeは差分があるときはステータスコード 1 で終了、ないときは 0 で終了する。

https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---exit-code

--quietを使用して標準出力なしにしても良いが、今回はログに内容が出た方が良いので使用しない。

continue-on-error

通常はステップが失敗すると、ジョブも失敗になって処理が終了する。
今回の場合だと差分があってステータスコード 1 で終了した場合、ステップが失敗したことになり、ジョブも失敗になる。
continue-on-error: trueを指定することでステップが失敗してもジョブを継続することができる。

https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepscontinue-on-error

ここの成功、失敗のステータスを後で使用したいので、idも指定しておく。

コミットする

差分がある場合のみ実行する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
      - name: Commit
        if: ${{ steps.diff.outcome == 'failure' }}
        env:
          TZ: 'Asia/Tokyo'
        run: |
          changed=`git diff --name-only`
          git config user.name github-actions[bot]
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git add $changed
          git commit -m "auto publish: $(echo $changed | grep -Po '(?<=posts/).*(?=\.md)')"
          git push origin main          

if

ステップを実行する条件を指定できる。
https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsif

stepsコンテキストの中に実行結果があるのでそれを使用して対応する。
https://docs.github.com/ja/actions/learn-github-actions/contexts#steps-context

プロパティはconclusionoutcomeがあるが、conclusionだと失敗した場合もsuccessになるので今回の用途に合わない。

※前のジョブが失敗した時は${{ failure() }}trueを返すのでそれでも対応できる。(後から気づいた)
https://docs.github.com/ja/actions/learn-github-actions/expressions#failure

TZ

ここでタイムゾーンを指定する。
指定しない場合はコミット日時が日本時間ではないので、hugo利用の際は不都合となるケースがある。
https://gohugo.io/getting-started/configuration/#enablegitinfo
gitの情報を参照して最終更新日を判断する機能があり、それが有効になっている場合にはタイムゾーンの違いにより投稿日と最終更新日の表示が意図したものと異なってしまう。
今回のケースだと、投稿日更新時に日本時間を指定しているので、合わせておかないと最終更新日の方が投稿日より前になる事象が発生する。

ユーザー設定

手動で行ったものと区別しやすくするため、botを設定する。

アドレスについては以下を参考にした。
https://github.com/orgs/community/discussions/26560#discussioncomment-3252340

grep

正規表現でファイルパスから拡張子を除いたファイル名を取得したかった。
grepの中で正規表現の「後読み」「先読み」を使用する時には-Pオプションを使用する必要がある。
ここでもmacとlinux環境の差があるようで当初-Pオプションが指定できなかった。

BSDの場合には-Pオプションに対応してないらしい。
https://teratail.com/questions/107898
sedの時もそうだったが、同じ名前だが別コマンドみたいなパターンはエラーでても気付きにくい。

❯ ggrep --version
-bash: ggrep: command not found

❯ brew install grep
Running `brew update --auto-update`...

省略

==> grep
All commands have been installed with the prefix "g".
If you need to use these commands with their normal names, you
can add a "gnubin" directory to your PATH from your bashrc like:
  PATH="/usr/local/opt/grep/libexec/gnubin:$PATH"

❯ ggrep --version
ggrep (GNU grep) 3.8
Packaged by Homebrew
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Haertel and others; see
<https://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.

これでggrepを使用することで-Pを使用した抽出が可能になった。
grepの使い方を検索したときにはGNUを前提とした情報が多く出てきている気がしたので、今後同じようなはまり方をしないようにインストール時に出ていた方法でプレフィックスなしで使用できるようにする。

パスを指定した後のgrep(ggrep入れる前がどうなってたかは残してなかった。。)

❯ grep --version
grep (BSD grep, GNU compatible) 2.6.0-FreeBSD

ストック数を通知する

hugo list futureで表示されるものが公開予定のものなので、その数をslackに通知する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
      - name: Check stocks
        id: stocks
        run: |
          count=`hugo list future | wc -l`
          echo "count=$count" >> $GITHUB_OUTPUT          

      - name: Stocks notification
        uses: slackapi/slack-github-action@v1.23.0
        with:
          payload: |
            {
              "username": "記事数お知らせbot",
              "icon_emoji": "👻",
              "text": "<@${{ secrets.TARGET_USER }}>\n記事ストック数:${{ steps.stocks.outputs.count }}"
            }            
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
          SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK

echo "count=$count" >> $GITHUB_OUTPUTのような感じにすると他のステップで${{ steps.stocks.outputs.count }}と値を取り出せる。
https://docs.github.com/ja/actions/learn-github-actions/contexts#example-usage-of-the-steps-context

slack通知についてはcurlでも良いが、actionが提供されているのでそれを使用する。
https://github.com/slackapi/slack-github-action

blocksを使用することで見た目を変えられるが、自分用なのでテキストだけで良い。

ドキュメント
https://api.slack.com/block-kit

ビルダーを使用すると見た目の確認や記述内容の確認が簡単にできる。
https://api.slack.com/tools/block-kit-builder

ローカルではact使用時にオプションとしてURL等を渡すと通知の確認ができる。

❯ act -s SLACK_WEBHOOK_URL={webhook_url} -s TARGET_USER={メンション対象のメンバーID}

本番環境ではリポジトリの設定画面でActions secretsを設定する。

その他

一旦ここまでで、自動公開処理は完成して公開可能なものがあれば定期的に公開されるようになった。
想定外のエラーで処理が止まったときはメールがくるので、エラー対応については運用し始めてから考える。
基本的には大丈夫なはずだが、日付更新処理の時点でおかしな変更がされてしまった時のことを考え、しばらくはアクションの実行履歴を目視で確認した方が良いかもしれない。

今後の課題

  • twitterで記事公開の投稿を自動化(zapier等のサービスを利用してできそう)
  • 定期以外に手動で作業する用に日付更新処理を.shファイルにして共通化する

書いた人
keee
Webエンジニア

目次