📝

GitHub Actions による Issue 自動生成で、TIL を続けた実践記

2024/12/18に公開

導入

この記事は、ourly Advent Calendar 2024🎄 18日目の記事です。
昨日は神本さん『One Teamで挑む!機能×運用による価値提供術』を書いてくれました。

https://adventar.org/calendars/10628

以下は TIL を自動で蓄積していく仕組みや、その過程で得た気づきをまとめたものです。
環境や今後の改善点、1年以上継続してきた感想などを紹介します。

TIL とは

TIL (Today I Learned) は「日々得た知識や気づき」を記録する文化・習慣で、GitHub 上に til という名前のリポジトリを立てて Markdown 形式などのファイルを commit していくのが一時期流行ったそうです。

しかし毎回ファイルを commit するのは意外と手間がかかります。
そこで今回は GitHub Issue に着目し、より手軽にアウトプットできる環境を作ってみました。

なぜ GitHub Issue を採用したか

まず手動でファイルを増やして commit, push するといった手間を省けることです。

さらに普段業務で GitHub を使っているため Issue のインターフェースは見慣れた環境であり、新たなツールを覚える必要がないことも大きなメリットでした。

また、これは実際にやってみて感じたことですが Issue は GitHub 上で検索できるほか、ラベルで管理することも可能なため、後から必要な情報を振り返ったり整理するのを簡単に行えました。

要件

環境を用意するにあたり以下の要件を満たすことを目指しました。

  • Issue が平日の始業時間前に自動で作成されること
  • 前回の Issue が自動でクローズされること
  • タイトルはYYYY-MM-DD 形式にすること
  • TIL 以外の Issue もあったため、ラベルで振り分けられること

オレオレ TIL 環境の紹介

以下で提示するコードではこんな感じの Issue が毎日作成されます。

自動で作成された実際の Issue ページのキャプチャ。「2024-12-18」というタイトルで、今日やること、今日のハイライト、検索用ワードという3つの見出しがある。見出しの下にはそれぞれ空欄のリストや Markdown 形式のチェックボックスが用意されている。

公式の例を参考に、GitHub CLIを使用しました。
8割くらい公式と同じコードにはなりますが、個人的につまづいたポイントを元にいくつか解説を入れていきます。

ワークフローのコード
name: Create weekdays note
on:
  schedule:
    - cron: 0 0 * * 1-5
jobs:
  weekdays_note:
    name: Create weekdays note
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - name: Set current datetime as env variable
        env:
          TZ: Asia/Tokyo
        run: echo "CURRENT_DATETIME=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
      - name: Create weekdays note
        run: |
          if [[ $CLOSE_PREVIOUS == true ]]; then
            previous_issue_number=$(gh issue list \
              --label "$LABELS" \
              --json number \
              --jq '.[0].number')
            if [[ -n $previous_issue_number ]]; then
              gh issue close "$previous_issue_number"
              gh issue unpin "$previous_issue_number"
            fi
          fi
          new_issue_url=$(gh issue create \
            --title "$TITLE" \
            --assignee "$ASSIGNEES" \
            --label "$LABELS" \
            --body "$BODY")
          if [[ $PINNED == true ]]; then
            gh issue pin "$new_issue_url"
          fi
        env:
          GH_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
          GH_REPO: ${{ github.repository }}
          TITLE: ${{ env.CURRENT_DATETIME }}
          ASSIGNEES: [自身の GitHub ユーザID]
          LABELS: TIL
          BODY: |
            ## 今日やること
            - [ ] 
            ## 今日のハイライト
            - 
            ## 検索用ワード
            - 
          PINNED: false
          CLOSE_PREVIOUS: true

Secret names は GITHUB_ から始まってはいけない

GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Actions の実行には token の発行が必要です。
コードに合わせて GITHUB_TOKEN という名前で Actions secrets を追加したところ、以下のようなエラーが。

Failed to add secret. Secret names must not start with GITHUB_.

GITHUB_ で始まってはいけないとのことで、PERSONAL_ACCESS_TOKEN に変更して解決しました。

GH_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}

GitHub Actions の schedule は遅延する可能性がある

on:
  schedule:
    - cron: 55 0 * * 1-5

cron 構文を完全理解し、始業時間の AM10:00 に合わせ、AM9:55 相当の cron: 55 0 * * 1-5 を指定したところ、なんと始業時間過ぎの AM11:00 過ぎに作成されました。

これが完全理解の伏線回収か、、、と思い原因を調べたところ、遅延する可能性があるとの記載が公式にありました。

GitHub Actions のワークフローの実行によって高い負荷がかかっている間、schedule イベントが遅延する可能性があります。 高負荷の時間帯には、毎時の開始時点が含まれます。 負荷が十分に高い場合、キューに登録されたジョブの一部が削除される可能性があります。 遅延の可能性を減らすために、Ⅰ時間の中の別の時間帯に実行されるようワークフローをスケジューリングしてください。
https://docs.github.com/ja/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule

始業時間前であればいつでも良かったのと、タイムゾーンが指定できない関係で、以下に落ち着きました。

on:
  schedule:
    - cron: 0 0 * * 1-5

日によって30分程度の幅はありますが、これで今は始業時間前には作成できているのでよしとしました。

タイトルを日付にする

こちらは schedule とは違い、タイムゾーンが指定できました。

    steps:
      - name: Set current datetime as env variable
        env:
          TZ: Asia/Tokyo
        run: echo "CURRENT_DATETIME=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
    ...
        env:
          ...
          TITLE: ${{ env.CURRENT_DATETIME }}

前回の issue をクローズする

      - name: Create weekdays note
        run: |
          if [[ $CLOSE_PREVIOUS == true ]]; then
            previous_issue_number=$(gh issue list \
              --label "$LABELS" \
              --json number \
              --jq '.[0].number')
            if [[ -n $previous_issue_number ]]; then
              gh issue close "$previous_issue_number"
              gh issue unpin "$previous_issue_number"
            fi
          fi

前回 Issue 判別をラベルで行なっているため、専用のラベルである TIL を作成し、作成時にも自動で付与されるようにしました。
公式のコードを参考に、専用のラベルを作ることをおすすめします。

今後の改善点

今後は祝日の考慮とテンプレートの拡充を検討しています。

まず祝日の考慮については、現状では平日の祝日にも自動で作成されてしまうため、より厳密に判断ができるようにしたいと考えています。また、テンプレートに関しては、現状では簡素な形式で記述しているため、別ファイルに切り出して保守性を高めることを目指したいです。

改善できたらまた加筆しようと思います。

運用してみた感想

1年以上この仕組みを回してみた結果、様々なメリットに気づきました。たとえば、ちょっとしたアイデアや気づきを記録しておくことで、後日「あれなんだっけ?」となったときにも簡単に検索できます。また、思考を外部化することで頭のメモリが節約でき、新たな課題解決に専念することができるようになりました。

さらに、日々の小さな情報発信や思考整理が習慣化することで、自然とアウトプットの練習にもなります。アドベントカレンダーや発表、ブログ執筆など、ネタが必要なときにも過去の TIL が役立ちますし、ちょっとした考えごとや感情をアウトプットすることで、自分自身との対話が深まり、最終的には自分が本当に求めていることや優先すべきことが明確になります。また、その日のコンディションを言語化することで、パフォーマンスを意識した自己管理にもつながります。

総じて「TIL はいいぞ」です。積み重ねることで小さな学びが自然と体系化され、必要な時にすぐ参照できる「知のアーカイブ」ができあがっている実感があります。

さいごに

毎日ほんの少しずつ記録を重ねていくことで、「今日学んだこと」のアーカイブは1年、2年と積み重なり、やがて後の自分を支える、心強い味方になってくれるはずです。

もし興味があれば、手軽に始められるこの方法を試してみてください。
TIL を習慣化することで、思考や情報を外部化し、日々の前進を後押しするような下地が少しずつ整っていくと思います。

ourly tech blog

Discussion