GitHubAPI チートシート

みなさんGithubはお世話になっていますよね？Githubの各種操作はghコマンドやGithubAPIで行うことができます！この記事ではGithubAPIについて紹介します．GitHub APIはGitHub上のリポジトリやユーザ情報などを柔軟に操作できる強力なAPIである. 本記事では, 代表的なエンドポイントの使い方を初心者にもわかりやすく解説する. まずはcurlでのリクエスト例を示し, それからGo言語で[github.com/google/go-github/v57/github](https://pkg.go.dev/github.com/google/go-github/v57/github)ライブラリを使った実装例を紹介する. 各エンドポイントごとにGoファイル(`example/SampleRepository`配下を想定)を作成しているので参考にしてほしい.

:::note info
**前提**
- GitHub APIを利用するには適切な認証が必要である(パーソナルアクセストークンなど)
- 本記事はAPIの利用方法を示す. セキュリティ的な観点やトークン管理については別途注意が必要
- APIを実行する際はAPIのRate Limitにも注意する
:::

# 他のチートシート
git/gh コマンド(gitコマンド以外にもgitの概念も書いてあります)

https://qiita.com/JavaLangRuntimeException/items/6b46551f56e0def76eba

> Githubの操作にはGithub API以外にもCUI操作のghコマンドがあります．ぜひご覧ください．

lazygit

https://qiita.com/JavaLangRuntimeException/items/42087d09728d5739d73d

Docker コマンド(dockerコマンド以外にもdockerの概念の記事へのリンクもあります)

https://qiita.com/JavaLangRuntimeException/items/21f7c7bf3d143f821697

ステータスコード

https://qiita.com/JavaLangRuntimeException/items/ab1bc7b976ed2dfad91c

TypeScript

https://qiita.com/JavaLangRuntimeException/items/5894391c08e0d8e28389

Go/Gorm

https://qiita.com/JavaLangRuntimeException/items/d388717fc1436bc3ec9d

testing/gomock

https://qiita.com/JavaLangRuntimeException/items/bf521190f6f4d79e59fb

Ruby/Ruby on Rails

https://qiita.com/JavaLangRuntimeException/items/42d935cf92c212f1c7ec

SQL

https://qiita.com/JavaLangRuntimeException/items/f038fbaccdd92fb0308a

Vim

https://qiita.com/JavaLangRuntimeException/items/0c68ab96ea198e0a7294

プルリクエスト・マークダウン記法チートシート

https://qiita.com/JavaLangRuntimeException/items/329eb92a47a07ff4dde8

ファイル操作コマンドチートシート

https://qiita.com/JavaLangRuntimeException/items/16f244606a73f7d106e4

VSCode Github Copilot拡張機能

https://qiita.com/JavaLangRuntimeException/items/be13dc3a346cf6e5ee44

OpenAI Assistants API

https://qiita.com/JavaLangRuntimeException/items/1a1abc01e8d7d05dce93

# 他のシリーズ記事
**TypeScriptで学ぶプログラミングの世界**
プログラミング言語を根本的に理解するシリーズです．

https://qiita.com/JavaLangRuntimeException/items/cadf49bb419076819963

**情報処理技術者試験合格への道[IP・SG・FE・AP]**
情報処理技術者試験に出題されるコンピュータサイエンス用語の紹介や単語集

https://qiita.com/JavaLangRuntimeException/items/991be402099542ccb936

**IAM AWS User クラウドサービスをフル活用しよう！**
AWSのサービスを例にしてバックエンドとインフラ開発の手法を説明するシリーズです．

https://qiita.com/JavaLangRuntimeException/items/371a334f5a6e07035db5

**AWS UserのGCP浮気日記**
GCPの様子をAWSと比較して考えてみるシリーズ

https://qiita.com/JavaLangRuntimeException/items/527d99e774165a763180

**Project Gopher: Unlocking Go’s Secrets**
Go言語や標準ライブラリの深掘り調査レポートです．

https://qiita.com/JavaLangRuntimeException/items/dc45b412d3fbd2ccb9e8

**Gopher’s Journey: Exploring TCP Protocol**
Goを用いてTCPプロトコルを探求 & 作成するシリーズです．

https://qiita.com/JavaLangRuntimeException/items/38091220106d86651d2b

## ユーザ情報 (Users API)

### curlでの例
ユーザ情報を取得するためのUsers APIの一例を示す. 以下は任意のユーザ情報を取得する例だ.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     https://api.github.com/users/example
```

`example`というユーザのプロフィール情報を取得している. アクセストークンを利用しないと回数制限が厳しくなるので, できるだけアクセストークンを使うとよい.

### Go言語での例
```users.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	// 任意のユーザ情報を取得する
	user, _, err := client.Users.Get(ctx, "example")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("ユーザ: %s\nID: %d\nアバターURL: %s\n", user.GetLogin(), user.GetID(), user.GetAvatarURL())
}
```
`github.NewClient(tc)`を用いてGitHub APIクライアントを作成している. `oauth2`パッケージでGitHubトークンを認証に利用する仕組みである.


## リポジトリ (Repositories API)

### curlでの例
認証済みユーザでアクセスできるリポジトリ一覧を取得する例を示す.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     https://api.github.com/user/repos
```

認証したユーザのパブリックおよびプライベートリポジトリ一覧を取得できる.

### Go言語での例
```repos.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	// 自身のリポジトリ一覧を取得する
	repos, _, err := client.Repositories.List(ctx, "", nil)
	if err != nil {
		log.Fatal(err)
	}

	for _, repo := range repos {
		fmt.Printf("リポジトリ名: %s (%s)\n説明: %s\nプライベート: %v\n\n",
			repo.GetName(), repo.GetFullName(), repo.GetDescription(), repo.GetPrivate())
	}
}
```

`client.Repositories.List(ctx, "", nil)`でユーザ名に空文字を渡すと, 認証ユーザのリポジトリ一覧を取得できる.  
また, ほかにもスターを付けたリポジトリの一覧取得やリポジトリの作成, 削除なども可能である.


## イシュー (Issues API)

### curlでの例
イシューの一覧を取得する例である. 以下のリポジトリ`example/SampleRepository`の全イシューを取得する.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     https://api.github.com/repos/example/SampleRepository/issues
```

イシューの作成や更新も同様に`POST`や`PATCH`メソッドを使う.

### Go言語での例
```issues.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	owner := "example"
	repo := "SampleRepository"

	// イシュー一覧を取得する
	issues, _, err := client.Issues.ListByRepo(ctx, owner, repo, nil)
	if err != nil {
		log.Fatal(err)
	}

	for _, issue := range issues {
		fmt.Printf("イシュー番号: %d\nタイトル: %s\n内容: %s\n\n",
			issue.GetNumber(), issue.GetTitle(), issue.GetBody())
	}

	// 新規イシューを作成する例
	newIssue := &github.IssueRequest{
		Title: github.String("新しいイシュー"),
		Body:  github.String("イシューの内容"),
	}
	createdIssue, _, err := client.Issues.Create(ctx, owner, repo, newIssue)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("作成されたイシュー番号: %d\nタイトル: %s\n内容: %s\n",
		createdIssue.GetNumber(), createdIssue.GetTitle(), createdIssue.GetBody())
}
```

イシュー作成時には`Issues.Create`に`IssueRequest`を渡し, タイトルや本文などを指定している. 更新の場合は`Issues.Edit`, 閉じる場合は`state`を`closed`に編集する.

## プルリクエスト (Pull Requests API)

### curlでの例
プルリクエスト一覧を取得する. 以下は`example/SampleRepository`リポジトリのプルリクを取得する例だ.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     https://api.github.com/repos/example/SampleRepository/pulls
```

プルリクエストを作成する際は`POST`メソッドを使う.

### Go言語での例
```pullrequest.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	owner := "example"
	repo := "SampleRepository"

	// プルリクエスト一覧を取得する
	pulls, _, err := client.PullRequests.List(ctx, owner, repo, nil)
	if err != nil {
		log.Fatal(err)
	}

	for _, pr := range pulls {
		fmt.Printf("PR番号: %d\nタイトル: %s\nベースブランチ: %s\nヘッドブランチ: %s\n\n",
			pr.GetNumber(), pr.GetTitle(), pr.Base.GetRef(), pr.Head.GetRef())
	}

	// 新規プルリクエストを作成する例
	newPR := &github.NewPullRequest{
		Title: github.String("新しいプルリクエスト"),
		Head:  github.String("feature-branch"),
		Base:  github.String("main"),
		Body:  github.String("プルリクエストの内容"),
	}
	createdPR, _, err := client.PullRequests.Create(ctx, owner, repo, newPR)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("作成されたプルリク: %d\nタイトル: %s\n",
		createdPR.GetNumber(), createdPR.GetTitle())
}
```

`Head`や`Base`の指定が必要であり, ブランチ名に気をつけてプルリクを作成する. 更新やマージ操作も合わせて利用可能である.

## Gists API
Gistはコードスニペットを管理するための仕組みである. 公開/非公開設定が可能だ.

### curlでの例
個人のGist一覧を取得する例を示す.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     https://api.github.com/users/example/gists
```

### Go言語での例
```gists.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	user := "example"
	gists, _, err := client.Gists.List(ctx, user, nil)
	if err != nil {
		log.Fatal(err)
	}

	for _, gist := range gists {
		fmt.Printf("Gist ID: %s\nDescription: %s\n公開: %v\n\n",
			gist.GetID(), gist.GetDescription(), !gist.GetPublic())
	}

	// 新規Gist作成例
	files := map[github.GistFilename]github.GistFile{
		"sample.go": {
			Content: github.String("package main\n\nfunc main() {}"),
		},
	}
	newGist := &github.Gist{
		Description: github.String("サンプルGist"),
		Public:      github.Bool(true),
		Files:       files,
	}
	createdGist, _, err := client.Gists.Create(ctx, newGist)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("作成されたGist ID: %s\n", createdGist.GetID())
}
```

## Search API
リポジトリ, コード, イシューなどを検索できる. 例としてリポジトリ検索を紹介する.

### curlでの例
Go言語のサンプルリポジトリを検索する例である. クエリはURLエンコードして利用する.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     "https://api.github.com/search/repositories?q=language:go+sample"
```

### Go言語での例
```search.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	query := "language:go sample"
	result, _, err := client.Search.Repositories(ctx, query, nil)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("検索結果: %d件\n", *result.Total)
	for _, repo := range result.Repositories {
		fmt.Printf("- %s (%d stars)\n", repo.GetFullName(), repo.GetStargazersCount())
	}
}
```

Search APIは結果や詳細表示, パラメータ指定など多彩な機能がある.  
リポジトリ以外にもコード, イシュー, コミットなどを検索可能である.

## Notifications API
通知一覧や既読処理を行うためのAPIである. プロジェクトの状態を把握する際に役立つ.

### curlでの例
通知一覧を取得する. たとえば全通知を取得する場合は以下のようにする.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     https://api.github.com/notifications
```

### Go言語での例
```notifications.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	// 通知の一覧を取得する
	notifications, _, err := client.Activity.ListNotifications(ctx, nil)
	if err != nil {
		log.Fatal(err)
	}

	for _, n := range notifications {
		fmt.Printf("通知: %s\nリポジトリ: %s\nスレッドURL: %s\n\n",
			n.GetSubject().GetTitle(),
			n.GetRepository().GetFullName(),
			n.GetSubject().GetURL())
	}

	// 既読にする場合はMarkThreadReadなどを利用する
}
```

## Organizations API
組織情報を取得・管理するためのAPIである. 組織のメンバ情報やリポジトリ管理などに使われる.

### curlでの例
組織情報を取得する例を示す.

```bash
curl -H "Authorization: token <YOUR_PERSONAL_ACCESS_TOKEN>" \
     https://api.github.com/orgs/github
```

### Go言語での例
```orgs.go
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/google/go-github/v57/github"
	"golang.org/x/oauth2"
)

func main() {
	token := os.Getenv("GITHUB_TOKEN")
	if token == "" {
		log.Fatal("GITHUB_TOKENが設定されていない")
	}

	ctx := context.Background()
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: token},
	)
	tc := oauth2.NewClient(ctx, ts)

	client := github.NewClient(tc)

	orgName := "example"
	org, _, err := client.Organizations.Get(ctx, orgName)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("組織名: %s\n説明: %s\nWebサイト: %s\n",
		org.GetLogin(), org.GetDescription(), org.GetBlog())
}
```

組織のメンバーやリポジトリの一括管理などに利用できる.


本記事ではGitHub APIの主要なエンドポイントと, curlおよびGo言語の[github.com/google/go-github/v57/github](https://pkg.go.dev/github.com/google/go-github/v57/github)ライブラリを使った例を紹介した. エンドポイントによってメソッドやパラメータが異なるが, 適切な認証とリクエストを行うことで様々な操作を自動化できる. 本記事のサンプルコードは`example/SampleRepository`というディレクトリ構成での使用を想定しているが, 適宜カスタマイズして自身のプロジェクトに組み込んでみてほしい.