Slide 1

Slide 1 text

1 Yuki ITO mercari.go #12 Bazel Go

Slide 2

Slide 2 text

2 ʮGoͷ৽ػೳΛ࢖ͬͨDBεΩʔϚ؅ཧπʔϧʯ

Slide 3

Slide 3 text

3 https://github.com/mercari/wrench Schema Management Tool for Cloud Spanner

Slide 4

Slide 4 text

4 https://speakerdeck.com/micnncim/accelerate-go-development-with-bazel

Slide 5

Slide 5 text

Agenda 5 ɾWhat is Bazel ɾHow to use for Go ɾTips

Slide 6

Slide 6 text

Agenda 6 ɾWhat is Bazel ɾHow to use for Go ɾTips

Slide 7

Slide 7 text

What is Bazel 7 Bazel is an open-source build and test tool similar to Make, Maven, and Gradle. https://docs.bazel.build/versions/master/bazel-overview.html

Slide 8

Slide 8 text

What is Bazel 8 One tool, multiple languages/platforms ...

Slide 9

Slide 9 text

What is Bazel 9 High-level build language Starlark (dialect of Python) Starlark is a language intended for use as a configuration language. It was designed for the Bazel build system, but may be useful for other projects as well. https://github.com/bazelbuild/starlark

Slide 10

Slide 10 text

What is Bazel 10 Starlark (dialect of Python) def fizz_buzz(n): """Print Fizz Buzz numbers from 1 to n.""" for i in range(1, n + 1): s = "" if i % 3 == 0: s += "Fizz" if i % 5 == 0: s += "Buzz" print(s if s else i) fizz_buzz(20)

Slide 11

Slide 11 text

What is Bazel 11 Extensible load( "@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", ) http_archive( name = "io_bazel_rules_go", urls = ["..."], )

Slide 12

Slide 12 text

Agenda 12 ɾWhat is Bazel ɾHow to use for Go ɾTips

Slide 13

Slide 13 text

WORKSPACE & BUILD 13 ᵓ── BUILD.bazel ᵓ── WORKSPACE ᵓ── cmd │ ᵓ── BUILD.bazel │ ᵓ── apply.go │ └── ... ᵓ── main.go ᵓ── pkg │ └── spanner │ ᵓ── BUILD.bazel │ ᵓ── client.go │ └── ... └── ...

Slide 14

Slide 14 text

WORKSPACE & BUILD 14 ᵓ── BUILD.bazel ᵓ── WORKSPACE ᵓ── cmd │ ᵓ── BUILD.bazel │ ᵓ── apply.go │ └── ... ᵓ── main.go ᵓ── pkg │ └── spanner │ ᵓ── BUILD.bazel │ ᵓ── client.go │ └── ... └── ... WORKSPACE

Slide 15

Slide 15 text

WORKSPACE & BUILD 15 The WORKSPACE file, which identifies the directory and its contents as a Bazel workspace and lives at the root of the project’s directory structure. WORKSPACE

Slide 16

Slide 16 text

16 http_archive( name = "io_bazel_rules_go", urls = ["..."], ) load( "@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies", ) go_rules_dependencies() go_register_toolchains( go_version = "1.13.4", nogo = "@//:nogo", )

Slide 17

Slide 17 text

17 http_archive( name = "io_bazel_rules_go", urls = ["..."], ) load( "@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies", ) go_rules_dependencies() go_register_toolchains( go_version = "1.13.4", nogo = "@//:nogo", )

Slide 18

Slide 18 text

18 go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", version = "v0.0.0-20190523083050-ea95bdfd59fc", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) go_repository( name = "com_github_burntsushi_xgb", importpath = "github.com/BurntSushi/xgb", sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", version = "v0.0.0-20160522181843-27f122750802", ) ...

Slide 19

Slide 19 text

19 https://github.com/bazelbuild/rules_go Extension for Go

Slide 20

Slide 20 text

WORKSPACE & BUILD 20 ᵓ── BUILD.bazel ᵓ── WORKSPACE ᵓ── cmd │ ᵓ── BUILD.bazel │ ᵓ── apply.go │ └── ... ᵓ── main.go ᵓ── pkg │ └── spanner │ ᵓ── BUILD.bazel │ ᵓ── client.go │ └── ... └── ... BUILD

Slide 21

Slide 21 text

WORKSPACE & BUILD 21 One or more BUILD files, which tell Bazel how to build different parts of the project. BUILD

Slide 22

Slide 22 text

22 go_library( name = "go_default_library", srcs = ["main.go"], importpath = "github.com/mercari/wrench", visibility = ["//visibility:private"], deps = [ "//cmd:go_default_library", "//pkg/spanner:go_default_library", ], ) go_binary( name = "wrench", embed = [":go_default_library"], visibility = ["//visibility:public"], )

Slide 23

Slide 23 text

23 go_library( name = "go_default_library", srcs = [ "apply.go", ... ], importpath = "github.com/mercari/wrench/cmd", visibility = ["//visibility:public"], deps = [ "//pkg/spanner:go_default_library", "@com_github_spf13_cobra//:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ "export_test.go", "migrate_test.go", ], data = glob(["testdata/**"]), embed = [":go_default_library"], )

Slide 24

Slide 24 text

WORKSPACE & BUILD 24 ᵓ── BUILD.bazel ᵓ── WORKSPACE ᵓ── cmd │ ᵓ── BUILD.bazel │ ᵓ── apply.go │ └── ... ᵓ── main.go ᵓ── pkg │ └── spanner │ ᵓ── BUILD.bazel │ ᵓ── client.go │ └── ... └── ... Time consuming to write manually...

Slide 25

Slide 25 text

WORKSPACE & BUILD 25 go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", version = "v0.0.0-20190523083050-ea95bdfd59fc", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) go_repository( name = "com_github_burntsushi_xgb", importpath = "github.com/BurntSushi/xgb", sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", version = "v0.0.0-20160522181843-27f122750802", ) ... Time consuming to write manually...

Slide 26

Slide 26 text

26 https://github.com/bazelbuild/bazel-gazelle gazelle ɾGenerates BUILD files for all packages ɾGenerates all go_repository instructions

Slide 27

Slide 27 text

27 https://github.com/bazelbuild/bazel-gazelle gazelle ɾGenerates BUILD files for all packages ɾGenerates all go_repository instructions

Slide 28

Slide 28 text

28 gazelle > bazel run //:gazelle

Slide 29

Slide 29 text

WORKSPACE & BUILD 29 ᵓ── BUILD.bazel ᵓ── WORKSPACE ᵓ── cmd │ ᵓ── BUILD.bazel │ ᵓ── apply.go │ └── ... ᵓ── main.go ᵓ── pkg │ └── spanner │ ᵓ── BUILD.bazel │ ᵓ── client.go │ └── ... └── ... BUILD

Slide 30

Slide 30 text

30 https://github.com/bazelbuild/bazel-gazelle gazelle ɾGenerates BUILD files for all packages ɾGenerates all go_repository instructions

Slide 31

Slide 31 text

31 gazelle > bazel run //:gazelle -- \ update-repos \ -from_file go.mod

Slide 32

Slide 32 text

32 go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", version = "v0.0.0-20190523083050-ea95bdfd59fc", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) go_repository( name = "com_github_burntsushi_xgb", importpath = "github.com/BurntSushi/xgb", sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", version = "v0.0.0-20160522181843-27f122750802", ) ...

Slide 33

Slide 33 text

WORKSPACE & BUILD 33 ᵓ── BUILD.bazel ᵓ── WORKSPACE ᵓ── cmd │ ᵓ── BUILD.bazel │ ᵓ── apply.go │ └── ... ᵓ── main.go ᵓ── pkg │ └── spanner │ ᵓ── BUILD.bazel │ ᵓ── client.go │ └── ... └── ...

Slide 34

Slide 34 text

34 > bazel build //:wrench

Slide 35

Slide 35 text

35 go_library( name = "go_default_library", srcs = ["main.go"], importpath = "github.com/mercari/wrench", visibility = ["//visibility:private"], deps = [ "//cmd:go_default_library", "//pkg/spanner:go_default_library", ], ) go_binary( name = "wrench", embed = [":go_default_library"], visibility = ["//visibility:public"], )

Slide 36

Slide 36 text

36 > ./bazel-bin/darwin_amd64_stripped/wrench help Usage: wrench [command] ...

Slide 37

Slide 37 text

Bake Docker Image 37 https://github.com/bazelbuild/rules_docker

Slide 38

Slide 38 text

Bake Docker Image 38

Slide 39

Slide 39 text

Bake Docker Image 39 load( "@io_bazel_rules_docker//go:image.bzl", "go_image", ) go_image( name = "image", embed = [":go_default_library"], )

Slide 40

Slide 40 text

Bake Docker Image 40 bazel build \ --platforms=\ @io_bazel_rules_go//go/toolchain:linux_amd64 \ //:image

Slide 41

Slide 41 text

Bake Docker Image 41 > ./bazel-bin/image help Loaded image ID: sha256:xxx Tagging xxx as bazel:image Usage: wrench [command] ...

Slide 42

Slide 42 text

Bake Docker Image 42 Dockerfile LESS

Slide 43

Slide 43 text

Bake Docker Image 43 Push to Registry load( "@io_bazel_rules_docker//container:container.bzl", "container_push", ) container_push( name = "registry", format = "Docker", image = ":image", registry = "index.docker.io", repository = "mercari/wrench", tag = version, )

Slide 44

Slide 44 text

Bake Docker Image 44

Slide 45

Slide 45 text

Agenda 45 ɾWhat is Bazel ɾHow to use for Go ɾTips

Slide 46

Slide 46 text

Tips 46 ɾExtract dependencies ɾnogo ɾRemote Caching

Slide 47

Slide 47 text

Tips 47 ɾExtract dependencies ɾnogo ɾRemote Caching

Slide 48

Slide 48 text

48 go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", version = "v0.0.0-20190523083050-ea95bdfd59fc", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) go_repository( name = "com_github_burntsushi_xgb", importpath = "github.com/BurntSushi/xgb", sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=", version = "v0.0.0-20160522181843-27f122750802", ) ... Extract Dependencies WORKSPACE

Slide 49

Slide 49 text

49 Extract Dependencies > bazel run //:gazelle -- \ update-repos \ -from_file go.mod \ -to_macro bazel/deps.bzl%wrench_deps

Slide 50

Slide 50 text

50 ᵓ── BUILD.bazel ᵓ── WORKSPACE ᵓ── bazel │ ᵓ── deps.bzl ᵓ── cmd │ ᵓ── BUILD.bazel │ ᵓ── apply.go │ └── ... ᵓ── main.go └── ... BUILD Extract Dependencies

Slide 51

Slide 51 text

51 load("@bazel_gazelle//:deps.bzl", "go_repository") def wrench_deps(): go_repository( name = "co_honnef_go_tools", importpath = "honnef.co/go/tools", sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=", version = "v0.0.0-20190523083050-ea95bdfd59fc", ) go_repository( name = "com_github_burntsushi_toml", importpath = "github.com/BurntSushi/toml", sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=", version = "v0.3.1", ) Extract Dependencies

Slide 52

Slide 52 text

Tips 52 ɾExtract dependencies ɾnogo ɾRemote Caching

Slide 53

Slide 53 text

nogo (experimental) 53 nogo is a tool that analyzes the source code of Go programs. It runs alongside the Go compiler in the Bazel Go rules and rejects programs that contain disallowed coding patterns. In addition, nogo may report compiler-like errors. https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst

Slide 54

Slide 54 text

nogo (experimental) 54 nogo( name = "nogo", visibility = ["//visibility:public"], deps = [ "@org_golang_x_tools//go/analysis/passes/atomic:go_tool_library", "@org_golang_x_tools//go/analysis/passes/bools:go_tool_library", "@org_golang_x_tools//go/analysis/passes/buildtag:go_tool_library", "@org_golang_x_tools//go/analysis/passes/nilfunc:go_tool_library", "@org_golang_x_tools//go/analysis/passes/printf:go_tool_library", "@org_golang_x_tools//go/analysis/passes/structtag:go_tool_library", ], )

Slide 55

Slide 55 text

Tips 55 ɾExtract dependencies ɾnogo ɾRemote Caching

Slide 56

Slide 56 text

Remote Caching 56 # ☁ Developers CI Cache

Slide 57

Slide 57 text

Remote Caching 57 ɾNginx ɾbazel-remote ɾGoogle Cloud Storage

Slide 58

Slide 58 text

Remote Caching 58 bazel-remote bazel-remote is a HTTP/1.1 and gRPC server that is intended to be used as a remote build cache for Bazel. The cache contents are stored in a directory on disk.

Slide 59

Slide 59 text

Remote Caching 59 Google Cloud Storage # Developers CI Cache

Slide 60

Slide 60 text

Remote Caching 60 Google Cloud Storage resource "google_storage_bucket" "bazel-cache" { name = "my-bazel-remote-cache" location = "asia-northeast1" storage_class = "STANDARD" }

Slide 61

Slide 61 text

Remote Caching 61 Google Cloud Storage resource "google_storage_bucket" "bazel-cache" { name = "my-bazel-remote-cache" location = "asia-northeast1" storage_class = "STANDARD" } ᶃ Create GCS Bucket

Slide 62

Slide 62 text

Remote Caching 62 Google Cloud Storage ᶄ Specify Remote Bucket bazel build \ --google_credentials= \ --remote_http_cache=https://storage.googleapis.com/ \ //:image

Slide 63

Slide 63 text

Agenda 63 ɾWhat is Bazel ɾHow to use for Go ɾTips