Slide 1

Slide 1 text

go.mod、DockerfileやCI設定に 分散しがちなGoのバージョンを まとめて管理する id:arthur-1 株式会社はてな 2024-10-23 Go Connect #3 1

Slide 2

Slide 2 text

Arthurと申します 株式会社はてな アプリケーションエンジニア 好きなプログラミング言語マスコッ トはD言語くんとDenoの恐竜です 𝕏: @Arthur1__ 2

Slide 3

Slide 3 text

MackerelはGoを使って作ってます 3

Slide 4

Slide 4 text

昨日はイベントやってました 4 https://www.youtube.com/live/NJM3HK744Bs?si=Z0XYOkDOk5yOCFHL

Slide 5

Slide 5 text

本題 5

Slide 6

Slide 6 text

アプリケーションで 利用したい Goのバージョ ン どう宣言してますか? 6

Slide 7

Slide 7 text

go.modのgo directive 7 module github.com/Arthur1/hoge go 1.22

Slide 8

Slide 8 text

go.modのtoolchain directive 8 module github.com/Arthur1/hoge go 1.22 toolchain go1.23.0

Slide 9

Slide 9 text

Dockerfileのbase image tag 9 FROM golang:1.23-bookworm AS builder COPY . . RUN go build -o server ./cmd/server

Slide 10

Slide 10 text

GitHub Actionsのsetup-go 10 - uses: actions/setup-go@v5 with: go-version: 1.23

Slide 11

Slide 11 text

GitHub Actionsのsetup-go 11 - uses: actions/setup-go@v5 with: go-version-file: go.mod

Slide 12

Slide 12 text

こんな悩みはないか? ● 様々な場所にGoのバージョンが書かれてい て、アップデート時の書き換えが大変 ● パッケージの自動更新をするツールでGoの バージョンも自動アップデートしていきたい 12

Slide 13

Slide 13 text

ソリューションを 提示する前に 13

Slide 14

Slide 14 text

Goビルトインの バージョン宣言方法紹介 14

Slide 15

Slide 15 text

go.modのgo directive > The go directive sets the minimum version of Go required to use this module. https://go.dev/ref/mod#go-mod-file-go ビルドできる最小の言語バージョンを定義する 15

Slide 16

Slide 16 text

go.modのtoolchain directive > A toolchain directive declares a suggested Go toolchain to use with a module. https://go.dev/ref/mod#go-mod-file-toolchain 推奨されるGoのツールチェーンのバージョン (の下限)を定義する 16

Slide 17

Slide 17 text

Goのツールチェーンの仕組み GOTOOLCHAIN=auto(デフォルト)なら、推奨され るツールチェーンかそれより新しいものがない場合に ダウンロードされる goenvやasdfで複数のGoのバイナリを使い分ける必要 は、基本はないはず 17

Slide 18

Slide 18 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.0で go directiveが1.23.0 →使用されるツールチェーンのバージョンは? 18

Slide 19

Slide 19 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.0で go directiveが1.23.0 →使用されるツールチェーンのバージョンは1.23.0 19

Slide 20

Slide 20 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.3で go directiveが1.23.0 →使用されるツールチェーンのバージョンは? 20

Slide 21

Slide 21 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.3で go directiveが1.23.0 →使用されるツールチェーンのバージョンは1.23.3 21

Slide 22

Slide 22 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.0で go directiveが1.22.0 toolchain directiveがgo1.23.3 →使用されるツールチェーンのバージョンは? 22

Slide 23

Slide 23 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.0で go directiveが1.22.0 toolchain directiveがgo1.23.3 →使用されるツールチェーンのバージョンは1.23.3 23

Slide 24

Slide 24 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.3で go directiveが1.22.0 toolchain directiveがgo1.22.0 →使用されるツールチェーンのバージョンは? 24

Slide 25

Slide 25 text

Goのツールチェーンの仕組み(例) 手元のGoのバイナリが1.23.3で go directiveが1.22.0 toolchain directiveがgo1.22.0 →使用されるツールチェーンのバージョンは1.23.3 25

Slide 26

Slide 26 text

[再掲]こんな悩みはないか? ● 様々な場所にGoのバージョンが書かれてい て、アップデート時の書き換えが大変 ● パッケージの自動更新をするツールでGoの バージョンも自動アップデートしていきたい 26

Slide 27

Slide 27 text

ソリューション 27

Slide 28

Slide 28 text

私の主張 アプリケーションで使用されるべき Goのバージョンは go.modのtoolchain directiveで 宣言しよう! 28

Slide 29

Slide 29 text

ただし 宣言したバージョンかそれ以上のツールチェーンを許容す るので、宣言したものと常にピッタリ一致させたい場合は 工夫が必要 こういうニーズもあるはずだが、今回触れるには時間が足 りなさすぎるので、後で紹介するブログを読んでください 29

Slide 30

Slide 30 text

この仮定って現実的? 「宣言したバージョンか、それ以上はOK」という管理方 法で大丈夫か?という話 セキュリティ対応で特定のtoolchain以上にしたいという ニーズはあるはずで、これは満たせる Goの後方互換を信じるなら十分そう 30

Slide 31

Slide 31 text

パブリックな開発では OSSの場合や、公開packageが他のコードから参照され ている場合に、go directiveで不必要に他人のビルド環境 を制約する必要はない go directiveは利用したい言語機能が増えたときにはじめ てアップデートすれば良い 31

Slide 32

Slide 32 text

toolchainはRenovateで更新可能 Renovateはtoolchain directiveを最新のものに更新 するPull Requestを勝手に作ってくれる 32

Slide 33

Slide 33 text

Dockerfileや  CIの設定に書かれた バージョンはどうする? 33

Slide 34

Slide 34 text

Dockerfile 公式のGoのイメージはGOTOOLCHAIN=localに なっている(toolchainをダウンロードしない) DockerfileにENV GOTOOLCHAIN=autoと明示的 に書くことで、必要に応じてtoolchainがダウン ロードされる 34

Slide 35

Slide 35 text

Dockerfile(例) 35 FROM golang:bookworm AS builder ENV GOTOOLCHAIN=auto COPY . . RUN go build -o server ./cmd/server

Slide 36

Slide 36 text

GitHub Actionsのsetup-go go-version-file引数にgo.modを渡してあげ たらtoolchain directiveを参照してくれる? 36

Slide 37

Slide 37 text

GitHub Actionsのsetup-go go-version-file引数にgo.modを渡してあげ たらtoolchain directiveを参照してくれる? →わけではない 37

Slide 38

Slide 38 text

GitHub Actionsのsetup-go 38 - uses: actions/setup-go@v5 with: go-version-file: go.mod go 1.21.0 toolchain go1.23.0

Slide 39

Slide 39 text

GitHub Actionsのsetup-go 39 - uses: actions/setup-go@v5 with: go-version-file: go.mod go 1.21.0 toolchain go1.23.0 ① setup-goがgo directiveを見て1.21.0のGoバイナリを準備する ② build時にtoolchain directiveを見て1.23.0をダウンロードする 動くには動くけど、毎回DLしてて勿体無い

Slide 40

Slide 40 text

GitHub Actionsのsetup-go 40 - uses: actions/setup-go@v5 with: go-version: stable 宣言したツールチェーンと同じか、それより新しいものを許容する場 合には、とりあえずここはstableでよい。古い分にはtoolchainが自 動でダウンロードされる

Slide 41

Slide 41 text

まとめ Goのバージョンの決定についてはGoのエコシス テムにすべて寄せることで、テストやアップデー ト時の労力を減らすことができる! 今回のやり方ならRenovateのPRをmergeするだ けで推奨ツールチェーンが勝手に上がっていく 41

Slide 42

Slide 42 text

合わせて読んでね 1. アプリケーションではなくライブラリの場合 2. strictにGoのバージョンを指定したい場合 にも触れています: ● Go製アプリケーション/ライブラリにおけるメンテナ ンス性を重視したGoのバージョン管理戦略 ● GitHub ActionsのGoのバージョンをtoolchainディ レクティブの指定ぴったりで固定したい場合 42

Slide 43

Slide 43 text

おしまい 43