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.1
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.2
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,52 @@ 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
89- DOCKER_ARCHS ?= amd64
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+
93+ DOCKER_ARCHS ?= amd64 armv7 arm64 ppc64le riscv64 s390x
94+ DOCKERFILE_ARCH_EXCLUSIONS ?=
95+ DOCKER_REGISTRY_ARCH_EXCLUSIONS ?= quay.io:riscv64
96+ DOCKERFILE_VARIANTS ?= $(wildcard Dockerfile Dockerfile.*)
97+
98+ # Function to extract variant from Dockerfile label.
99+ # Returns the variant name from io.prometheus.image.variant label, or "default" if not found.
100+ define dockerfile_variant
101+ $(strip $(or $(shell sed -n 's/.*io\.prometheus\.image\.variant="\([^"]*\)".*/\1/p' $(1)),default))
102+ endef
103+
104+ # Check for duplicate variant names (including default for Dockerfiles without labels).
105+ DOCKERFILE_VARIANT_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)))
106+ DOCKERFILE_VARIANT_NAMES_SORTED := $(sort $(DOCKERFILE_VARIANT_NAMES))
107+ ifneq ($(words $(DOCKERFILE_VARIANT_NAMES)),$(words $(DOCKERFILE_VARIANT_NAMES_SORTED)))
108+ $(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))
109+ endif
110+
111+ # Build variant:dockerfile pairs for shell iteration.
112+ DOCKERFILE_VARIANTS_WITH_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)):$(df))
113+
114+ # Shell helper to check whether a dockerfile/arch pair is excluded.
115+ define dockerfile_arch_is_excluded
116+ case " $(DOCKERFILE_ARCH_EXCLUSIONS) " in \
117+ *" $$dockerfile:$(1) "*) true ;; \
118+ *) false ;; \
119+ esac
120+ endef
121+
122+ # Shell helper to check whether a registry/arch pair is excluded.
123+ # Extracts registry from DOCKER_REPO (e.g., quay.io/prometheus -> quay.io)
124+ define registry_arch_is_excluded
125+ registry=$$(echo "$(DOCKER_REPO)" | cut -d'/' -f1); \
126+ case " $(DOCKER_REGISTRY_ARCH_EXCLUSIONS) " in \
127+ *" $$registry:$(1) "*) true ;; \
128+ *) false ;; \
129+ esac
130+ endef
90131
91132BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS))
92133PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS))
@@ -129,6 +170,12 @@ common-check_license:
129170 echo "license header checking failed:"; echo "$${licRes}"; \
130171 exit 1; \
131172 fi
173+ @echo ">> checking for copyright years 2026 or later"
174+ @futureYearRes=$$(git grep -E 'Copyright (202[6-9]|20[3-9][0-9])' -- '*.go' ':!:vendor/*' || true); \
175+ if [ -n "$${futureYearRes}" ]; then \
176+ echo "Files with copyright year 2026 or later found (should use 'Copyright The Prometheus Authors'):"; echo "$${futureYearRes}"; \
177+ exit 1; \
178+ fi
132179
133180.PHONY: common-deps
134181common-deps:
@@ -220,28 +267,194 @@ common-docker-repo-name:
220267.PHONY: common-docker $(BUILD_DOCKER_ARCHS)
221268common-docker: $(BUILD_DOCKER_ARCHS)
222269$(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)
270+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
271+ dockerfile=$${variant#*:}; \
272+ variant_name=$${variant%%:*}; \
273+ if $(call dockerfile_arch_is_excluded,$*); then \
274+ echo "Skipping $$variant_name variant for linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
275+ continue; \
276+ fi; \
277+ distroless_arch="$*"; \
278+ if [ "$*" = "armv7" ]; then \
279+ distroless_arch="arm"; \
280+ fi; \
281+ if [ "$$dockerfile" = "Dockerfile" ]; then \
282+ echo "Building default variant ($$variant_name) for linux-$* using $$dockerfile"; \
283+ docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \
284+ -f $$dockerfile \
285+ --build-arg ARCH="$*" \
286+ --build-arg OS="linux" \
287+ --build-arg DISTROLESS_ARCH="$$distroless_arch" \
288+ $(DOCKERBUILD_CONTEXT); \
289+ if [ "$$variant_name" != "default" ]; then \
290+ echo "Tagging default variant with $$variant_name suffix"; \
291+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \
292+ "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
293+ fi; \
294+ else \
295+ echo "Building $$variant_name variant for linux-$* using $$dockerfile"; \
296+ docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" \
297+ -f $$dockerfile \
298+ --build-arg ARCH="$*" \
299+ --build-arg OS="linux" \
300+ --build-arg DISTROLESS_ARCH="$$distroless_arch" \
301+ $(DOCKERBUILD_CONTEXT); \
302+ fi; \
303+ done
228304
229305.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS)
230306common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
231307$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
232- docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)"
308+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
309+ dockerfile=$${variant#*:}; \
310+ variant_name=$${variant%%:*}; \
311+ if $(call dockerfile_arch_is_excluded,$*); then \
312+ echo "Skipping push for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
313+ continue; \
314+ fi; \
315+ if $(call registry_arch_is_excluded,$*); then \
316+ echo "Skipping push for $$variant_name variant on linux-$* to $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
317+ continue; \
318+ fi; \
319+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
320+ echo "Pushing $$variant_name variant for linux-$*"; \
321+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
322+ fi; \
323+ if [ "$$dockerfile" = "Dockerfile" ]; then \
324+ echo "Pushing default variant ($$variant_name) for linux-$*"; \
325+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)"; \
326+ fi; \
327+ if [ "$(DOCKER_IMAGE_TAG)" = "latest" ]; then \
328+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
329+ echo "Pushing $$variant_name variant version tags for linux-$*"; \
330+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
331+ fi; \
332+ if [ "$$dockerfile" = "Dockerfile" ]; then \
333+ echo "Pushing default variant version tag for linux-$*"; \
334+ docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"; \
335+ fi; \
336+ fi; \
337+ done
233338
234339DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION)))
235340.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS)
236341common-docker-tag-latest: $(TAG_DOCKER_ARCHS)
237342$(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)"
343+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
344+ dockerfile=$${variant#*:}; \
345+ variant_name=$${variant%%:*}; \
346+ if $(call dockerfile_arch_is_excluded,$*); then \
347+ echo "Skipping tag for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
348+ continue; \
349+ fi; \
350+ if $(call registry_arch_is_excluded,$*); then \
351+ echo "Skipping tag for $$variant_name variant on linux-$* for $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
352+ continue; \
353+ fi; \
354+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
355+ echo "Tagging $$variant_name variant for linux-$* as latest"; \
356+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest-$$variant_name"; \
357+ 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"; \
358+ fi; \
359+ if [ "$$dockerfile" = "Dockerfile" ]; then \
360+ echo "Tagging default variant ($$variant_name) for linux-$* as latest"; \
361+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"; \
362+ docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"; \
363+ fi; \
364+ done
240365
241366.PHONY: common-docker-manifest
242367common-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)"
368+ @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
369+ dockerfile=$${variant#*:}; \
370+ variant_name=$${variant%%:*}; \
371+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
372+ echo "Creating manifest for $$variant_name variant"; \
373+ refs=""; \
374+ for arch in $(DOCKER_ARCHS); do \
375+ if $(call dockerfile_arch_is_excluded,$$arch); then \
376+ echo " Skipping $$arch for $$variant_name (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
377+ continue; \
378+ fi; \
379+ if $(call registry_arch_is_excluded,$$arch); then \
380+ echo " Skipping $$arch for $$variant_name on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
381+ continue; \
382+ fi; \
383+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
384+ done; \
385+ if [ -z "$$refs" ]; then \
386+ echo "Skipping manifest for $$variant_name variant (no supported architectures)"; \
387+ continue; \
388+ fi; \
389+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" $$refs; \
390+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
391+ fi; \
392+ if [ "$$dockerfile" = "Dockerfile" ]; then \
393+ echo "Creating default variant ($$variant_name) manifest"; \
394+ refs=""; \
395+ for arch in $(DOCKER_ARCHS); do \
396+ if $(call dockerfile_arch_is_excluded,$$arch); then \
397+ echo " Skipping $$arch for default variant (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
398+ continue; \
399+ fi; \
400+ if $(call registry_arch_is_excluded,$$arch); then \
401+ echo " Skipping $$arch for default variant on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
402+ continue; \
403+ fi; \
404+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)"; \
405+ done; \
406+ if [ -z "$$refs" ]; then \
407+ echo "Skipping default variant manifest (no supported architectures)"; \
408+ continue; \
409+ fi; \
410+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $$refs; \
411+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)"; \
412+ fi; \
413+ if [ "$(DOCKER_IMAGE_TAG)" = "latest" ]; then \
414+ if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
415+ echo "Creating manifest for $$variant_name variant version tag"; \
416+ refs=""; \
417+ for arch in $(DOCKER_ARCHS); do \
418+ if $(call dockerfile_arch_is_excluded,$$arch); then \
419+ echo " Skipping $$arch for $$variant_name version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
420+ continue; \
421+ fi; \
422+ if $(call registry_arch_is_excluded,$$arch); then \
423+ echo " Skipping $$arch for $$variant_name version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
424+ continue; \
425+ fi; \
426+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
427+ done; \
428+ if [ -z "$$refs" ]; then \
429+ echo "Skipping version-tag manifest for $$variant_name variant (no supported architectures)"; \
430+ continue; \
431+ fi; \
432+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name" $$refs; \
433+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
434+ fi; \
435+ if [ "$$dockerfile" = "Dockerfile" ]; then \
436+ echo "Creating default variant version tag manifest"; \
437+ refs=""; \
438+ for arch in $(DOCKER_ARCHS); do \
439+ if $(call dockerfile_arch_is_excluded,$$arch); then \
440+ echo " Skipping $$arch for default variant version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
441+ continue; \
442+ fi; \
443+ if $(call registry_arch_is_excluded,$$arch); then \
444+ echo " Skipping $$arch for default variant version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
445+ continue; \
446+ fi; \
447+ refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)"; \
448+ done; \
449+ if [ -z "$$refs" ]; then \
450+ echo "Skipping default variant version-tag manifest (no supported architectures)"; \
451+ continue; \
452+ fi; \
453+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)" $$refs; \
454+ DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)"; \
455+ fi; \
456+ fi; \
457+ done
245458
246459.PHONY: promu
247460promu: $(PROMU)
0 commit comments