@octokit/rest でコミット / ブランチの作成 / PR の作成をやる
Yuji Matsumoto / January 21 2021
普段は IDE 経由で mdx ファイルを GitHub 上にコミットして、ブログ記事を作成している。
PC を開けない状態でも mdx ファイルを作成できたら便利では考え、@octokit/rest
を使って script を書いてみたので、やったことを書く。
@octokit/rest とは
https://github.com/octokit/rest.js/
- GitHub 公式の Rest API Client
- 他にも GraphQL 用の client がある
Access Token を GitHub 上で発行する
https://github.com/settings/tokens/new にアクセスして、octokit に渡す token を作成する。今回書く script では public repository への read/write があれば良いので、repo
scope の中の public_repo
にチェックをつける。
Generate token
ボタンを押すと、新しい token が生成され、value が表示されるので、どこかに保存しておく。
今回の script では .env
上で GITHUB_TOKEN
という環境変数を定義し、process.env.GITHUB_TOKEN
のような形で利用する。
token の scope については公式ドキュメント を参照
PR を作成する script を書く
octokit の instance を定義する
まずは Octokit の instance を定義する。先程作成した token はauth
key から Octokit に渡す。
import { Octokit } from '@octokit/rest';
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
});
新しいブランチを作成する
次に、mdx ファイルの追加コミットを積むためのブランチを作成する。 octokit.git.getRef
でベースとなるブランチの sha を取得し、 octokit.git.createRef
で新しいブランチを作成する。
// base ブランチの情報をfetch する
const baseBranchRef = await octokit.git.getRef({
owner: 'queq1890', // ブランチを作成したいリポジトリのowner のuser / org
repo: 'shuho', // リポジトリの名前
ref: `heads/main`, // `heads/<ブランチ名>` のように指定する
});
// 新しいブランチを作成する
const newBranchRef = await octokit.git.createRef({
owner: 'queq1890',
repo: 'shuho',
ref: `refs/heads/foo`, // `ref/heads/<ブランチ名>`のように指定する
sha: baseBranchRef.data.object.sha, // base ブランチのSHA
});
作成したブランチにコミットをする
次に、作成したブランチに mdx ファイルを追加するコミットを行う。全体の作業は大きく次の 4 つの工程に分かれる。
- コミットを行うブランチの最新のコミットの tree を fetch する
- fetch した tree を元に mdx ファイルを追加する tree を作成する
- 作成した tree を用いてコミットを作成する
- 作成したコミットをブランチに反映する
コミットを行うブランチの最新のコミットの tree を fetch する
新しい tree を作成するのに、現在の tree の情報が必要になるため、まずはコミットを行うブランチの最新のコミットの tree を fetch する。
const currentCommit = await octokit.git.getCommit({
owner,
repo,
commit_sha: newBranchRef.data.object.sha,
});
fetch した tree を元に mdx ファイルを追加する tree を作成する
次に、fetch した tree を元に mdx ファイルを追加する tree を作成する。base_tree
に元となる tree の SHA を渡し、tree
に追加・変更したいファイル郡の Object を Array で渡す。
const newTree = await octokit.git.createTree({
owner,
repo,
base_tree: currentCommit.data.tree.sha,
tree: [
{
path: `contents/new.mdx`, // 追加したいファイルのpath
mode: '100644', //100 はファイル 644は実行不可なファイルであるという意味
content: '任意のテキストを入れる', // 今回はstring
},
],
});
作成した tree を用いて commit を作成する
次に、作成した tree と紐付いた commit を作成する。parents
には現時点での最新の commit に SHA を指定する。
const newCommit = await octokit.git.createCommit({
owner,
repo,
message: 'マークダウンの追加',
tree: newTree.data.sha,
parents: [currentCommit.data.sha],
});
作成したコミットをブランチに反映する
作成したコミットの SHA をブランチの HEAD に反映する。
await octokit.git.updateRef({
owner,
repo,
ref: `heads/${newBranch}`,
sha: newCommit.data.sha,
});
PR を作成する
最後に、更新した branch から base となる branch に向かってプルリクエストを作成する。
await octokit.pulls.create({
owner,
repo,
head: newBranch,
base: baseBranch,
title,
body,
});
今回書いた script の gist はこちら
参考
Tree Ref といった git の概念がそもそもよく分かっていなかったので、↓ の記事が参考になった。