⚓
GitHubのPR file changesの中身をmarkdownのcode形式で抽出するコマンドを作った
GitHubのPR file changesの中身をmarkdownのcode形式で抽出するコマンドを作った
まあこんなことしなくても取得する方法ある気もしますが、作ってみました。
これは何か
ChatGPTやClaudeにコードのdiffを投げて、解説してもらいたいケースが多く、リポジトリとPR番号を指定したら、diffを出力してそれをコピペで生成AIにぶん投げるためのコマンド。
ほぼすべてClaudeに実装させたので、実装時間15分ぐらいです。
実装
main.go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"github.com/spf13/cobra"
)
type FileChange struct {
Filename string `json:"filename"`
Patch string `json:"patch"`
}
var (
prNumber string
repoOwner string
repoName string
)
var rootCmd = &cobra.Command{
Use: "ext_pr_diff",
Short: "A tool to fetch and display GitHub PR diffs",
Long: `This tool fetches the diff for a specified GitHub Pull Request and displays it in a markdown-friendly format.`,
Run: func(cmd *cobra.Command, args []string) {
fetchAndDisplayDiff()
},
}
func init() {
rootCmd.Flags().StringVarP(&prNumber, "pr", "p", "", "Pull Request number (required)")
rootCmd.Flags().StringVarP(&repoOwner, "owner", "o", "", "Repository owner (required)")
rootCmd.Flags().StringVarP(&repoName, "repo", "r", "", "Repository name (required)")
rootCmd.MarkFlagRequired("pr")
rootCmd.MarkFlagRequired("owner")
rootCmd.MarkFlagRequired("repo")
}
func main() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func fetchAndDisplayDiff() {
// auth token is needed.
cmd := exec.Command("gh", "auth", "token")
tokenBytes, err := cmd.Output()
if err != nil {
log.Fatalf("Error getting GitHub token: %v", err)
}
token := string(tokenBytes[:len(tokenBytes)-1]) // 改行を削除
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/pulls/%s/files", repoOwner, repoName, prNumber)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Fatalf("Error creating request: %v", err)
}
req.Header.Set("Authorization", "token "+token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("Error sending request: %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Error reading response: %v", err)
}
var files []FileChange
err = json.Unmarshal(body, &files)
if err != nil {
log.Fatalf("Error parsing JSON: %v", err)
}
for _, file := range files {
fmt.Printf("```diff\n")
fmt.Printf("# %s\n", file.Filename)
fmt.Printf("%s\n", file.Patch)
fmt.Printf("```\n\n")
}
}
Claudeによる上記実装の解説
このコードは、GitHub のプルリクエスト(PR)の差分を取得し、マークダウン形式で表示するGoのコマンドラインツールです。主な機能は以下の通りです:
-
コマンドライン引数の処理:
-
cobra
ライブラリを使用して、PRナンバー、リポジトリ所有者、リポジトリ名を必須の引数として受け取ります。
-
-
GitHub認証:
-
gh
コマンドを使用してGitHubの認証トークンを取得します。
-
-
GitHub APIへのリクエスト:
- 指定されたPR、リポジトリ所有者、リポジトリ名を使用してGitHub APIのエンドポイントを構築します。
- 取得した認証トークンを使用してAPIリクエストを行います。
-
レスポンスの処理:
- APIレスポンスをJSONとしてパースし、各ファイルの変更内容を取得します。
-
差分の表示:
- 各ファイルの変更内容をマークダウンのコードブロック形式で出力します。
- ファイル名とパッチ(変更内容)を表示します。
このツールを使用することで、指定したGitHubのプルリクエストの差分を簡単に取得し、マークダウン形式で表示できます。これは、PRのレビューや変更内容の確認に役立ちます。
コードの説明や詳細な解説が必要な場合は、お知らせください。
Example
こういうノリで活用できます。
まとめ
結論、Claude3.5 Sonnetは最高です。
Discussion