毎回、go-githubのclientをGITHUB_*やらGH_*やらを判定して組み立てたり、外部パッケージのgo-githubのバージョンに合わせたりするのが面倒になって、カッとなって作ったhttps://t.co/8zhsP3V8cv
— k1LoW (@k1LoW) 2021年11月6日
サブディレクトリの使い方がひどい(go-githubのバージョンに合わせて切っている)がもうこれでいい
GitHubやGitHub Actionsが好きで、いろいろツールを作ったりするのですが、毎回毎回go-githubのClientのインスタンス生成のために何行かコードを書いています。
最初の頃は GITHUB_TOKEN
のことだけを考えていていたのが、その後GitHub Enterpriseのエンドポイントも考えるようになり、GitHub Actionsの登場からはActions上の環境変数をうまく使いたくもなり、GitHub CLI extensionがでてきてからは、GH_*
という環境変数も考慮する必要がでてきています。
その都度過去のツールのコードをまるっとコピペしつつもgo-githubのClientインスタンス生成コードは変わってきています。
また、go-githubはセマンティックバージョニングを採用している(?)のか、既にv39まできています。 go-githubのClientを引数に受け取るような外部パッケージがあったとき、その外部パッケージが採用しているgo-githubのメジャーバージョンに合わせないといけないのも苦でした。
毎回コピペコードを書いたり、過去ツールの実装を直したりするのも嫌になってきたので、go-github-clientとしてコード片をパッケージ化しました。
go-github-client
使い方は go-github のメジャーバージョンに合わせて go-github-client/[VERSION]/factory
をimportして使うだけです。
package main import ( "context" "fmt" "github.com/k1LoW/go-github-client/v39/factory" ) func main() { ctx := context.Background() c, _ := factory.NewGithubClient() u, _, _ := c.Users.Get(ctx, "k1LoW") fmt.Printf("%s\n", u.GetLocation()) }
factory.NewGithubClient()
内で、環境変数からトークンやエンドポイントの解決をし生成したClientインスタンスを返します。
また、Functional Option Patternを採用しているので、外部からトークンやエンドポイントなどを差し込むことも可能です。
例えば、go-githubをモック化したい場合は、 *http.Client
を外部から差し込むことで解決します。
package main import ( "context" "testing" "github.com/google/go-github/v39/github" "github.com/k1LoW/go-github-client/v39/factory" "github.com/migueleliasweb/go-github-mock/src/mock" ) func TestUsingMock(t *testing.T) { mockedHTTPClient := mock.NewMockedHTTPClient( mock.WithRequestMatch( mock.GetUsersByUsername, github.User{ Name: github.String("foobar"), }, ), ) c, err := factory.NewGithubClient(factory.HTTPClient(mockedHTTPClient)) if err != nil { t.Fatal(err) } ctx := context.Background() user, _, err := c.Users.Get(ctx, "myuser") if err != nil { t.Fatal(err) } got := user.GetName() if want := "foobar"; got != want { t.Errorf("got %v\nwant %v", got, want) } }
バージョニング
バージョニングは少し特殊です。
このgo-github-clientパッケージ自体がgo-githubのClientを生成するだけのものなので、基本的にgo-githubバージョンと合わせてタグやディレクトリを切っています。
ただ、go-github-client自体の機能追加もあるので、それにはパッチバージョンに加算することで対応します。
表で表すと以下のような感じです。
バージョン | 構成 |
---|---|
Major | google/go-github のmajorバージョン |
Minor | google/go-github のminorバージョン |
Patch | google/go-github のpatchバージョンにk1LoW/go-github-clientの更新を加算 |
まあちょっとひどいですが、利便性を考えて割り切ります。
というわけで
ただのコード片ですが、これからもGitHub APIを叩くツールや実装は作りそうなので、個人的にはこれを使っていこうかと思っています。
そういえば昔もawsecretsというgemを作ったりしていて、成長していないなーなどと思いました。