Go 製 CLI ツールにおける selfupdate の実装

3 min read読了の目安(約2700字

intro

どうもこんにちは、@kamina-zzz と申します。初めての zenn で緊張しております。よろしくおねがいします。

突然ですが、入社時に「 これをインストールしておけばとりあえず開発できるで! 」みたいなツールがあると何かと便利ですよね。
例えばエンジニアが開発するにあたって必要なツール(例えば kubectlistioctl とかとか)のインストールとかをやったり認証をしたりデプロイをしたりするのを全部ひとつの CLI ツール経由でやれると嬉しいですよね。

ということで今 Ubie では ubiectl という名前の CLI ツールを Go で作っています。
普段からよく使う機能はどんどん実装していきたいし、改善したらすぐに最新ビルドを使ってもらいたいですよね。
だけど毎回エンジニア個々人に repo 見に行ってもらって最新版が出てるかチェックしてもらうのは手間だし、最新版があるかどうかは勝手に教えて欲しいし、それこそ ubiectl update self とかしたらいい感じに最新化してほしいですよね。

そこで、以前から業務委託で手伝ってもらっている方と一緒にガガッと selfupdate 機構を作ったので、その時二人で調べて実装した部分を書いてみようと思います。

そもそも、既にそういうのないの?

と思って調べてみると rhysd/go-github-selfupdate という GitHub の release を使った selfupdate ライブラリがありました。

go-github-selfupdate

調べてみても機能としては完全に必要十分で、早速有力そうだぞ、ということで試していきます。

package main

import (
    "fmt"
    "os"

    "github.com/blang/semver"
    "github.com/rhysd/go-github-selfupdate/selfupdate"
)

func main() {
    selfupdate.EnableLog()

    latest, err := selfupdate.UpdateSelf(
        semver.MustParse("1.2.3"),
        "kamina-zzz/gh-update-test",
    )
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
    }

    fmt.Printf("version: %s, releasenote: %s", latest.Version, latest.ReleaseNotes)
}

使い方も簡単でやりたいことはこれを使えばすべてできそうなんですが、よくよく考えれば会社の repo が対象なので全部 private repo なんですよね…
README にも書かれていますが、GitHub API の仕様上 private repo を扱うには $GITHUB_TOKEN かもしくは .gitconfig[token] を追記する必要があります。

これを入社時にやってもらってもいいんですが、ちょっとだけめんどくさいですよね…

go-selfupdate

他にもさがしてみると sanbornm/go-selfupdate というライブラリがみつかりました。
このライブラリはより一般化した selfupdate 体験を提供するための機能が詰まっていて使えそうな感じがします。

ただし、詳細は省きますがこのライブラリは結構ルールがひかれてる感じで、そのために整えるべき命名規則やサーバーなどがいろいろとあり、うーん…となってきます。
というか本質の「ダウンロードしてきたバイナリを自身のバイナリと入れ替える」機構だけに絞ってあとは自分で好きに用意したいな、という気持ちになってきました。

ということで go-selfupdate が依存してるライブラリを見てみるとどうやら inconshreveable/go-update というライブラリがあり、どうもここが本質そうなのでこちらを使うようにします。

やっていき

ということで結局はこんな感じで実装しました。

  • ubiectl コマンド実行のついでに最新版のチェックを行うようにした
    • 毎回は多いかなと思ったので最大でも1日に1回だけチェックする
  • バイナリ置き換えは go-update を使う
    • バイナリ置き場は GCS にした
    • Ubie では Google Workspace をヘビーに使っているので Google auth は入社直後でもできてるだろう、ということにした
    • ubiectl update self で最新化される
  • バージョニングの機構は自前で実装することにした
    • ~/.config 以下に ubiectl のバージョンなどをまとめておく
    • 尚セマンティクスバージョニングの細かい仕様などは一旦目をつぶることにして大雑把にやった

よく分かる図

ちなみに初回インストール用のシェルスクリプトも用意しておいてこれも GCS 上に置いておくことで bash <(gsutil cat gs://hoge/install) みたいな感じで latest を持ってこれるようにもしました。

outro

一旦は目的果たせた感じですが、外部通信でちょっとだけ待たされるのが微妙だなーと思うので今後は最新版チェックを並列化したりなんだりできたらなーと思っていますね。

他にも機能面では各種ダッシュボードへのリンクすぐ開けたりよく見るあの画面を開けたり、とかとか作っていこうと思っています。