1- # Copyright 2018 The Prometheus Authors
1+ # Copyright The Prometheus Authors
22# Licensed under the Apache License, Version 2.0 (the "License");
33# you may not use this file except in compliance with the License.
44# You may obtain a copy of the License at
@@ -55,13 +55,13 @@ ifneq ($(shell command -v gotestsum 2> /dev/null),)
5555endif
5656endif
5757
58- PROMU_VERSION ?= 0.17 .0
58+ PROMU_VERSION ?= 0.18 .0
5959PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
6060
6161SKIP_GOLANGCI_LINT :=
6262GOLANGCI_LINT :=
6363GOLANGCI_LINT_OPTS ?=
64- GOLANGCI_LINT_VERSION ?= v2.6.0
64+ GOLANGCI_LINT_VERSION ?= v2.10.1
6565GOLANGCI_FMT_OPTS ?=
6666# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
6767# windows isn't included here because of the path separator being different.
@@ -82,11 +82,50 @@ endif
8282PREFIX ?= $(shell pwd)
8383BIN_DIR ?= $(shell pwd)
8484DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
85- DOCKERFILE_PATH ?= ./Dockerfile
8685DOCKERBUILD_CONTEXT ?= ./
8786DOCKER_REPO ?= prom
8887
88+ # Check if deprecated DOCKERFILE_PATH is set
89+ ifdef DOCKERFILE_PATH
90+ $(error DOCKERFILE_PATH is deprecated. Use DOCKERFILE_VARIANTS ?= $(DOCKERFILE_PATH) in the Makefile)
91+ endif
92+
8993DOCKER_ARCHS ?= amd64
94+ DOCKERFILE_VARIANTS ?= Dockerfile $(wildcard Dockerfile.*)
95+
96+ # Function to extract variant from Dockerfile label.
97+ # Returns the variant name from io.prometheus.image.variant label, or "default" if not found.
98+ define dockerfile_variant
99+ $(strip $(or $(shell sed -n 's/.*io\.prometheus\.image\.variant="\([^"]*\)".*/\1/p' $(1)),default))
100+ endef
101+
102+ # Check for duplicate variant names (including default for Dockerfiles without labels).
103+ DOCKERFILE_VARIANT_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)))
104+ DOCKERFILE_VARIANT_NAMES_SORTED := $(sort $(DOCKERFILE_VARIANT_NAMES))
105+ ifneq ($(words $(DOCKERFILE_VARIANT_NAMES)),$(words $(DOCKERFILE_VARIANT_NAMES_SORTED)))
106+ $(error Duplicate variant names found. Each Dockerfile must have a unique io.prometheus.image.variant label, and only one can be without a label (default))
107+ endif
108+
109+ # Build variant:dockerfile pairs for shell iteration.
110+ DOCKERFILE_VARIANTS_WITH_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)):$(df))
111+
112+ # Shell helper to check whether a dockerfile/arch pair is excluded.
113+ define dockerfile_arch_is_excluded
114+ case " $(DOCKERFILE_ARCH_EXCLUSIONS) " in \
115+ *" $$dockerfile:$(1) "*) true ;; \
116+ *) false ;; \
117+ esac
118+ endef
119+
120+ # Shell helper to check whether a registry/arch pair is excluded.
121+ # Extracts registry from DOCKER_REPO (e.g., quay.io/prometheus -> quay.io)
122+ define registry_arch_is_excluded
123+ registry=$$(echo "$(DOCKER_REPO)" | cut -d'/' -f1); \
124+ case " $(DOCKER_REGISTRY_ARCH_EXCLUSIONS) " in \
125+ *" $$registry:$(1) "*) true ;; \
126+ *) false ;; \
127+ esac
128+ endef
90129
91130BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS))
92131PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS))
@@ -129,6 +168,12 @@ common-check_license:
129168 echo "license header checking failed:"; echo "$${licRes}"; \
130169 exit 1; \
131170 fi
171+ @echo ">> checking for copyright years 2026 or later"
172+ @futureYearRes=$$(git grep -E 'Copyright (202[6-9]|20[3-9][0-9])' -- '*.go' ':!:vendor/*' || true); \
173+ if [ -n "$${futureYearRes}" ]; then \
174+ echo "Files with copyright year 2026 or later found (should use 'Copyright The Prometheus Authors'):"; echo "$${futureYearRes}"; \
175+ exit 1; \
176+ fi
132177
133178.PHONY: common-deps
134179common-deps:
@@ -220,28 +265,194 @@ common-docker-repo-name:
220265.PHONY: common-docker $(BUILD_DOCKER_ARCHS)
221266common-docker: $(BUILD_DOCKER_ARCHS)
222267$(BUILD_DOCKER_ARCHS): common-docker-%:
223- docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \
224- -f $(DOCKERFILE_PATH) \
225- --build-arg ARCH="$*" \
226- --build-arg OS="linux" \
227- $(DOCKERBUILD_CONTEXT)
268+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
269+ dockerfile=$${variant#*:}; \
270+ variant_name=$${variant%%:*}; \
271+ if $(call dockerfile_arch_is_excluded,$*); then \
272+ echo "Skipping $$variant_name variant for linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
273+ continue; \
274+ fi; \
275+ distroless_arch="$*"; \
276+ if [ "$*" = "armv7" ]; then \
277+ distroless_arch="arm"; \
278+ fi; \
279+ if [ "$$dockerfile" = "Dockerfile" ]; then \
280+ echo "Building default variant ($$variant_name) for linux-$* using $$dockerfile"; \
281+ docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \
282+ -f $$dockerfile \
283+ --build-arg ARCH="$*" \
284+ --build-arg OS="linux" \
285+ --build-arg DISTROLESS_ARCH="$$distroless_arch" \
286+ $(DOCKERBUILD_CONTEXT); \
287+ if [ "$$variant_name" != "default" ]; then \
288+ echo "Tagging default variant with $$variant_name suffix"; \
289+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \
290+ "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
291+ fi; \
292+ else \
293+ echo "Building $$variant_name variant for linux-$* using $$dockerfile"; \
294+ docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" \
295+ -f $$dockerfile \
296+ --build-arg ARCH="$*" \
297+ --build-arg OS="linux" \
298+ --build-arg DISTROLESS_ARCH="$$distroless_arch" \
299+ $(DOCKERBUILD_CONTEXT); \
300+ fi; \
301+ done
228302
229303.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS)
230304common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
231305$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
232- docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)"
306+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
307+ dockerfile=$${variant#*:}; \
308+ variant_name=$${variant%%:*}; \
309+ if $(call dockerfile_arch_is_excluded,$*); then \
310+ echo "Skipping push for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
311+ continue; \
312+ fi; \
313+ if $(call registry_arch_is_excluded,$*); then \
314+ echo "Skipping push for $$variant_name variant on linux-$* to $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
315+ continue; \
316+ fi; \
317+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
318+ echo "Pushing $$variant_name variant for linux-$*"; \
319+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
320+ fi; \
321+ if [ "$$dockerfile" = "Dockerfile" ]; then \
322+ echo "Pushing default variant ($$variant_name) for linux-$*"; \
323+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)"; \
324+ fi; \
325+ if [ "$(DOCKER_IMAGE_TAG)" = "latest" ]; then \
326+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
327+ echo "Pushing $$variant_name variant version tags for linux-$*"; \
328+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
329+ fi; \
330+ if [ "$$dockerfile" = "Dockerfile" ]; then \
331+ echo "Pushing default variant version tag for linux-$*"; \
332+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"; \
333+ fi; \
334+ fi; \
335+ done
233336
234337DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION)))
235338.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS)
236339common-docker-tag-latest: $(TAG_DOCKER_ARCHS)
237340$(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
238- docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"
239- docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"
341+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
342+ dockerfile=$${variant#*:}; \
343+ variant_name=$${variant%%:*}; \
344+ if $(call dockerfile_arch_is_excluded,$*); then \
345+ echo "Skipping tag for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
346+ continue; \
347+ fi; \
348+ if $(call registry_arch_is_excluded,$*); then \
349+ echo "Skipping tag for $$variant_name variant on linux-$* for $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
350+ continue; \
351+ fi; \
352+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
353+ echo "Tagging $$variant_name variant for linux-$* as latest"; \
354+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest-$$variant_name"; \
355+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
356+ fi; \
357+ if [ "$$dockerfile" = "Dockerfile" ]; then \
358+ echo "Tagging default variant ($$variant_name) for linux-$* as latest"; \
359+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"; \
360+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"; \
361+ fi; \
362+ done
240363
241364.PHONY: common-docker-manifest
242365common-docker-manifest:
243- DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(SANITIZED_DOCKER_IMAGE_TAG))
244- DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)"
366+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
367+ dockerfile=$${variant#*:}; \
368+ variant_name=$${variant%%:*}; \
369+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
370+ echo "Creating manifest for $$variant_name variant"; \
371+ refs=""; \
372+ for arch in $(DOCKER_ARCHS); do \
373+ if $(call dockerfile_arch_is_excluded,$$arch); then \
374+ echo " Skipping $$arch for $$variant_name (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
375+ continue; \
376+ fi; \
377+ if $(call registry_arch_is_excluded,$$arch); then \
378+ echo " Skipping $$arch for $$variant_name on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
379+ continue; \
380+ fi; \
381+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
382+ done; \
383+ if [ -z "$$refs" ]; then \
384+ echo "Skipping manifest for $$variant_name variant (no supported architectures)"; \
385+ continue; \
386+ fi; \
387+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" $$refs; \
388+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
389+ fi; \
390+ if [ "$$dockerfile" = "Dockerfile" ]; then \
391+ echo "Creating default variant ($$variant_name) manifest"; \
392+ refs=""; \
393+ for arch in $(DOCKER_ARCHS); do \
394+ if $(call dockerfile_arch_is_excluded,$$arch); then \
395+ echo " Skipping $$arch for default variant (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
396+ continue; \
397+ fi; \
398+ if $(call registry_arch_is_excluded,$$arch); then \
399+ echo " Skipping $$arch for default variant on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
400+ continue; \
401+ fi; \
402+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)"; \
403+ done; \
404+ if [ -z "$$refs" ]; then \
405+ echo "Skipping default variant manifest (no supported architectures)"; \
406+ continue; \
407+ fi; \
408+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $$refs; \
409+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)"; \
410+ fi; \
411+ if [ "$(DOCKER_IMAGE_TAG)" = "latest" ]; then \
412+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
413+ echo "Creating manifest for $$variant_name variant version tag"; \
414+ refs=""; \
415+ for arch in $(DOCKER_ARCHS); do \
416+ if $(call dockerfile_arch_is_excluded,$$arch); then \
417+ echo " Skipping $$arch for $$variant_name version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
418+ continue; \
419+ fi; \
420+ if $(call registry_arch_is_excluded,$$arch); then \
421+ echo " Skipping $$arch for $$variant_name version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
422+ continue; \
423+ fi; \
424+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
425+ done; \
426+ if [ -z "$$refs" ]; then \
427+ echo "Skipping version-tag manifest for $$variant_name variant (no supported architectures)"; \
428+ continue; \
429+ fi; \
430+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name" $$refs; \
431+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
432+ fi; \
433+ if [ "$$dockerfile" = "Dockerfile" ]; then \
434+ echo "Creating default variant version tag manifest"; \
435+ refs=""; \
436+ for arch in $(DOCKER_ARCHS); do \
437+ if $(call dockerfile_arch_is_excluded,$$arch); then \
438+ echo " Skipping $$arch for default variant version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
439+ continue; \
440+ fi; \
441+ if $(call registry_arch_is_excluded,$$arch); then \
442+ echo " Skipping $$arch for default variant version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
443+ continue; \
444+ fi; \
445+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)"; \
446+ done; \
447+ if [ -z "$$refs" ]; then \
448+ echo "Skipping default variant version-tag manifest (no supported architectures)"; \
449+ continue; \
450+ fi; \
451+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)" $$refs; \
452+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)"; \
453+ fi; \
454+ fi; \
455+ done
245456
246457.PHONY: promu
247458promu: $(PROMU)
0 commit comments