概要

2024年の1月の発表にGitHub BlogでこれまでのGitHubを操作するSDKであるOctokitからKiotaを使用したSDKに移行するという記事が公開されました。 KiotaとはOpenAPIで記述されたWebAPI仕様書を元に多言語で使用可能なクライアントライブラリを自動生成するツールです。 GitHubのAPIについてのOpenAPIでの記述はこちらのリポジトリで別途管理されています。

現在KiotaによるSDKがC#とGoで公開されています。 これら言語は既存のOctkitで対応していないため、新たに採用されたようです。 尚、現在これらSDKは非安定版となっていますので変更される可能性があります。

本記事ではGoを使って特定リポジトリのIssueリストを取得します。

環境

  • Ubuntu 22.04
  • Go 1.22.2

サンプル実行

まずはインストールしてサンプルを動かしてみます。

Moduleを追加します。

go get github.com/octokit/go-sdk
go get github.com/microsoft/kiota-abstractions-go
go mod tidy

main.goを作成(元コード)します。

package main

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

	abs "github.com/microsoft/kiota-abstractions-go"
	"github.com/octokit/go-sdk/pkg"
)

func main() {
	client, err := pkg.NewApiClient(
		pkg.WithUserAgent("my-user-agent"),
		pkg.WithRequestTimeout(5*time.Second),
		pkg.WithBaseUrl("https://api.github.com"),
		pkg.WithAuthorizationToken(os.Getenv("GITHUB_TOKEN")),
	)

	// equally valid:
	//client, err := pkg.NewApiClient()
	if err != nil {
		log.Fatalf("error creating client: %v", err)
	}

	queryParams := &abs.DefaultQueryParameters{}
	requestConfig := &abs.RequestConfiguration[abs.DefaultQueryParameters]{
		QueryParameters: queryParams,
	}
	zen, err := client.Zen().Get(context.Background(), requestConfig)
	if err != nil {
		fmt.Printf("error getting Zen: %v\n", err)
		return
	}
	fmt.Printf("%v\n", *zen)
}

上記コードを実行すると、 https://api.github.com/zen の実行と同様の結果を文字列として取得できていることがわかります。

go run main.go

Speak like a human.

Issueリストを取得する

基本的にはZenのやり方と同じですが、試しにIssueリストを取得してみることにしました。 マニュアルは見当たらなかったので、ライブラリのドキュメントを元にしました。

Issueは特定リポジトリのIssueだけでなく、ユーザーの所有するIssueを取得するエンドポイントもあるため、 間違わないように注意です。

Repos().ByOwnerId(owner_id).ByRepoId(repo_id).Issues().Get() のようにメソッドチェーンでかけるのはわかりやすいです。

package main

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

	abs "github.com/microsoft/kiota-abstractions-go"
	"github.com/octokit/go-sdk/pkg"
	"github.com/octokit/go-sdk/pkg/github/repos"
)

func main() {
	client, err := pkg.NewApiClient(
		pkg.WithAuthorizationToken(os.Getenv("GITHUB_TOKEN")),
		pkg.WithBaseUrl("https://api.github.com"),
	)

	if err != nil {
		log.Fatalf("error creating client: %v", err)
	}

	// リポジトリ情報
	owner_id := "octop162"
	repo_id := "notify_github_issues_deadline"

	// リポジトリ情報をもとに検索
	params := repos.ItemItemIssuesRequestBuilderGetQueryParameters{}
	requestConfig := &abs.RequestConfiguration[repos.ItemItemIssuesRequestBuilderGetQueryParameters]{
		QueryParameters: &params,
	}
	issue, err := client.Repos().ByOwnerId(owner_id).
		ByRepoId(repo_id).
		Issues().
		Get(context.Background(), requestConfig)

	if err != nil {
		fmt.Printf("error getting issues: %v\n", err)
		return
	}

	for _, value := range issue {
		fmt.Println(
			"IssueNo:" + strconv.FormatInt(int64(*value.GetNumber()), 10) +
				" Title:" + *value.GetTitle())
	}
}

実行結果はこんな感じです。構造体からIssue番号とタイトルを取得してきました。 ドキュメントにまあまあ手こずったのでREST APIでいいのではと途中思いました。

go run main.go

IssueNo:8 Title:[remind-20240504]のってくべきだよ
IssueNo:7 Title:[20240503] のってくべきでしょ
IssueNo:6 Title:20240502 test
IssueNo:4 Title:20240601
IssueNo:3 Title:test3
IssueNo:2 Title:test2