1PREFIX ?= $(shell pwd) 2FILES_TO_FMT ?= $(shell find . -path ./vendor -prune -o -name '*.go' -print) 3 4DOCKER_IMAGE_REPO ?= quay.io/thanos/thanos 5DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))-$(shell date +%Y-%m-%d)-$(shell git rev-parse --short HEAD) 6DOCKER_CI_TAG ?= test 7 8# Ensure everything works even if GOPATH is not set, which is often the case. 9# The `go env GOPATH` will work for all cases for Go 1.8+. 10GOPATH ?= $(shell go env GOPATH) 11 12TMP_GOPATH ?= /tmp/thanos-go 13GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin 14GO111MODULE ?= on 15export GO111MODULE 16GOPROXY ?= https://proxy.golang.org 17export GOPROXY 18 19# Tools. 20EMBEDMD ?= $(GOBIN)/embedmd-$(EMBEDMD_VERSION) 21# v2.0.0 22EMBEDMD_VERSION ?= 97c13d6e41602fc6e397eb51c45f38069371a969 23LICHE ?= $(GOBIN)/liche-$(LICHE_VERSION) 24LICHE_VERSION ?= 2a2e6e56f6c615c17b2e116669c4cdb31b5453f3 25GOIMPORTS ?= $(GOBIN)/goimports-$(GOIMPORTS_VERSION) 26GOIMPORTS_VERSION ?= 9d4d845e86f14303813298ede731a971dd65b593 27PROMU ?= $(GOBIN)/promu-$(PROMU_VERSION) 28PROMU_VERSION ?= 9583e5a6448f97c6294dca72dd1d173e28f8d4a4 29PROTOC ?= $(GOBIN)/protoc-$(PROTOC_VERSION) 30PROTOC_VERSION ?= 3.4.0 31# v0.55.3 This needs to match with version in netlify.toml 32HUGO_VERSION ?= 993b84333cd75faa224d02618f312a0e96b53372 33HUGO ?= $(GOBIN)/hugo-$(HUGO_VERSION) 34# v3.1.1 35GOBINDATA_VERSION ?= a9c83481b38ebb1c4eb8f0168fd4b10ca1d3c523 36GOBINDATA ?= $(GOBIN)/go-bindata-$(GOBINDATA_VERSION) 37GIT ?= $(shell which git) 38 39GOLANGCILINT_VERSION ?= d2b1eea2c6171a1a1141a448a745335ce2e928a1 40GOLANGCILINT ?= $(GOBIN)/golangci-lint-$(GOLANGCILINT_VERSION) 41MISSPELL_VERSION ?= c0b55c8239520f6b5aa15a0207ca8b28027ba49e 42MISSPELL ?= $(GOBIN)/misspell-$(MISSPELL_VERSION) 43 44GOJSONTOYAML_VERSION ?= e8bd32d46b3d764bef60f12b3bada1c132c4be55 45GOJSONTOYAML ?= $(GOBIN)/gojsontoyaml-$(GOJSONTOYAML_VERSION) 46# v0.14.0 47JSONNET_VERSION ?= fbde25be2182caa4345b03f1532450911ac7d1f3 48JSONNET ?= $(GOBIN)/jsonnet-$(JSONNET_VERSION) 49JSONNET_BUNDLER_VERSION ?= efe0c9e864431e93d5c3376bd5931d0fb9b2a296 50JSONNET_BUNDLER ?= $(GOBIN)/jb-$(JSONNET_BUNDLER_VERSION) 51# Prometheus v2.14.0 52PROMTOOL_VERSION ?= edeb7a44cbf745f1d8be4ea6f215e79e651bfe19 53PROMTOOL ?= $(GOBIN)/promtool-$(PROMTOOL_VERSION) 54 55# Support gsed on OSX (installed via brew), falling back to sed. On Linux 56# systems gsed won't be installed, so will use sed as expected. 57SED ?= $(shell which gsed 2>/dev/null || which sed) 58 59MIXIN_ROOT ?= mixin 60THANOS_MIXIN ?= mixin/thanos 61JSONNET_VENDOR_DIR ?= mixin/vendor 62 63WEB_DIR ?= website 64WEBSITE_BASE_URL ?= https://thanos.io 65PUBLIC_DIR ?= $(WEB_DIR)/public 66ME ?= $(shell whoami) 67 68# E2e test deps. 69# Referenced by github.com/thanos-io/thanos/blob/master/docs/getting_started.md#prometheus 70 71# Limited prom version, because testing was not possible. This should fix it: https://github.com/thanos-io/thanos/issues/758 72PROM_VERSIONS ?= v2.4.3 v2.5.0 v2.8.1 v2.9.2 v2.13.0 73PROMS ?= $(GOBIN)/prometheus-v2.4.3 $(GOBIN)/prometheus-v2.5.0 $(GOBIN)/prometheus-v2.8.1 $(GOBIN)/prometheus-v2.9.2 $(GOBIN)/prometheus-v2.13.0 74 75ALERTMANAGER_VERSION ?= v0.20.0 76ALERTMANAGER ?= $(GOBIN)/alertmanager-$(ALERTMANAGER_VERSION) 77 78MINIO_SERVER_VERSION ?= RELEASE.2018-10-06T00-15-16Z 79MINIO_SERVER ?=$(GOBIN)/minio-$(MINIO_SERVER_VERSION) 80 81# fetch_go_bin_version downloads (go gets) the binary from specific version and installs it in $(GOBIN)/<bin>-<version> 82# arguments: 83# $(1): Install path. (e.g github.com/campoy/embedmd) 84# $(2): Tag or revision for checkout. 85# TODO(bwplotka): Move to just using modules, however make sure to not use or edit Thanos go.mod file! 86define fetch_go_bin_version 87 @mkdir -p $(GOBIN) 88 @mkdir -p $(TMP_GOPATH) 89 90 @echo ">> fetching $(1)@$(2) revision/version" 91 @if [ ! -d '$(TMP_GOPATH)/src/$(1)' ]; then \ 92 GOPATH='$(TMP_GOPATH)' GO111MODULE='off' go get -d -u '$(1)/...'; \ 93 else \ 94 CDPATH='' cd -- '$(TMP_GOPATH)/src/$(1)' && git fetch; \ 95 fi 96 @CDPATH='' cd -- '$(TMP_GOPATH)/src/$(1)' && git checkout -f -q '$(2)' 97 @echo ">> installing $(1)@$(2)" 98 @GOBIN='$(TMP_GOPATH)/bin' GOPATH='$(TMP_GOPATH)' GO111MODULE='off' go install '$(1)' 99 @mv -- '$(TMP_GOPATH)/bin/$(shell basename $(1))' '$(GOBIN)/$(shell basename $(1))-$(2)' 100 @echo ">> produced $(GOBIN)/$(shell basename $(1))-$(2)" 101 102endef 103 104define require_clean_work_tree 105 @git update-index -q --ignore-submodules --refresh 106 107 @if ! git diff-files --quiet --ignore-submodules --; then \ 108 echo >&2 "cannot $1: you have unstaged changes."; \ 109 git diff-files --name-status -r --ignore-submodules -- >&2; \ 110 echo >&2 "Please commit or stash them."; \ 111 exit 1; \ 112 fi 113 114 @if ! git diff-index --cached --quiet HEAD --ignore-submodules --; then \ 115 echo >&2 "cannot $1: your index contains uncommitted changes."; \ 116 git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2; \ 117 echo >&2 "Please commit or stash them."; \ 118 exit 1; \ 119 fi 120 121endef 122 123.PHONY: all 124all: format build 125 126# assets repacks all static assets into go file for easier deploy. 127.PHONY: assets 128assets: $(GOBINDATA) 129 @echo ">> deleting asset file" 130 @rm pkg/ui/bindata.go || true 131 @echo ">> writing assets" 132 @$(GOBINDATA) $(bindata_flags) -pkg ui -o pkg/ui/bindata.go -ignore '(.*\.map|bootstrap\.js|bootstrap-theme\.css|bootstrap\.css)' pkg/ui/templates/... pkg/ui/static/... 133 @go fmt ./pkg/ui 134 135 136# build builds Thanos binary using `promu`. 137.PHONY: build 138build: check-git deps $(PROMU) 139 @echo ">> building binaries $(GOBIN)" 140 @$(PROMU) build --prefix $(PREFIX) 141 142# crossbuild builds all binaries for all platforms. 143.PHONY: crossbuild 144crossbuild: $(PROMU) 145 @echo ">> crossbuilding all binaries" 146 $(PROMU) crossbuild -v 147 148# deps ensures fresh go.mod and go.sum. 149.PHONY: deps 150deps: 151 @go mod tidy 152 @go mod verify 153 154# docker builds docker with no tag. 155.PHONY: docker 156docker: build 157 @echo ">> building docker image 'thanos'" 158 @docker build -t "thanos" . 159 160#docker-multi-stage builds docker image using multi-stage. 161.PHONY: docker-multi-stage 162docker-multi-stage: 163 @echo ">> building docker image 'thanos' with Dockerfile.multi-stage" 164 @docker build -f Dockerfile.multi-stage -t "thanos" . 165 166# docker-push pushes docker image build under `thanos` to "$(DOCKER_IMAGE_REPO):$(DOCKER_IMAGE_TAG)" 167.PHONY: docker-push 168docker-push: 169 @echo ">> pushing image" 170 @docker tag "thanos" "$(DOCKER_IMAGE_REPO):$(DOCKER_IMAGE_TAG)" 171 @docker push "$(DOCKER_IMAGE_REPO):$(DOCKER_IMAGE_TAG)" 172 173# docs regenerates flags in docs for all thanos commands. 174.PHONY: docs 175docs: $(EMBEDMD) build 176 @EMBEDMD_BIN="$(EMBEDMD)" SED_BIN="$(SED)" scripts/genflagdocs.sh 177 @find . -type f -name "*.md" | SED_BIN="$(SED)" xargs scripts/cleanup-white-noise.sh 178 179# check-docs checks: 180# - discrepancy with flags is valid 181# - links are valid 182# - white noise 183.PHONY: check-docs 184check-docs: $(EMBEDMD) $(LICHE) build 185 @EMBEDMD_BIN="$(EMBEDMD)" SED_BIN="$(SED)" scripts/genflagdocs.sh check 186 @$(LICHE) --recursive docs --exclude "(couchdb.apache.org/bylaws.html|cloud.tencent.com|alibabacloud.com)" --document-root . 187 @$(LICHE) --exclude "goreportcard.com" --document-root . *.md 188 @find . -type f -name "*.md" | SED_BIN="$(SED)" xargs scripts/cleanup-white-noise.sh 189 $(call require_clean_work_tree,"check documentation") 190 191# checks Go code comments if they have trailing period (excludes protobuffers and vendor files). 192# Comments with more than 3 spaces at beginning are omitted from the check, example: '// - foo'. 193.PHONY: check-comments 194check-comments: 195 @printf ">> checking Go comments trailing periods\n\n\n" 196 @./scripts/build-check-comments.sh 197 198# format the code: 199# - format code (including imports format) 200# - clean up all white noise 201.PHONY: format 202format: $(GOIMPORTS) check-comments 203 @echo ">> formatting code" 204 @$(GOIMPORTS) -w $(FILES_TO_FMT) 205 @SED_BIN="$(SED)" scripts/cleanup-white-noise.sh $(FILES_TO_FMT) 206 207# proto generates golang files from Thanos proto files. 208.PHONY: proto 209proto: check-git $(GOIMPORTS) $(PROTOC) 210 @GOIMPORTS_BIN="$(GOIMPORTS)" PROTOC_BIN="$(PROTOC)" scripts/genproto.sh 211 212.PHONY: promu 213promu: $(PROMU) 214 215.PHONY: tarballs-release 216tarballs-release: $(PROMU) 217 @echo ">> Publishing tarballs" 218 $(PROMU) crossbuild -v tarballs 219 $(PROMU) checksum -v .tarballs 220 $(PROMU) release -v .tarballs 221 222# test runs all Thanos golang tests against each supported version of Prometheus. 223.PHONY: test 224test: export GOCACHE= $(TMP_GOPATH)/gocache 225test: export THANOS_TEST_MINIO_PATH= $(MINIO_SERVER) 226test: export THANOS_TEST_PROMETHEUS_VERSIONS= $(PROM_VERSIONS) 227test: export THANOS_TEST_ALERTMANAGER_PATH= $(ALERTMANAGER) 228test: check-git install-deps 229 @echo ">> install thanos GOOPTS=${GOOPTS}" 230 # Thanos binary is required by e2e tests. 231 @go install github.com/thanos-io/thanos/cmd/thanos 232 # Be careful on GOCACHE. Those tests are sometimes using built Thanos/Prometheus binaries directly. Don't cache those. 233 @rm -rf ${GOCACHE} 234 @echo ">> running all tests. Do export THANOS_TEST_OBJSTORE_SKIP=GCS,S3,AZURE,SWIFT,COS,ALIYUNOSS if you want to skip e2e tests against all real store buckets. Current value: ${THANOS_TEST_OBJSTORE_SKIP}" 235 @go test $(shell go list ./... | grep -v /vendor/); 236 237.PHONY: test-ci 238test-ci: export THANOS_TEST_OBJSTORE_SKIP=AZURE,SWIFT,COS,ALIYUNOSS 239test-ci: 240 @echo ">> Skipping ${THANOS_TEST_OBJSTORE_SKIP} tests" 241 $(MAKE) test 242 243.PHONY: test-local 244test-local: export THANOS_TEST_OBJSTORE_SKIP=GCS,S3,AZURE,SWIFT,COS,ALIYUNOSS 245test-local: 246 $(MAKE) test 247 248# install-deps installs dependencies for e2e tetss. 249# It installs supported versions of Prometheus and alertmanager to test against in e2e. 250.PHONY: install-deps 251install-deps: $(ALERTMANAGER) $(MINIO_SERVER) $(PROMS) 252 @echo ">>GOBIN=$(GOBIN)" 253 254.PHONY: docker-ci 255# To be run by Thanos maintainer. 256docker-ci: install-deps 257 # Copy all to tmp local dir as this is required by docker. 258 @rm -rf ./tmp/bin 259 @mkdir -p ./tmp/bin 260 @cp -r $(GOBIN)/* ./tmp/bin 261 @docker build -t thanos-ci -f Dockerfile.thanos-ci . 262 @echo ">> pushing thanos-ci image" 263 @docker tag "thanos-ci" "quay.io/thanos/thanos-ci:$(DOCKER_CI_TAG)" 264 @docker push "quay.io/thanos/thanos-ci:$(DOCKER_CI_TAG)" 265 266# tooling deps. TODO(bwplotka): Pin them all to certain version! 267.PHONY: check-git 268check-git: 269ifneq ($(GIT),) 270 @test -x $(GIT) || (echo >&2 "No git executable binary found at $(GIT)."; exit 1) 271else 272 @echo >&2 "No git binary found."; exit 1 273endif 274 275.PHONY: web-pre-process 276web-pre-process: 277 @echo ">> running documentation website pre processing" 278 @bash scripts/websitepreprocess.sh 279 280.PHONY: web 281web: web-pre-process $(HUGO) 282 @echo ">> building documentation website" 283 # TODO(bwplotka): Make it --gc 284 @cd $(WEB_DIR) && HUGO_ENV=production $(HUGO) --config hugo.yaml --minify -v -b $(WEBSITE_BASE_URL) 285 286.PHONY: lint 287# PROTIP: 288# Add 289# --cpu-profile-path string Path to CPU profile output file 290# --mem-profile-path string Path to memory profile output file 291# 292# to debug big allocations during linting. 293lint: check-git $(GOLANGCILINT) $(MISSPELL) 294 @echo ">> examining all of the Go files" 295 @go vet -stdmethods=false ./pkg/... ./cmd/... && go vet doc.go 296 @echo ">> linting all of the Go files GOGC=${GOGC}" 297 @$(GOLANGCILINT) run 298 @echo ">> detecting misspells" 299 @find . -type f | grep -v vendor/ | grep -vE '\./\..*' | xargs $(MISSPELL) -error 300 @echo ">> detecting white noise" 301 @find . -type f \( -name "*.md" -o -name "*.go" \) | SED_BIN="$(SED)" xargs scripts/cleanup-white-noise.sh 302 $(call require_clean_work_tree,"detected white noise") 303 @echo ">> ensuring Copyright headers" 304 @go run ./scripts/copyright 305 $(call require_clean_work_tree,"detected files without copyright") 306 307.PHONY: web-serve 308web-serve: web-pre-process $(HUGO) 309 @echo ">> serving documentation website" 310 @cd $(WEB_DIR) && $(HUGO) --config hugo.yaml -v server 311 312# Check https://github.com/coreos/prometheus-operator/blob/master/scripts/jsonnet/Dockerfile for the image. 313JSONNET_CONTAINER_CMD:=docker run --rm \ 314 -u="$(shell id -u):$(shell id -g)" \ 315 -v "$(shell go env GOCACHE):/.cache/go-build" \ 316 -v "$(PWD):/go/src/github.com/thanos-io/thanos:Z" \ 317 -w "/go/src/github.com/thanos-io/thanos" \ 318 -e USER=deadbeef \ 319 -e GO111MODULE=on \ 320 quay.io/coreos/jsonnet-ci:release-0.36 321 322.PHONY: examples-in-container 323examples-in-container: 324 @echo ">> Compiling and generating thanos-mixin" 325 $(JSONNET_CONTAINER_CMD) make $(MFLAGS) JSONNET_BUNDLER='/go/bin/jb' jsonnet-vendor 326 $(JSONNET_CONTAINER_CMD) make $(MFLAGS) \ 327 EMBEDMD='/go/bin/embedmd' \ 328 JSONNET='/go/bin/jsonnet' \ 329 JSONNET_BUNDLER='/go/bin/jb' \ 330 PROMTOOL='/go/bin/promtool' \ 331 GOJSONTOYAML='/go/bin/gojsontoyaml' \ 332 GOLANGCILINT='/go/bin/golangci-lint' \ 333 examples 334 335.PHONY: examples 336examples: jsonnet-format ${THANOS_MIXIN}/README.md examples/alerts/alerts.md examples/alerts/alerts.yaml examples/alerts/rules.yaml examples/dashboards examples/tmp 337 $(EMBEDMD) -w examples/alerts/alerts.md 338 $(EMBEDMD) -w ${THANOS_MIXIN}/README.md 339 340.PHONY: examples/tmp 341examples/tmp: 342 -rm -rf examples/tmp/ 343 -mkdir -p examples/tmp/ 344 $(JSONNET) -J ${JSONNET_VENDOR_DIR} -m examples/tmp/ ${THANOS_MIXIN}/separated_alerts.jsonnet | xargs -I{} sh -c 'cat {} | $(GOJSONTOYAML) > {}.yaml; rm -f {}' -- {} 345 346.PHONY: examples/dashboards # to keep examples/dashboards/dashboards.md. 347examples/dashboards: $(JSONNET) ${THANOS_MIXIN}/mixin.libsonnet ${THANOS_MIXIN}/defaults.libsonnet ${THANOS_MIXIN}/dashboards/* 348 -rm -rf examples/dashboards/*.json 349 $(JSONNET) -J ${JSONNET_VENDOR_DIR} -m examples/dashboards ${THANOS_MIXIN}/dashboards.jsonnet 350 351examples/alerts/alerts.yaml: $(JSONNET) $(GOJSONTOYAML) ${THANOS_MIXIN}/mixin.libsonnet ${THANOS_MIXIN}/defaults.libsonnet ${THANOS_MIXIN}/alerts/* 352 $(JSONNET) ${THANOS_MIXIN}/alerts.jsonnet | $(GOJSONTOYAML) > $@ 353 354examples/alerts/rules.yaml: $(JSONNET) $(GOJSONTOYAML) ${THANOS_MIXIN}/mixin.libsonnet ${THANOS_MIXIN}/defaults.libsonnet ${THANOS_MIXIN}/rules/* 355 $(JSONNET) ${THANOS_MIXIN}/rules.jsonnet | $(GOJSONTOYAML) > $@ 356 357.PHONY: jsonnet-vendor 358jsonnet-vendor: $(JSONNET_BUNDLER) $(MIXIN_ROOT)/jsonnetfile.json $(MIXIN_ROOT)/jsonnetfile.lock.json 359 rm -rf ${JSONNET_VENDOR_DIR} 360 cd ${MIXIN_ROOT} && $(JSONNET_BUNDLER) install 361 362JSONNET_FMT := jsonnetfmt -n 2 --max-blank-lines 2 --string-style s --comment-style s 363 364.PHONY: jsonnet-format 365jsonnet-format: 366 @which jsonnetfmt 2>&1 >/dev/null || ( \ 367 echo "Cannot find jsonnetfmt command, please install from https://github.com/google/jsonnet/releases.\nIf your C++ does not support GLIBCXX_3.4.20, please use xxx-in-container target like jsonnet-format-in-container." \ 368 && exit 1) 369 find . -name 'vendor' -prune -o -name '*.libsonnet' -print -o -name '*.jsonnet' -print | \ 370 xargs -n 1 -- $(JSONNET_FMT) -i 371 372.PHONY: jsonnet-format-in-container 373jsonnet-format-in-container: 374 $(JSONNET_CONTAINER_CMD) make $(MFLAGS) jsonnet-format 375 376.PHONY: example-rules-lint 377example-rules-lint: $(PROMTOOL) examples/alerts/alerts.yaml examples/alerts/rules.yaml 378 $(PROMTOOL) check rules examples/alerts/alerts.yaml examples/alerts/rules.yaml 379 $(PROMTOOL) test rules examples/alerts/tests.yaml 380 381.PHONY: examples-clean 382examples-clean: 383 rm -f examples/alerts/alerts.yaml 384 rm -f examples/alerts/rules.yaml 385 rm -f examples/dashboards/*.json 386 rm -f examples/tmp/*.yaml 387 388# non-phony targets 389$(EMBEDMD): 390 $(call fetch_go_bin_version,github.com/campoy/embedmd,$(EMBEDMD_VERSION)) 391 392$(GOIMPORTS): 393 $(call fetch_go_bin_version,golang.org/x/tools/cmd/goimports,$(GOIMPORTS_VERSION)) 394 395$(LICHE): 396 $(call fetch_go_bin_version,github.com/raviqqe/liche,$(LICHE_VERSION)) 397 398$(PROMU): 399 $(call fetch_go_bin_version,github.com/prometheus/promu,$(PROMU_VERSION)) 400 401$(HUGO): 402 @go get github.com/gohugoio/hugo@$(HUGO_VERSION) 403 @mv $(GOBIN)/hugo $(HUGO) 404 @go mod tidy 405 406$(GOBINDATA): 407 $(call fetch_go_bin_version,github.com/go-bindata/go-bindata/go-bindata,$(GOBINDATA_VERSION)) 408 409$(GOLANGCILINT): 410 $(call fetch_go_bin_version,github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCILINT_VERSION)) 411 412$(MISSPELL): 413 $(call fetch_go_bin_version,github.com/client9/misspell/cmd/misspell,$(MISSPELL_VERSION)) 414 415$(ALERTMANAGER): 416 $(call fetch_go_bin_version,github.com/prometheus/alertmanager/cmd/alertmanager,$(ALERTMANAGER_VERSION)) 417 418$(MINIO_SERVER): 419 $(call fetch_go_bin_version,github.com/minio/minio,$(MINIO_SERVER_VERSION)) 420 421$(PROMS): 422 $(foreach ver,$(PROM_VERSIONS),$(call fetch_go_bin_version,github.com/prometheus/prometheus/cmd/prometheus,$(ver))) 423 424$(PROTOC): 425 @mkdir -p $(TMP_GOPATH) 426 @echo ">> fetching protoc@${PROTOC_VERSION}" 427 @PROTOC_VERSION="$(PROTOC_VERSION)" TMP_GOPATH="$(TMP_GOPATH)" scripts/installprotoc.sh 428 @echo ">> installing protoc@${PROTOC_VERSION}" 429 @mv -- "$(TMP_GOPATH)/bin/protoc" "$(GOBIN)/protoc-$(PROTOC_VERSION)" 430 @echo ">> produced $(GOBIN)/protoc-$(PROTOC_VERSION)" 431 432$(JSONNET): 433 $(call fetch_go_bin_version,github.com/google/go-jsonnet/cmd/jsonnet,$(JSONNET_VERSION)) 434 435$(GOJSONTOYAML): 436 $(call fetch_go_bin_version,github.com/brancz/gojsontoyaml,$(GOJSONTOYAML_VERSION)) 437 438$(JSONNET_BUNDLER): 439 $(call fetch_go_bin_version,github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb,$(JSONNET_BUNDLER_VERSION)) 440 441$(PROMTOOL): 442 $(call fetch_go_bin_version,github.com/prometheus/prometheus/cmd/promtool,$(PROMTOOL_VERSION)) 443