Diary of a Perpetual Student

Perpetual Student: A person who remains at university far beyond the normal period

Go のテーブル駆動テストは map を使って書きたい

Go 言語のプログラムのテストでは、テーブル駆動テストと呼ばれる書き方をすることが多いです。シンプルに例を挙げると以下のような形。

func TestAdd(t *testing.T) {
    cases := []struct{
        title string
        inLhs int64
        inRhs int64
        want int64
    }{
        {
            name: "1 + 1 = 2",
            inLhs: 1,
            inRhs 1,
            want: 2,
        },
    }
    for _, tt := range cases {
        t.Run(tt.title, func(t *testing.T) {
            if got := Add(tt.inLhs, tt.inRhs); got != tt.want {
                t.Errorf("want=%d, got=%d", tt.want, got)
            }
        })
    }
}

色々流派はあるのですが、僕は上のような slice ではなく、下のように map を使ってテストケースを作る方が好みです。

func TestAdd(t *testing.T) {
    cases := map[string]struct{
        inLhs int64
        inRhs int64
        want int64
    }{
        "1 + 1 = 2": {
            inLhs: 1,
            inRhs 1,
            want: 2,
        },
    }
    for title, tt := range cases {
        t.Run(title, func(t *testing.T) {
            if got := Add(tt.inLhs, tt.inRhs); got != tt .want {
                t.Errorf("want=%d, got=%d", tt.want, got)
            }
        })
    }
}

理由は2つ:

  • テストケース名が独立している方が読みやすいから
  • go の map を for した時の順序はランダムなので、順序に依存しないテストであることを保証できるから

明日はいよいよ Go Conference 2023 ですよ〜

gocon.jp

developer.hatenastaff.com

docker build 時に private リポジトリから go get する

要件

Go 言語で作られた、GitHub の private repository の go module に依存しているアプリケーションについて考えましょう。例えばオープンソースではない社内ライブラリに依存している、という状態です。

手元の開発マシン上では GOPRIVATE 環境変数を利用して、go mod download できている状態です。このアプリケーションはコンテナ上で動かすことを想定しており、Dockerfile 内で RUN go build することでバイナリを生成し container image に格納しようとしています。

しかし、public な module だけに依存しているときと同じように Dockerfile を書いても docker build に失敗してしまいます。go mod download 時に private repository から fetch できないのです。

この問題、あなたなら数ある選択肢からどう取捨選択してこの問題を解決しますか?自分は以下の要件を立てて解決策を模索しました:

  • (must) 開発マシン上で docker build した時に、private repository から go get できる
  • (must) GitHub Actions 上で docker build した時に、private repository から go getできる
  • (should) docker build 時にコンテナ環境内で go mod download -> go build できる
  • (should) 生成された docker image 内に不用意に認証情報が埋め込まれていない
  • (may) GitHub の Private Access Token の運用はしたくない
  • (may) 開発マシン上と GitHub Actions 上で同じ Dockerfile を使いまわせる

GitHub Actions 環境で private repostitory から go get する

zenn.dev

概ねこの記事通りにやれば良いです。GitHub App を作る→GitHub Actions上で一時トークンを生成する→そのトークンを使ってgo get する という流れです。

少し古めの記事を見ると、Private Access Token を用いた方法が紹介されています。PAT に依存する運用では組織ではなく個人に紐づいてしまう、アクセス権限の制御をきめ細やかにできない、シークレットのローテーションを定期的に行う必要があるなどのデメリットがあります。

multi stage build を利用することで解決できる問題ではあるのですが、認証情報を ARG で受け渡しているところは少し気になります。multi stage build を用いない場合、RUN --mount=type=secret を用いて一時トークンを受け渡すとより安全になるでしょう。

docs.docker.jp

開発マシン上で docker build した時に、private repository から go get する

こちらの説明も他の記事に譲ります。

qiita.com

手元の秘密鍵を COPY するパワフルなやり方もありますがまあ怖いですよね。今時のBuildKit には --mount=type=ssh と言うオプションがあり、これを用いて ssh-agent に登録している鍵を docker build 時に一時利用することができます。

合わせ技

上の2つを両立するために以下のような Dockerfile を用意しました:

# syntax=docker/dockerfile:experimental

# ** build stage **
FROM golang:1.20-bullseye AS build

COPY ./ /go/src
WORKDIR /go/src

ENV GOPRIVATE=github.com/Arthur1/something-private-repo

# ここがすごい!
RUN --mount=type=secret,id=github_secret_token --mount=type=ssh \
    if [ -z "$(cat /run/secrets/github_secret_token)" ]; then \
    mkdir -p ~/.ssh && chmod 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts; \
    git config --global url."git@github.com:".insteadOf https://github.com/; \
    else \
    git config --global url."https://x-access-token:$(cat /run/secrets/github_secret_token)@github.com/".insteadOf https://github.com/; \
    fi

RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=ssh \
    go build -o hoge ./cmd/hoge/

# ** main stage **
FROM debian:bullseye-slim

COPY --from=build /go/src/hoge  /hoge

ポイントはシェルコマンドの中で if 文を使っている箇所で、

  • github_secret_token secret がセットされているなら、その secret を用いて https で go get するための git config を用意
  • github_secret_token secret がセットされていないなら、mount した ssh 鍵を使って go get するための git config を用意

と言う挙動を実現しています。

つまり、GitHub Actions 上では DOCKER_BUILDKIT=1 docker build --secret id=github_secret_token,env=GH_SECRET_TOKEN .、手元では DOCKER_BUILDKIT=1 docker build --ssh default . すればコンテナイメージの build 時に private repository から go get してコンテナ上でバイナリビルドができるようになります。

めでたしめでたし。


 
 
 
 
 

END ... ?

これでいいのか?

この Dockerfile を見てなにか腑に落ちない人もいるかなと思います。高々 private repository から go get したいだけなのに、何でこんな大層な workaround を用意しているのだろう、と言う気持ちになりました。

要件を疑え

そもそも、要件にある「 docker build 時にコンテナ環境内で go mod download -> go build できる」という条件は本当に必要でしょうか?

例えば、go module の download は GOMODCACHE 変数を指定した上で Docker の外でやり、mod cache ディレクトリを Dockerfile で COPY してコンテナ内で build はやる、という解決策もあるでしょう。

他にも、クロスコンパイルが得意な Go で docker container 内で build する必要もなくて、docker の外で go build して生成した実行ファイルをコンテナに格納すると言う手法もあります。docker を使ってホスト環境依存をなくしたつもりでも、結局 Linux カーネル大親友である glibc への依存は避けられないですからね。もちろん、Go のバージョンを各自で固定しづらいといったデメリットは生じます。

まとめ

docker build 時に private リポジトリから go get する手法については、要件を定義して、各自でベストと思える解決策を採用しましょう。また、そもそも docker build 時にやる必要ありますか?ということについてもぜひ考え直してみてください。

愚痴しか出てこないアグリコラ ドレミの歌

動画にする気力はなかった


ドは「ドラフトミスったわ〜なんであれ流しちゃったんだろ〜〜はいGG」のド〜

レは「レン窯使い捨てするなら俺にくれよ〜」のレ〜

ミは「ミネラルフィーダー*1って収穫の"ない"ラウンドなの?は〜読み間違えたわ」のミ〜

ファは「ファサード彫刻*2の前提、分かりづらすぎね?」のファ〜

ソは「そこの葦補充されてなくない?R4に葦2で取ったから今葦3だよね、それめっちゃ大事だから」〜

ラは「ランタンの家*3出したけど全然手札減らね〜授業空けてくれ〜〜」のラ〜

シは「下家にスタプ打たれまくって死んだわ〜〜〜〜〜」

さぁ歌いましょ〜

AWS Certified Solutions Architect - Associate になりました

気づいたら社会人2年目が始まっていた id:arthur-1 です。

この度、めでたく AWS SAA-C03 試験に合格しました。

得点は 796 / 1000 点(ボーダー 720点)で可もなく不可もなく。早く仕事がしたかったので制限時間を半分以上残して退出したのですが、もう少し見直しなどしても良かったかもしれません。

感想と知見

C03 対応の教材はまだ限られている

2022/8/30 に SAA の試験が改定されました。現時点で改定から間もないこともあり、出版物の改版がなかなか追いついていません。自分は今年3月に発売された以下の本を購入して読破しました。文章や模擬試験にちょっとした typo はあるものの、読みやすくて良かったと思います。

手を動かしてこそ分かることはいっぱいある

自分は書籍を買ったり模擬試験を解いたりしましたが、出題される内容の範囲の割には座学の時間は比較的短く済ませられた方なんじゃないかなと思います。

普段の業務でも AWS をかなり触っていること、さらに、そこで得た知識を個人開発という砂場でも活かしたことで、自然とすでに身についていた知識も多かったなと思いました。特に IAM 周りとか、初見では概念が複雑すぎて意味不明なのだけど、実際に設定して苦労することで分かることがたくさんあるんですよね。

また、AWS JumpStart for NewGrads (設計編)に参加させてもらったのも良い結果に結びついた要因かなと思っています。VPC 周りの概念をちゃんと身につけたのはこのワークショップのおかげですし、複数考えられるアーキテクチャ案から何を重視してどんな選択をするのかという体験がまさに試験問題そのものでした。

developer.hatenastaff.com

the next is...

次は Certified Developer - Associate (DVA-C02) あたりにチャレンジしようと思います。ではでは

『「気軽にアウトプット」する危うさ』をアウトプットする危うさはあるか

これはただ思考実験したというメモ。

note.com

を読んだ。

とにかくだ、Bad Practiceを広めるな

(中略)

結局行き着く先は、間違った情報の拡散による、その技術を扱う者へのダメージ源になるだけだ。

とある。

直接的ではないにせよこの記事も技術に関する話題なわけだ。とすると、もしこの主張自身が Bad Practice だとしたらこの主張を伝える手段の正当性はどうなるんだろう?と考えていた。

2023 GW のゆるふわ日記

これはゆるふわアウトプット。

同僚の家にお邪魔してアイドルの動画を見ながら朝まで酒を飲んだところで GW が始まった。前々からなんとなく憧れのあったライダースジャケットを頂いた。ポップとクールの狭間で生きたいと思っていて、このオトナなアイテムをどう料理しようか考えあぐねている。


大学時代の友人6人が自分の家に遊びに来てホームパーティをした。リビング(通称キッズコーナー)に椅子が6個しかないので、普段仕事で使っているオフィスチェアを動員してなんとか7人座れた。ito のお題で「聞いてみたい〇〇(人物)の△△(物事)講座」というのをやってみたら結構盛り上がった。呂布カルマの人を傷つけないラップ講座あったら誰もが聞きたいでしょ。


中日の平日は普通に出勤して、新入社員をワイワイ歓迎したりゆるふわでないアウトプットの仕込みをしたりしていた。ゆるふわでないアウトプットというのは Slack 活用アワード 決勝プレゼン大会の登壇である。歓迎会も増え幹事力は高まりつつあるけど普通に仕事で評価されるようにならなくちゃ。


髪を切った。いつもお世話になってます。行くたびに学割のための学生証の提示を求められて、「すみませんもう学生じゃないんです〜」ってやりとりをしている。まあ気分は今でも学生でブログの名前も Diary of Perpetual Student なのだけれど。


実家に帰ってダラダラ…する暇はなく、個人開発サービスのメンテナンス準備をやっていた。サポート終了した PHP 7.4 を脱却するために Laravel のバージョンを上げるなどの地味な作業をしていた。テストがないとシステムを破壊するのが怖くてどうしてもメンテの機運が下がる。本番環境のオペレーションは普段のアクセス状況を鑑み、 GW を外した平日の深夜に行おうと思う。


かつやに初めて行った。かなり良かった。夕食のローテーションに加えたいぐらいだが今住んでるところだと車がないと行けない距離感なので厳しい。車欲しい。免許も欲しい。


沼津アルプストンネルが開通したので通ってきた。昔住んでいた地域なので思い入れがある。そして便利ですね〜。

www.numa2.jp

余談だけれど、この「ぬまつー」というサイトが結構良くて、地元を離れていてもちゃんと沼津の情報が入ってきて浦島太郎にならずに済む。こういう地元メディア的なものが自分は大好きで、横浜の日吉に住んでいた頃も横浜日吉新聞をよく watch していた。

hiyosi.net


サポートメンバーとして入っているバンドの練習に参加した。スコアはもらっていなくて、その場で曲聞いてコード進行覚えたりアレンジの方針立てたりしてセッションする感じ。自分はトランスポーズに頼っていて(ゆゆうたスタイル)、曲が変わると設定をポチポチいじらなきゃいけないので、スタジオ備え付けの鍵盤で頑張るのはちょっと大変。


ふと、中学とか高校同期と全く会話していないなということに気づいた。Instagram を見るとホイホイと結婚報告が上がったりしていてはえ〜という気分になる。自分だけ精神年齢が止まっていて、家に集まってテレビゲームしようぜ!的な価値観で今も過ごしているので、ギャップに苦しんでいる。

ゼルダの伝説 ブレス オブ ザ ワイルドの続編、ゼルダの伝説 ティアーズ オブ ザ キングダムは2023年5月12日(金)発売です。

www.nintendo.co.jp

最近聴いてる曲: Apr. 2023

prev:

blog.arthur1.dev

瞳のランデヴー / フジファブリック×フレデリック

サビのコーラスが良い。BRADIO の 感情リテラシー のような爽快感ある旋律の合わせ方

www.youtube.com

あの子コンプレックス / =LOVE

最近の坂道刺さる曲全然ないな~と思っていてアイドル自体から離れつつあったので久々に

www.youtube.com

青い春のエチュード / TOKYO SKA PARADISE ORCHESTRA feat.長屋晴子 (緑黄色社会)

良いコラボすぎた

www.youtube.com

すれ違う視線、重なる言葉。 / フロクロ feat. 重音テト

何から何まで好き

www.youtube.com

ビビビビ のリファレンスも読み応えあってよかった

scrapbox.io

世界五分後仮説 / ダンダンヲ

この人高校生なのかすごい

www.youtube.com

浮遊感UFO / 月ノ美兎

理論好きなのでイントロのギターサウンドでバッチリ刺さった

www.youtube.com

まとめ

イヤホンをなくしてしまってから全く開拓できていない…