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