なんでもノート

なんでも書くノートみたいなブログ

GitHub ActionsからGitHubへpushできないエラー

GitHub Actionsで以下のエラーが出た。

Push the commit or tag
  /usr/bin/git push origin master
  remote: Permission to azujuuuuuun/azujuuuuuun.github.io.git denied to github-actions[bot].
  fatal: unable to access 'https://github.com/azujuuuuuun/azujuuuuuun.github.io.git/': The requested URL returned error: 403
  Error: Action failed with "The process '/usr/bin/git' failed with exit code 128"

権限がなくGitHub Actionsからpushが拒否されたよう。直前のPRで権限を変更したので心当たりがあった。

https://github.com/azujuuuuuun/azujuuuuuun.github.io/blob/d38acc9466d01ec004d861427e285597055db0a4/.github/workflows/continuous-delivery-workflow.yml#L13-L15

    permissions:
      contents: "read"
      id-token: "write"

このpermissionsはgoogle-github-actions/authを元に設定した。Assigning permissions to jobs - GitHub Docsによると

これらのスコープのいずれかのアクセスを指定した場合、指定されたなかったものはすべてnoneに設定されます。

だそうだ。つまり、このpermissionsの設定によってどれかのスコープにnoneが設定されて書き込み権限がなくなったか、contents: "read" によって書き込み権限がなくなったかのどちらかが原因だとわかった。

スコープと対応するアクセス権限はPermissions required for GitHub Apps - GitHub Docsにあった。Git操作のアクセス権はcontentsスコープだったので contents: "write" に変更したら解決した。

GitHub ActionsからGoogle Cloudに認証する

GitHub Pagesにはてなブログの最新記事を表示する - なんでもノートGitHub ActionsからGCSへの認証に困ったと書いた。詳細をこの記事に書く。

前回の記事ではGCSにアップロードしたJSONを取得し、そのJSONに入っているブログの最新記事を表示した。JSON取得にCloud StorageのNode.js Clientライブラリを利用した。

サービスアカウントを利用した認証

Cloud Storage client libraries  |  Google Cloudの順に沿ってセットアップを進めた。

  1. サービスアカウントを作成
  2. サービスアカウントにGCSの読み取りロールを付与
  3. サービスアカウントキーを作成し、JSONファイルをダウンロード
  4. 環境変数 GOOGLE_APPLICATION_CREDENTIALS に3でダウンロードしたクレデンシャルファイルのパスを設定

これでライブラリが環境変数に設定したパスからクレデンシャルファイルを読み込み、よしなにGoogle Cloudと認証を行ってくれるようになった。ローカルで認証できるようになったが、GitHub Actions上で認証するにはどうしたらよいか。Next.jsのgetStaticPropsでStatic Site Generationをしているので、GitHub Actionsでのビルド時にJSON取得、認証が行われる。GitHubGOOGLE_APPLICATION_CREDENTIALS で検索したら、以下のコードがあった(一部省略)。

https://github.com/Gradder-Official/gradder_main/blob/a00b4030e20119ab91dc73df33361f030e21708f/.github/workflows/deploy.yml#L23-L30

      env: 
        GOOGLE_APPLICATION_CREDENTIALS: key.json
      run: |
        echo -n '${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}' > key.json

GitHub Actionsのシークレットにクレデンシャルファイルを保存しておいて、ジョブの実行時にファイルに書き出すというものだった。自分も考えはしたが、間違えてファイルの中身がログに出力されないか不安があったのでもう少し調べた。

Workload Identity 連携

調べたところ以下のブログを見つけた。

cloud.google.com

  • サービスアカウントキーより認証情報の有効期限を短くでき、不正利用時間が短くなる
  • サービスアカウントキーより管理コストが小さい
  • サービスアカウントより詳細な権限管理ができる

というものだった。また、authというGitHub Actionで簡単に認証ができそうだった。Workload Identity連携の方がサービスアカウントより総合的に良さそうだったので利用することにした。

Configuring workload identity federation  |  IAM Documentation  |  Google CloudObtaining short-lived credentials with identity federation  |  IAM Documentation  |  Google Cloudに沿って、以下の設定をした。

また、GitHub Actionsのワークフローにauth GitHub Actionのstepを追加した。必須パラメーターの workload_identity_providerservice_account を設定した。create_credentials_file パラメーターがデフォルト true で設定されていて、Clientライブラリで利用するクレデンシャルファイルを生成してくれる。また、cleanup_credentials パラメーターがデフォルト true で設定されていて、ジョブ終了時にクレデンシャルファイルを削除してくれる。

これでGitHub ActionsからGoogle Cloudに認証することができるようになった。

感想

どうするのが良いかわからなかったので困ったが、無事に解決できてよかった。Workload Identity連携はまだ理解がふわふわしているので醸成したい。

GitHub Pagesにはてなブログの最新記事を表示する

https://azujuuuuuun.github.ioにブログの最新記事を出した。

実装方法

  1. はてなブログの更新フィードを取得する
    • Atomフォーマットを取得する
  2. 1の更新フィードをJSONに変換する
    • XMLより扱いに慣れているのでJSONに変換した
  3. 2のJSONGoogle Cloud Storage(以下、GCS)にアップロードする
    • 無料枠があるのでGCSを選択した
  4. Next.jsのgetStaticPropsでGCSからJSONを取得する

当初の目的はブログを更新したらazujuuuuuun.github.ioを更新することだった。それを踏まえた実装方法になっている。今後、以下の日時の定期実行処理を別コンポーネントに実装する。

  1. GCSから更新フィードJSONを取得する
  2. はてなブログの更新フィードAtomを取得する
  3. 1と2のJSONAtomの最終更新日時が同じ場合は処理を終了する
  4. 異なる場合
    1. 2のAtomからJSONを生成し、GCSにアップロードする
    2. GitHub Actionsのrepository dispatchを利用してGitHub Pagesのデプロイ処理を走らせる

困ったこと

GCSのバケット

https://cloud.google.com/storage/docs/naming-buckets

バケット名は一般公開されます。 ユーザー ID、メールアドレス、プロジェクト名、プロジェクト番号、個人を特定可能な情報(PII)をバケット名に使用しないでください。バケットの存在を誰でも調べることができます。

この考慮事項に悩まされた。良い命名規則が未だにわからない。当たり障りのないバケット名をつけた。

Google Cloudはリソースに名前とIDを求められるのでその度に悩んでいる。

GCSの無料枠を超えないか

GCSの無料枠は2022/09/03現在以下の条件。

  • 5 GB 月の Regional Storage(米国リージョンのみ)
  • 5,000 回のクラス A オペレーション(1 か月あたり)
  • 50,000 回のクラス B オペレーション(1 か月あたり)
  • 1 GB の北米から全リージョン宛ての下りネットワーク(1 か月あたり、中国とオーストラリアを除く)

https://cloud.google.com/free/docs/free-cloud-features?hl=ja

クラスAオペレーションとクラスBオペレーションはhttps://cloud.google.com/storage/pricing?hl=jaの説明を参照。更新系やバケット内のオブジェクト一覧取得などのやや重い処理がクラスA、比較的軽めの参照系がクラスB。

ローカルで開発中にビルドの度にファイル取得が走るので無料枠を超えないか心配だった。とりあえず、開発中は環境変数でローカルのファイルを参照するようにした。ただ、開発中のソースコードと本番のソースコードが異なるので、GCS互換のオブジェクトストレージをローカルに立てられないか検討中。

GitHub ActionsからGCSへの認証方法

長くなりそうなので別の記事に書く。

感想

Google Cloudを初めて触るので読むドキュメントが多い。実装よりGoogle Cloudの設定、Google Cloudの設定よりリソースの命名に時間を使ってる気がする。

VSCodeのデバッガーでTypeScriptのスクリプトをデバッグをする

恥ずかしながらこれまでJavaScriptの開発にデバッガーを使ってこなかった。ひたすらconsole.logを仕込みデバッグしていた。VSCodeでTypeScriptのデバッグをする方法を調べた。

とりあえずデバッガーを起動できるようになった設定ファイルはこちら

  • type
    • デバッガーの種類
    • node は組み込みのNode Debugger
  • request
    • 起動設定のリクエストの種類
  • name
    • 名前
  • skipFiles
    • (雑な説明)デバッグ中にスキップするファイル一覧
    • <node_internals> はNode.jsの組み込みのコアモジュール
  • program
    • デバッガー起動時に実行するもの
  • preLaunchTask
    • デバッグセッションを始める前に実行するタスク
    • TypeScriptをJavaScriptにトランスパイルするためにnpm Scriptのbuildを指定している
  • outFiles
  • envFile
    • .envファイルのパス
    • ローカル環境ではdotenv環境変数を読み込んでいるので

画像の左のペインの「Launch Program」(launch.jsonのnameに設定した値)をクリックすると、プログラムとデバッガーが実行される。元のTSファイルにブレークポイントを設定すれば、そこで処理が止まり、ローカル変数やグローバル変数の値を見ることができる。

今回はTypeScriptのシンプルなスクリプトデバッグをした。デバッガーを起動できるようになったので一歩前進。より実践的にWebブラウザで動くJavaScriptアプリケーションサーバーをデバッグできるようにしていきたい。

新型コロナウイルス新規感染者数をSlackに通知する

いつからかコロナの感染者数の推移を見なくなった。メディアの公式LINEから速報で来なくなったし、自分から調べる回数も減った。7月から新型コロナウイルス新規感染者数が増えている。早く落ち着いてほしいと願っている。在宅勤務でテレビでもネットでもニュースを見ていないので世の中の情報がなかなか入ってこない。積極的に情報を取りに行くのはなかなかハードルが高いが、受動的に受け取ることはできる。コロナの感染者数をSlackに通知できないかと考えた。

やりたいこと

  • 毎日1回東京都の新型コロナウィルス感染者数をSlackに通知する

実現方法

ツール・データ

フロー

  1. データを取得する
  2. 最新のデータを取り出す
  3. Slackに通知する

技術スタック

作ったもの

リポジトリhttps://github.com/azujuuuuuun/newly-cases-slack-notification

8/17・18分の通知

終わりに

これを作る前に「LINE新型コロナ情報」というLINE公式アカウントを友だち追加していた。今朝、国内感染者数の推移と都道府県別感染状況が来ていた。これで十分だったのでSlack通知は止めることにした。

linecorp.com

依存パッケージを更新することなくpackage.jsonとpackage-lock.jsonのversionを上げる

依存パッケージを更新することなくpackage.jsonとpackage-lock.jsonのversionを上げる方法をまとめる。

$ npm version patch

このコマンドでセマンティックバージョニングのパッチバージョンを上げることができる。versionが 1.0.0 だった場合、1.0.1 になる。1.0.1 というメッセージでgitのコミットが作成され、v1.0.1 というgitのタグが作成される。マイナーバージョンを上げたい場合はpatchをminorに、メジャーバージョンを上げたい場合はpatchをmajorにすればよい。コミットメッセージを指定したい場合は -m もしくは --message オプションをつければよい。

$ npm version patch -m "Upgrade to %s"

%s は該当バージョンに置き換えられる。

gitのタグを打ちたくない場合は、以下のように --no-git-tag-version をつける。

$ npm --no-git-tag-version patch

もしくは npm config コマンドでgit-tag-versionをfalseに設定して、npm version コマンドを実行する。

$ npm config set git-tag-version false

$ npm version patch

いずれの場合もpackage.jsonファイルとpackage-lock.jsonファイルのversionは変更されるが、コミットとタグは作成されない。

参考リンク:https://docs.npmjs.com/cli/v8/commands/npm-version

GitHub ActionsでNotionの日記ページを毎日作成する

タイトルにある通り、1日1ページNotionに日記を書いている。「YYYY/MM/DD(ddd)」というタイトルをつけているのだが、この入力が地味にめんどくさかった。「きょう」→変換→ 「(」→「つき」→変換→「)」という手順で入力していた。Notion APIを使ってみた - なんでもノート でNotion APIの使い方がわかったので、このページ作成を自動化することにした。

要件

  • 毎日NotionのDiaryデータベースにページを自動で作成する
  • タイトルは「YYYY/MM/DD(ddd)」
  • ページが既に作成済みであれば作成しない
    • 自分が翌日分を手動で作成することもあるため

開発

定期実行に今回はGitHub Actionsを利用することにした。リポジトリこちら

やったこと

感想

  • 自動化便利
  • Notion APIは前回以上のことをしていないのでコメントなし
  • GitHub Actionsは環境ごとにシークレットを作成できて便利
  • ワークフローのファイル名とnameをどんな風につければいいかまだわかってない