概要
GitHub REST APIを使用して簡単にGitHub ActionsのコミットにVerifiedマークを付ける方法になります。

❌️ 書かれていないこと
- CLIのgitコマンドを使用してVerified Commitを作成する方法
- GitHub REST APIでコミットの作成者やコミッター情報を変更しつつVerified Commitを作成する方法
前提情報
GitHub Docsに記載されているのですが、ボットによる署名はCommit APIでカスタム署名情報が含まれていなければ署名されます。
この仕組みを使用すれば比較的簡単にVerified Commitにすることができます!
ただし、GitHub REST APIでコミットを作成する際には少しGitの内部構造を知っていないと難しいところがあります。
自分もこの辺りは詳しくなかったので下記の資料を見てある程度理解しながら進めました。
実現方法
REST APIでの流れと、go-githubライブラリを使用した際の参考実装をそれぞれ記載しておきます。
また、各APIを実行できる権限があるトークンを使用して実行しないといけないので注意してください。
REST APIの流れ
- GET /repos/{owner}/{repo}/git/ref/{ref}でコミット先のrefを取得する
- GET /repos/{owner}/{repo}/commits/{ref}で親コミットを取得する
- POST /repos/{owner}/{repo}/git/treesでツリーを作成する
-
POST /repos/{owner}/{repo}/git/commitsで新しいコミットを作成する
- このときに
author
とcommitter
を指定しないことで署名を自動的につけることができます
- このときに
- PATCH /repos/{owner}/{repo}/git/refs/{ref}でコミット先にrefを更新する
go-github
での参考実装
client
の初期化は省いていますが、下記の流れでVerified Commitを作成することができます。
package main
import (
"log"
"github.com/google/go-github/v71/github"
)
func main() {
// TODO: clientは初期化しておく
client := github.NewClient(tc)
// リポジトリ情報
owner := "owner"
repo := "repository"
branch := "main"
// 1. コミット先のrefを取得
ref, _, err := client.Git.GetRef(ctx, owner, repo, "refs/heads/"+branch)
if err != nil {
log.Fatalf("Failed to get branch reference: %v", err)
}
// 2. 親のコミットを取得
parentCommit, _, err := client.Git.GetCommit(ctx, owner, repo, *ref.Object.SHA)
if err != nil {
log.Fatalf("Failed to get parent commit: %v", err)
}
// 3. ツリーを作成する
treeEntries := []*github.TreeEntry{
{Path: github.Ptr("new.txt"), Type: github.Ptr("blob"), Content: github.Ptr("new content"), Mode: github.Ptr("100644")},
}
tree, _, err := client.Git.CreateTree(ctx, owner, repo, *parentCommit.SHA, treeEntries)
if err != nil {
log.Fatalf("Failed to create tree: %v", err)
}
// 4. 新しいコミットを作成
// NOTE: このときにAuthorとCommiterの設定を行わない
commit := &github.Commit{
Message: github.Ptr("new file"),
Parents: []*github.Commit{parentCommit},
Tree: tree,
}
newCommit, _, err := client.Git.CreateCommit(ctx, owner, repo, commit, nil)
if err != nil {
log.Fatalf("Failed to create commit: %v", err)
}
// 5. コミット先のrefを更新
ref.Object.SHA = newCommit.SHA
_, _, err = client.Git.UpdateRef(ctx, owner, repo, ref, false)
if err != nil {
log.Fatalf("Failed to update new branch reference: %v", err)
}
}