Lento con forza

大学生気分のIT系エンジニアが色々書いてく何か。ブログ名決めました。

GitHub ActionsのCustom Actionからリポジトリ内のファイルにアクセスする

最近GitHub Actionsを便利に使うためのCustom Actionを作っていました。

kouki.hatenadiary.com

このActionに設定をリポジトリ内のファイルから取得する機能を追加したくなったんですが、この機能のためだけにcheckoutするのもなぁ、と悩んでいました。

具体的には、このPRの実装に必要でした。リリース用Issueの先頭に固定のテキスト(リリースフローなどを想定しています)を追加する機能です。

github.com

Custom Actionからリポジトリ内のファイルを参照する

GitHub ActionsではそのActionが発火するリポジトリに関する操作ができるGitHubのトークンが簡単に取得できます。APIから固定のファイルを取得することができれば、リポジトリ全体をcheckoutしてくる必要がありません。

GitHubはAPIが豊富なので、もちろんこのAPIも用意されていました。

Get repository content API

パスを指定してファイルを取得できます。パスがファイルの場合は*1 contentフィールドにエンコードされたファイルの内容が入っています。また、encodingフィールドにエンコード方式が入っています。

サンプルレスポンスには、エンコード方式にbase64とあり、実際にAPIを叩いてみてもBase64でエンコードされた内容が入っているようなのですが、ドキュメントにはエンコーディングについての説明が見当たりませんでした。

Stackoverflowに Base64 encoded content と昔は書かれていたような記録を見つけたので、これを信じてBase64固定で実装しました。

stackoverflow.com

このAPIでは指定したパスにあるファイル形式により挙動が変わるので少しややこしいのですが、ファイルを取得したいだけなら

const content = await octokit.rest.repos.getContent({
  owner: owner,
  repo: repo,
  path: path,
});
if ("content" in content.data) {
  const file_content = Buffer.from(content.data["content"]).toString("base64"); 
  console.log(file_content)
}

簡単ですね

ということでPRができました。PRではファイル以外のパターンでのエラー処理なども追加しています。

github.com

*1:ファイル以外にもディレクトリやサブモジュールの場合もあり、それぞれ返ってくるレスポンスが違います。