NAME := $(or $(NAME),$(NAME),selenium)
CURRENT_DATE := $(shell date '+%Y%m%d')
BUILD_DATE := $(or $(BUILD_DATE),$(BUILD_DATE),$(CURRENT_DATE))
BASE_RELEASE := $(or $(BASE_RELEASE),$(BASE_RELEASE),selenium-4.49.0)
BASE_VERSION := $(or $(BASE_VERSION),$(BASE_VERSION),4.49.0)
BINDING_VERSION := $(or $(BINDING_VERSION),$(BINDING_VERSION),4.49.0)
BASE_RELEASE_NIGHTLY := $(or $(BASE_RELEASE_NIGHTLY),$(BASE_RELEASE_NIGHTLY),nightly)
BASE_VERSION_NIGHTLY := $(or $(BASE_VERSION_NIGHTLY),$(BASE_VERSION_NIGHTLY),4.50.0-SNAPSHOT)
VERSION := $(or $(VERSION),$(VERSION),4.49.0)
MVN_SELENIUM_VERSION := $(or $(MVN_SELENIUM_VERSION),$(MVN_SELENIUM_VERSION),latest.release)
TAG_VERSION := $(VERSION)-$(BUILD_DATE)
CHART_VERSION_NIGHTLY := $(or $(CHART_VERSION_NIGHTLY),$(CHART_VERSION_NIGHTLY),1.0.0-nightly)
NAMESPACE := $(or $(NAMESPACE),$(NAMESPACE),$(NAME))
AUTHORS := $(or $(AUTHORS),$(AUTHORS),SeleniumHQ)
PUSH_IMAGE := $(or $(PUSH_IMAGE),$(PUSH_IMAGE),false)
RELEASE_OLD_VERSION := $(or $(RELEASE_OLD_VERSION),$(RELEASE_OLD_VERSION),false)
FROM_IMAGE_ARGS := --build-arg NAMESPACE=$(NAMESPACE) --build-arg VERSION=$(TAG_VERSION) --build-arg AUTHORS=$(AUTHORS) --sbom=true --attest type=provenance,mode=max
BUILD_ARGS := $(BUILD_ARGS) --progress plain
MAJOR := $(word 1,$(subst ., ,$(TAG_VERSION)))
MINOR := $(word 2,$(subst ., ,$(TAG_VERSION)))
MAJOR_MINOR_PATCH := $(word 1,$(subst -, ,$(TAG_VERSION)))
FFMPEG_VERSION := $(or $(FFMPEG_VERSION),$(FFMPEG_VERSION),8.1)
FFMPEG_TAG_PREV_VERSION := $(or $(FFMPEG_TAG_PREV_VERSION),$(FFMPEG_TAG_PREV_VERSION),ffmpeg-8.1)
FFMPEG_TAG_VERSION := $(or $(FFMPEG_TAG_VERSION),$(FFMPEG_TAG_VERSION),ffmpeg-8.1)
FFMPEG_BASED_NAME := $(or $(FFMPEG_BASED_NAME),$(FFMPEG_BASED_NAME),selenium)
FFMPEG_BASED_TAG := $(or $(FFMPEG_BASED_TAG),$(FFMPEG_BASED_TAG),latest)
CURRENT_PLATFORM := $(shell if [ `arch` = "aarch64" ] || [ `arch` = "arm64" ]; then echo "linux/arm64"; else echo "linux/amd64"; fi)
PLATFORMS := $(or $(PLATFORMS),$(shell echo $$PLATFORMS),$(CURRENT_PLATFORM))
SEL_PASSWD := $(or $(SEL_PASSWD),$(SEL_PASSWD),secret)
CHROMIUM_VERSION := $(or $(CHROMIUM_VERSION),$(CHROMIUM_VERSION),latest)
FIREFOX_DOWNLOAD_URL := $(or $(FIREFOX_DOWNLOAD_URL),$(FIREFOX_DOWNLOAD_URL),)
SBOM_OUTPUT := $(or $(SBOM_OUTPUT),$(SBOM_OUTPUT),package_versions.txt)
KEDA_TAG_PREV_VERSION := $(or $(KEDA_TAG_PREV_VERSION),$(KEDA_TAG_PREV_VERSION),2.20.1)
KEDA_CORE_VERSION := $(or $(KEDA_CORE_VERSION),$(KEDA_CORE_VERSION),2.20.1)
KEDA_TAG_VERSION := $(or $(KEDA_TAG_VERSION),$(KEDA_TAG_VERSION),2.20.1)
KEDA_BASED_NAME := $(or $(KEDA_BASED_NAME),$(KEDA_BASED_NAME),kedacore)
KEDA_BASED_TAG := $(or $(KEDA_BASED_TAG),$(KEDA_BASED_TAG),2.20.1)
TEST_PATCHED_KEDA := $(or $(TEST_PATCHED_KEDA),$(TEST_PATCHED_KEDA),false)
TRACING_EXPORTER_ENDPOINT := $(or $(TRACING_EXPORTER_ENDPOINT),$(TRACING_EXPORTER_ENDPOINT),http://\$$KUBERNETES_NODE_HOST_IP:4317)
GHCR_NAMESPACE := $(or $(GHCR_NAMESPACE),$(GHCR_NAMESPACE),ghcr.io/seleniumhq)

# --- CI image reuse -----------------------------------------------------------
#
# The PR test suite spans 37 matrix jobs and every one of them used to build the
# images it needed, because each test target names image targets as prerequisites
# (`test_video: video hub chrome firefox edge chromium`). Building once and
# reusing the result is worth ~36 redundant builds per pull request.
#
#   SKIP_BUILD=true   every image-build target becomes a no-op, so the test
#                     targets keep their prerequisites and need no edits. Use it
#                     only when the images are already present locally.
#   make push_ci_images / pull_ci_images   move that set through a registry.
#
# With SKIP_BUILD unset nothing below changes: `make build`, `make test` and every
# other local workflow behave exactly as before.

CI_REGISTRY := $(or $(CI_REGISTRY),ghcr.io/seleniumhq)
CI_TAG := $(or $(CI_TAG),main)

# The images a test run can need. Kept as one list so push and pull cannot drift.
CI_IMAGES := base hub distributor router sessions session-queue event-bus \
	node-base node-chrome node-chrome-for-testing node-chromium node-edge node-firefox \
	node-all-browsers node-docker node-kubernetes \
	standalone-chrome standalone-chrome-for-testing standalone-chromium standalone-edge \
	standalone-firefox standalone-all-browsers standalone-docker standalone-kubernetes \
	video keda-external-scaler

# Image-build targets, plus update_go. gen_certs and prepare_resources are
# deliberately absent: they produce working-tree files the tests read, not images,
# and must still run when the images come from a registry.
#
# update_go is here because it is a prerequisite of `base`, so it ran in every
# test job on the reuse path - a `docker pull golang:latest` plus `go get -u` and
# `go mod tidy` for two modules, over the network, in each of ~37 jobs. Nothing
# read at test time comes out of it: it edits go.mod/go.sum and rewrites the
# golang base image in .keda-external-scaler/, Hub/ and Router/ Dockerfiles, all
# of which matter only to a build. Leaving it in cost minutes per job, added a
# live-network flake to each one, and mutated hashed sources after the tag had
# already been decided.
# Overridable from the environment, not just as a make argument: the release
# needs `SKIP_BUILD=true SKIP_BUILD_TARGETS=base` to build the four tag-dependent
# images on top of the base it just published, and a plain `:=` here would
# silently ignore that and no-op the four as well.
SKIP_BUILD_TARGETS := $(or $(SKIP_BUILD_TARGETS),base hub distributor router sessions sessionqueue event_bus \
	node_base chrome chrome_only chrome-for-testing chrome-for-testing_only chromium \
	edge edge_only firefox firefox_only all_browsers docker kubernetes \
	standalone_chrome standalone_chrome_only standalone_chrome-for-testing \
	standalone_chrome-for-testing_only standalone_chromium standalone_edge \
	standalone_edge_only standalone_firefox standalone_firefox_only \
	standalone_all_browsers standalone_docker standalone_kubernetes \
	video ffmpeg keda_external_scaler update_go)

# Push what was just built, so the rest of the run can reuse it.
# video does not carry the grid tag: it is built as
# $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE), and the compose files read it
# from VIDEO_TAG. Assuming $(TAG_VERSION) for every image meant video was never
# found locally, silently skipped on push, and then missing at merge.
#
# Skips images this build did not produce. On an arm64 runner that is Edge and
# Chrome for Testing, which are amd64-only; without the check the loop would fail
# tagging an image that was correctly never built.
push_ci_images:
	@set -e; pushed=0; skipped=""; \
	for image in $(CI_IMAGES); do \
		case "$$image" in \
			video)  local_tag="$(FFMPEG_TAG_VERSION)-$(BUILD_DATE)" ;; \
			ffmpeg) local_tag="$(FFMPEG_VERSION)-$(BUILD_DATE)" ;; \
			*)      local_tag="$(TAG_VERSION)" ;; \
		esac; \
		if ! docker image inspect $(NAME)/$$image:$$local_tag >/dev/null 2>&1; then \
			skipped="$$skipped $$image"; continue; \
		fi; \
		echo "push $(CI_REGISTRY)/$$image:$(CI_TAG)"; \
		docker tag $(NAME)/$$image:$$local_tag $(CI_REGISTRY)/$$image:$(CI_TAG); \
		docker push --quiet $(CI_REGISTRY)/$$image:$(CI_TAG); \
		pushed=$$((pushed+1)); \
	done; \
	echo "pushed $$pushed image(s) as $(CI_TAG)"; \
	if [ -n "$$skipped" ]; then echo "not built here, skipped:$$skipped"; fi; \
		if [ "$$pushed" -eq 0 ]; then echo "nothing was pushed" >&2; exit 1; fi

# Pull the prebuilt set and give it the local names the compose files expect.
#
# Edge and Chrome for Testing are amd64-only, so on arm64 their manifest list has
# no matching entry and `docker pull` fails with "no matching manifest for
# linux/arm64/v8". Skip those deliberately, by inspecting the manifest first -
# and only those. An image missing from the registry entirely is still a hard
# error, because that means the build or the merge went wrong, and a clear
# failure here beats a compose failure fifteen minutes into a test job.
pull_ci_images:
	@set -e; arch=$$(docker version --format '{{.Server.Arch}}'); \
	echo "pulling for linux/$$arch"; \
	pulled=0; other_arch=""; \
	for image in $(CI_IMAGES); do \
		case "$$image" in \
			video)  local_tag="$(FFMPEG_TAG_VERSION)-$(BUILD_DATE)" ;; \
			ffmpeg) local_tag="$(FFMPEG_VERSION)-$(BUILD_DATE)" ;; \
			*)      local_tag="$(TAG_VERSION)" ;; \
		esac; \
		ref="$(CI_REGISTRY)/$$image:$(CI_TAG)"; \
		if ! manifest=$$(docker manifest inspect $$ref 2>/dev/null); then \
			echo "$$ref is not in the registry" >&2; exit 1; \
		fi; \
		if ! echo "$$manifest" | tr -d ' ' | grep -q "\"architecture\":\"$$arch\""; then \
			other_arch="$$other_arch $$image"; continue; \
		fi; \
		echo "pull $$ref -> $(NAME)/$$image:$$local_tag"; \
		docker pull --quiet --platform linux/$$arch $$ref; \
		docker tag $$ref $(NAME)/$$image:$$local_tag; \
		pulled=$$((pulled+1)); \
	done; \
	echo "pulled $$pulled image(s) for linux/$$arch"; \
	if [ -n "$$other_arch" ]; then echo "not built for linux/$$arch:$$other_arch"; fi; \
		if [ "$$pulled" -eq 0 ]; then echo "nothing was pulled" >&2; exit 1; fi

# Merge the per-architecture tags pushed by native runners into one manifest
# list. Building multi-arch on a single runner means QEMU-emulating arm64, which
# took over an hour; two native runners in parallel cost about one amd64 build.
#
# Edge and Chrome for Testing are amd64-only - the Makefile skips them when
# PLATFORMS has no linux/amd64 - so their arm64 tag never exists and the list is
# built from amd64 alone rather than failing.
merge_ci_images:
	@set -e; for image in $(CI_IMAGES); do \
		refs="" ; \
		for arch in amd64 arm64; do \
			if docker manifest inspect $(CI_REGISTRY)/$$image:$(CI_TAG)-$$arch >/dev/null 2>&1; then \
				refs="$$refs $(CI_REGISTRY)/$$image:$(CI_TAG)-$$arch" ; \
			fi ; \
		done ; \
		if [ -z "$$refs" ]; then echo "no architecture tags for $$image:$(CI_TAG)" ; exit 1 ; fi ; \
			echo "merge $$image:$(CI_TAG) <-$$refs" ; \
			docker buildx imagetools create -t $(CI_REGISTRY)/$$image:$(CI_TAG) $$refs ; \
		done

# The marker decide reuses on. Written only once merge_ci_images has finished
# every image, so "base:<tag> exists" can never be mistaken for "the whole set
# exists". It is a second tag on the manifest base:<tag> already is - no extra
# storage, and nothing for the cleanup to leak.
mark_ci_images_complete:
	docker buildx imagetools create -t $(CI_REGISTRY)/base:$(CI_TAG)-complete $(CI_REGISTRY)/base:$(CI_TAG)

# --- Release by promotion -----------------------------------------------------
#
# A release rebuilt every image the trunk suite had just built and tested, so
# what got published was a rebuild of the tested source rather than the tested
# artefact. Most images can be retagged instead.
#
# Most, not all. NodeDocker/config.toml and NodeKubernetes/config.toml name the
# exact standalone tags of the release being made -
#   "selenium/standalone-chrome:4.49.0-20260905"
# - and update_tag_in_docs_and_files.sh rewrites them as part of tagging. Those
# two images cannot exist before the tag does, nor can the two standalones built
# FROM them, so those four are still built at release time.
RELEASE_PROMOTED_IMAGES := base hub distributor router sessions session-queue event-bus \
	node-base node-chrome node-chrome-for-testing node-chromium node-edge node-firefox \
	node-all-browsers standalone-chrome standalone-chrome-for-testing standalone-chromium \
	standalone-edge standalone-firefox standalone-all-browsers keda-external-scaler

RELEASE_BUILT_IMAGES := node-docker node-kubernetes standalone-docker standalone-kubernetes

# Where a promotion lands. $(NAME) publishes to Docker Hub; pass
# $(GHCR_NAMESPACE) to mirror the same manifest there.
PROMOTE_NAMESPACE := $(or $(PROMOTE_NAMESPACE),$(NAME))

# Registry to registry, on the index. Nothing is pulled, so the multi-architecture
# manifest list arrives intact and the digest released is the digest tested.
# Pulling per architecture and pushing from the local store is what published
# single-architecture releases before.
promote_release_images:
	@set -e; for image in $(RELEASE_PROMOTED_IMAGES); do \
		echo "promote $$image -> $(PROMOTE_NAMESPACE)/$$image:$(TAG_VERSION)" ; \
		docker buildx imagetools create \
			--tag $(PROMOTE_NAMESPACE)/$$image:$(TAG_VERSION) \
			--tag $(PROMOTE_NAMESPACE)/$$image:$(MAJOR) \
			--tag $(PROMOTE_NAMESPACE)/$$image:$(MAJOR).$(MINOR) \
			--tag $(PROMOTE_NAMESPACE)/$$image:$(MAJOR_MINOR_PATCH) \
			$(CI_REGISTRY)/$$image:$(CI_TAG) ; \
	done
	docker buildx imagetools create \
		--tag $(PROMOTE_NAMESPACE)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) \
		$(CI_REGISTRY)/video:$(CI_TAG)

# Separate from the version tags, exactly as release_latest is separate from
# release: a prerelease publishes versions without moving :latest.
promote_release_latest:
	@set -e; for image in $(RELEASE_PROMOTED_IMAGES); do \
		echo "promote $$image -> $(PROMOTE_NAMESPACE)/$$image:latest" ; \
		docker buildx imagetools create --tag $(PROMOTE_NAMESPACE)/$$image:latest \
			$(CI_REGISTRY)/$$image:$(CI_TAG) ; \
	done
	docker buildx imagetools create --tag $(PROMOTE_NAMESPACE)/video:latest \
		$(CI_REGISTRY)/video:$(CI_TAG)

# The four the promotion cannot cover. Built after the tag rewrite, FROM the base
# image the promotion has just published, so they sit on the released base rather
# than on a second local build of it. That is what
#   SKIP_BUILD=true SKIP_BUILD_TARGETS=base
# buys: `docker` and `kubernetes` name base as a prerequisite, and without this
# make would rebuild it here and produce a different digest from the one released.
release_built_images:
	@set -e; for image in $(RELEASE_BUILT_IMAGES); do \
		for tag in $(MAJOR) $(MAJOR).$(MINOR) $(MAJOR_MINOR_PATCH); do \
			docker tag $(NAME)/$$image:$(TAG_VERSION) $(NAME)/$$image:$$tag ; \
		done ; \
		for tag in $(TAG_VERSION) $(MAJOR) $(MAJOR).$(MINOR) $(MAJOR_MINOR_PATCH); do \
			echo "push $(NAME)/$$image:$$tag" ; \
			docker push --quiet $(NAME)/$$image:$$tag ; \
		done ; \
	done

release_built_images_latest:
	@set -e; for image in $(RELEASE_BUILT_IMAGES); do \
		docker tag $(NAME)/$$image:$(TAG_VERSION) $(NAME)/$$image:latest ; \
		echo "push $(NAME)/$$image:latest" ; \
		docker push --quiet $(NAME)/$$image:latest ; \
	done

# Mirror the four to GHCR from what was just pushed to Docker Hub, the way
# release_ghcr already mirrors everything else.
release_built_images_ghcr:
	@set -e; for image in $(RELEASE_BUILT_IMAGES); do \
		for tag in $(TAG_VERSION) $(MAJOR) $(MAJOR).$(MINOR) $(MAJOR_MINOR_PATCH); do \
			docker buildx imagetools create \
			--tag $(GHCR_NAMESPACE)/$$image:$$tag docker.io/$(NAME)/$$image:$$tag ; \
		done ; \
	done

# :latest for the four, on GHCR. promote_release_latest covers the other 22, but
# it copies from the CI tag - these four have no CI tag, because they did not
# exist until the release built them.
release_built_images_ghcr_latest:
	@set -e; for image in $(RELEASE_BUILT_IMAGES); do \
		docker buildx imagetools create \
			--tag $(GHCR_NAMESPACE)/$$image:latest docker.io/$(NAME)/$$image:latest ; \
	done

# :nightly, for every image, straight from the tag the nightly suite ran against.
# Unlike a release, nothing here depends on the tag being created - nightly.yml
# rewrites the docs after publishing, not before - so all 26 can be promoted,
# which is exactly the set release_nightly used to push.
promote_nightly_images:
	@set -e; for image in $(CI_IMAGES); do \
		echo "promote $$image -> :nightly" ; \
		docker buildx imagetools create \
			--tag $(NAME)/$$image:nightly \
			--tag $(GHCR_NAMESPACE)/$$image:nightly \
			$(CI_REGISTRY)/$$image:$(CI_TAG) ; \
	done

# Point another tag at an already-tested manifest, without rebuilding. Used for
# the pr-<N> markers the cleanup keys on, and to retag a passing trunk set as
# :main.
promote_ci_images:
	@test -n "$(PROMOTE_TO)" || (echo "PROMOTE_TO is required" && exit 1)
	@for image in $(CI_IMAGES); do \
		echo "promote $$image: $(CI_TAG) -> $(PROMOTE_TO)" ; \
		docker buildx imagetools create -t $(CI_REGISTRY)/$$image:$(PROMOTE_TO) $(CI_REGISTRY)/$$image:$(CI_TAG) || exit 1 ; \
	done

all: hub \
	distributor \
	router \
	sessions \
	sessionqueue \
	event_bus \
	chrome \
	chromium \
	chrome-for-testing \
	edge \
	firefox \
	docker \
	kubernetes \
	all_browsers \
	standalone_chrome \
	standalone_chromium \
	standalone_chrome-for-testing \
	standalone_edge \
	standalone_firefox \
	standalone_docker \
	standalone_kubernetes \
	standalone_all_browsers \
	video \
	keda_external_scaler

check_dev_env:
	./tests/charts/make/chart_check_env.sh

setup_dev_env:
	./tests/charts/make/chart_setup_env.sh ; \
	exit_code=$$? ; \
	make set_containerd_image_store ; \
	exit $$exit_code ;

set_containerd_image_store:
	sudo mkdir -p /etc/docker
	sudo mv /etc/docker/daemon.json /etc/docker/daemon.json.bak || true
	echo "{\"features\":{\"containerd-snapshotter\": true, \"containerd\": true}, \"experimental\": true}" | sudo tee /etc/docker/daemon.json
	sudo systemctl restart docker
	sudo chmod 666 /var/run/docker.sock
	docker version -f '{{.Server.Experimental}}'
	docker info -f '{{ .DriverStatus }}'

format_shell_scripts: install_python_deps
	shfmt -l -w -d $${PWD}/*.sh $${PWD}/**/*.sh $$PWD/**.sh $$PWD/**/generate_** $$PWD/**/wrap_*

format_makefile: install_python_deps
	python3 -m mbake format Makefile
	python3 -m mbake validate Makefile

install_python_deps: install_python_venv
	python3 -m pip install -r tests/requirements.txt --break-system-packages

install_python_venv:
	python3 -m venv .venv ; \
	. .venv/bin/activate

format_python_scripts: install_python_deps
	python3 -m isort . ; \
	python3 -m black --line-length=120 --skip-string-normalization .

generate_readme_charts:
	if [ ! -f $$HOME/go/bin/helm-docs ] ; then \
		echo "helm-docs is not installed. Please install it or run 'make setup_dev_env' once." ; \
	else \
		$$HOME/go/bin/helm-docs --chart-search-root charts/selenium-grid --output-file CONFIGURATION.md --sort-values-order file ; \
	fi

update_list_env_vars: install_python_deps
	python3 scripts/generate_list_env_vars/extract_env.py

update_dockerhub_description:
	python3 scripts/dockerhub_description/update_description.py --namespace $(NAME) $(if $(DRY_RUN),--dry-run,)

check_dockerhub_description:
	python3 scripts/dockerhub_description/update_description.py --check

# Reproduce the nightly image scan locally for one image, e.g.
#   make scan_image_scout IMAGE=base
#   make scan_image_scout IMAGE=node-chrome TAG=4.49.0-20260909
# Needs `docker login`; Docker Scout must be enabled for the repository.
scan_image_scout:
	docker scout cves --only-fixed --format sarif \
		--output scout-$(IMAGE).sarif $(NAME)/$(IMAGE):$(or $(TAG),nightly)
	python3 scripts/scan_images/summarise_scout.py \
		scout-$(IMAGE).sarif $(NAME)/$(IMAGE):$(or $(TAG),nightly)

update_dockerhub_versions:
	python3 scripts/dockerhub_description/resolve_versions.py --namespace $(NAME) $(if $(GRID_TAG),--grid-tag $(GRID_TAG),)

test_dockerhub_description:
	python3 -m unittest discover -s tests/dockerhub_description -v

update_release_version: install_python_deps
	python3 scripts/release_preparation/update_versions.py --expected-base-version $(EXPECTED_BASE_VERSION)

update_selenium_version_matrix: install_python_deps
	python3 tests/build-backward-compatible/add_selenium_version.py $(BASE_VERSION)

update_browser_versions_matrix: update_selenium_version_matrix
	python3 tests/build-backward-compatible/fetch_firefox_version.py ; \
	python3 tests/build-backward-compatible/fetch_chrome_for_testing_version.py ; \
	python3 tests/build-backward-compatible/fetch_version.py ; \
	python3 tests/build-backward-compatible/update_workflow_versions.py ; \
	python3 CHANGELOG/generate-matrix-readme.py

lint_format_scripts: format_makefile format_shell_scripts format_python_scripts generate_readme_charts
	git diff --stat --exit-code ; \
	EXIT_CODE=$$? ; \
	if [ $$EXIT_CODE -ne 0 ]; then \
		echo "Scripts might get formatted. Run 'make lint_format_scripts' once after adding something new." ; \
		exit $$EXIT_CODE ; \
	fi ; \
  exit $$EXIT_CODE

set_build_nightly:
	echo BASE_VERSION=$(BASE_VERSION_NIGHTLY) > .env ; \
	echo BASE_RELEASE=$(BASE_RELEASE_NIGHTLY) >> .env ;
	echo "Execute 'source .env' to set the environment variables"

set_build_multiarch:
	echo PLATFORMS="linux/amd64,linux/arm64" > .env ; \
	echo "Execute 'source .env' to set the environment variables"

build_nightly:
	BASE_VERSION=$(BASE_VERSION_NIGHTLY) BASE_RELEASE=$(BASE_RELEASE_NIGHTLY) make build

build_exporter:
	cd .monitoring/exporter && go mod edit -go=$$(go env GOVERSION | sed 's/go//') && go mod tidy \
	&& go build -ldflags="-s -w" -o ../../bin/selenium-grid-exporter .

# Unit-test the Grid monitoring exporter. Run this after a Go toolchain or
# dependency bump (e.g. `make update_go`) to catch regressions before release.
test_exporter:
	cd .monitoring/exporter && go vet ./... && go test ./... -race -covermode=atomic -cover

# Unit-test the KEDA external scaler module.
test_scaler:
	cd .keda-external-scaler && go vet ./... && go test ./... -race -covermode=atomic -cover

# Test every in-repo Go module. Mirrors the go-test.yml CI workflow; run after
# `make update_go` to validate a toolchain/dependency bump locally.
test_go_modules: test_exporter test_scaler

# Container image providing the Go toolchain used by `update_go`. Defaults to the
# latest stable Go so no host Go install is needed and updates always track upstream.
GO_IMAGE ?= 'latest'
GO_MODULES ?= .monitoring/exporter .keda-external-scaler
# Dockerfiles with a `golang:` builder stage to keep in sync with the module Go version.
# Hub and Router build the .monitoring/exporter module in their exporter-builder stage.
GO_DOCKERFILES ?= .keda-external-scaler/Dockerfile Hub/Dockerfile Router/Dockerfile

# Update the in-repo Go modules to the latest Go toolchain and dependencies using the
# official Go container (override with GO_IMAGE=golang:1.27 to target a specific line).
# For each module it bumps the `go` directive to the container's Go version, runs
# `go get -u ./...` + `go mod tidy`, and aligns the `golang:` builder base image in the
# Dockerfiles building those modules to the same Go minor so container builds stay in sync.
update_go:
	docker pull golang:$(GO_IMAGE)
	@GO_VERSION="$$(docker run --rm golang:$(GO_IMAGE) go env GOVERSION | sed 's/go//')"; \
	GO_MM="$$(echo $$GO_VERSION | sed -E 's/([0-9]+\.[0-9]+).*/\1/')"; \
	echo "==> Using Go $$GO_VERSION from golang:$(GO_IMAGE)"; \
	for dir in $(GO_MODULES); do \
		echo "==> Updating Go module in $$dir"; \
		docker run --rm -v "$(PWD)":/src -w "/src/$$dir" \
		--user "$$(id -u):$$(id -g)" -e HOME=/tmp -e GOFLAGS=-mod=mod \
		golang:$(GO_IMAGE) sh -c "go mod edit -go=$$GO_VERSION && go get -u ./... && go mod tidy"; \
	done; \
	for file in $(GO_DOCKERFILES); do \
		echo "==> Aligning $$file base image to golang:$$GO_MM"; \
		sed -i.bak -E "s#(golang:)(latest|[0-9]+\.[0-9]+)#\1$$GO_MM#g" $$file && rm -f $$file.bak; \
	done

copy_dashboards:
	mkdir -p charts/selenium-grid/files/dashboards && cp -r .monitoring/dashboards/*.json charts/selenium-grid/files/dashboards/

build: check_dev_env all
	docker images | grep $(NAME)

ci: build test

prepare_resources:
	rm -rf ./Base/configs/node && mkdir -p ./Base/configs/node && cp -r ./charts/selenium-grid/configs/node ./Base/configs

gen_certs:
	rm -rf ./Base/certs && mkdir -p ./Base/certs && cp -r ./charts/selenium-grid/certs/*.sh ./Base/certs
	# ./Base/certs/gen-cert-helper.sh -d ./Base/certs

base: update_go prepare_resources gen_certs
	cd ./Base && SEL_PASSWD=$(SEL_PASSWD) docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg VERSION=$(BASE_VERSION) --build-arg RELEASE=$(BASE_RELEASE) --build-arg AUTHORS=$(AUTHORS) \
	--secret id=SEL_PASSWD --sbom=true --attest type=provenance,mode=max -t $(NAME)/base:$(TAG_VERSION) .

base_nightly:
	BASE_VERSION=$(BASE_VERSION_NIGHTLY) BASE_RELEASE=$(BASE_RELEASE_NIGHTLY) make base

hub: base
	cd ./Hub && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) \
		--build-context exporter-src=../.monitoring/exporter \
		-t $(NAME)/hub:$(TAG_VERSION) .

distributor: base
	cd ./Distributor && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/distributor:$(TAG_VERSION) .

router: base
	cd ./Router && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) \
		--build-context exporter-src=../.monitoring/exporter \
		-t $(NAME)/router:$(TAG_VERSION) .

sessions: base
	cd ./Sessions && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) \
	--build-arg MVN_SELENIUM_VERSION=$(MVN_SELENIUM_VERSION) -t $(NAME)/sessions:$(TAG_VERSION) .

sessionqueue: base
	cd ./SessionQueue && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/session-queue:$(TAG_VERSION) .

event_bus: base
	cd ./EventBus && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/event-bus:$(TAG_VERSION) .

node_base: base video
	cd ./NodeBase && SEL_PASSWD=$(SEL_PASSWD) docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=video --build-arg VERSION=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) --secret id=SEL_PASSWD -t $(NAME)/node-base:$(TAG_VERSION) .

chrome-for-testing_only:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Chrome for Testing is only supported on linux/amd64" \
		&& cd ./NodeChrome && docker buildx build --platform linux/amd64 $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg INSTALL_CFT=true -t $(NAME)/node-chrome-for-testing:$(TAG_VERSION) . \
		;; \
		*) \
		echo "Chrome for Testing doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

chrome-for-testing: node_base chrome-for-testing_only

standalone_chrome-for-testing_only:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Chrome for Testing is only supported on linux/amd64" \
		&& cd ./Standalone && docker buildx build --platform linux/amd64 $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-chrome-for-testing -t $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION) . \
		;; \
		*) \
		echo "Chrome for Testing doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

standalone_chrome-for-testing: chrome-for-testing standalone_chrome-for-testing_only

chrome_only:
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/node-chrome:$(TAG_VERSION) .

chrome: node_base chrome_only

chrome_dev:
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg CHROME_VERSION=google-chrome-unstable -t $(NAME)/node-chrome:dev .

chrome_beta:
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg CHROME_VERSION=google-chrome-beta -t $(NAME)/node-chrome:beta .

chrome-for-testing_dev:
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg CFT_VERSION=DEV --build-arg INSTALL_CFT=true -t $(NAME)/node-chrome-for-testing:dev .

chrome-for-testing_beta:
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg CHROME_VERSION=BETA --build-arg INSTALL_CFT=true -t $(NAME)/node-chrome-for-testing:beta .

chrome-for-testing_canary:
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg CHROME_VERSION=CANARY --build-arg INSTALL_CFT=true -t $(NAME)/node-chrome-for-testing:canary .

chromium: node_base
	cd ./NodeChromium && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg CHROMIUM_VERSION=$(CHROMIUM_VERSION) -t $(NAME)/node-chromium:$(TAG_VERSION) .

edge_only:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Microsoft Edge is only supported on linux/amd64" \
		&& cd ./NodeEdge && docker buildx build --platform linux/amd64 $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/node-edge:$(TAG_VERSION) . \
		;; \
		*) \
		echo "Microsoft Edge doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

edge: node_base edge_only

edge_dev:
	cd ./NodeEdge && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg EDGE_VERSION=microsoft-edge-dev -t $(NAME)/node-edge:dev .

edge_beta:
	cd ./NodeEdge && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg EDGE_VERSION=microsoft-edge-beta -t $(NAME)/node-edge:beta .

firefox_only:
	cd ./NodeFirefox && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg FIREFOX_DOWNLOAD_URL=$(FIREFOX_DOWNLOAD_URL) -t $(NAME)/node-firefox:$(TAG_VERSION) .

firefox: node_base firefox_only

firefox_dev:
	cd ./NodeFirefox && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg FIREFOX_VERSION=devedition-latest -t $(NAME)/node-firefox:dev .

firefox_beta:
	cd ./NodeFirefox && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg FIREFOX_VERSION=beta-latest -t $(NAME)/node-firefox:beta .

docker: base
	cd ./NodeDocker && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/node-docker:$(TAG_VERSION) .

standalone_docker: docker
	cd ./StandaloneDocker && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/standalone-docker:$(TAG_VERSION) .

kubernetes: base
	cd ./NodeKubernetes && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) \
	--build-arg MVN_SELENIUM_VERSION=$(MVN_SELENIUM_VERSION) -t $(NAME)/node-kubernetes:$(TAG_VERSION) .

standalone_kubernetes: kubernetes
	cd ./StandaloneKubernetes && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) -t $(NAME)/standalone-kubernetes:$(TAG_VERSION) .

standalone_firefox_only:
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-firefox -t $(NAME)/standalone-firefox:$(TAG_VERSION) .

standalone_firefox: firefox standalone_firefox_only

standalone_firefox_dev: firefox_dev
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=dev --build-arg BASE=node-firefox -t $(NAME)/standalone-firefox:dev .

standalone_firefox_beta: firefox_beta
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=beta --build-arg BASE=node-firefox -t $(NAME)/standalone-firefox:beta .

standalone_chrome_only:
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-chrome -t $(NAME)/standalone-chrome:$(TAG_VERSION) .

standalone_chrome: chrome standalone_chrome_only

standalone_chrome_dev: chrome_dev
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=dev --build-arg BASE=node-chrome -t $(NAME)/standalone-chrome:dev .

standalone_chrome_beta: chrome_beta
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=beta --build-arg BASE=node-chrome -t $(NAME)/standalone-chrome:beta .

standalone_chrome-for-testing_dev: chrome-for-testing_dev
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=dev --build-arg BASE=node-chrome-for-testing -t $(NAME)/standalone-chrome-for-testing:dev .

standalone_chrome-for-testing_beta: chrome-for-testing_beta
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=beta --build-arg BASE=node-chrome-for-testing -t $(NAME)/standalone-chrome-for-testing:beta .

standalone_chrome-for-testing_canary: chrome-for-testing_canary
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=canary --build-arg BASE=node-chrome-for-testing -t $(NAME)/standalone-chrome-for-testing:canary .

standalone_chromium: chromium
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-chromium -t $(NAME)/standalone-chromium:$(TAG_VERSION) .

standalone_edge_only:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Microsoft Edge is only supported on linux/amd64" \
		&& cd ./Standalone && docker buildx build --platform linux/amd64 $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-edge -t $(NAME)/standalone-edge:$(TAG_VERSION) . \
		;; \
		*) \
		echo "Microsoft Edge doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

standalone_edge: edge standalone_edge_only

standalone_edge_dev: edge_dev
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=dev --build-arg BASE=node-edge -t $(NAME)/standalone-edge:dev .

standalone_edge_beta: edge_beta
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --sbom=true --attest type=provenance,mode=max \
	--build-arg NAMESPACE=$(NAME) --build-arg VERSION=beta --build-arg BASE=node-edge -t $(NAME)/standalone-edge:beta .

video: base
	cd ./Video && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg FFMPEG_BASED_NAME=$(FFMPEG_BASED_NAME) --build-arg FFMPEG_BASED_TAG=$(FFMPEG_BASED_TAG) $(FROM_IMAGE_ARGS) -t $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) .

ffmpeg:
	cd ./.ffmpeg && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg FFMPEG_VERSION=$(FFMPEG_VERSION) $(FROM_IMAGE_ARGS) -t $(NAME)/ffmpeg:$(FFMPEG_VERSION)-$(BUILD_DATE) .

all_browsers: node_base
	cd ./NodeChromium && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-base --build-arg CHROMIUM_VERSION=$(CHROMIUM_VERSION) -t $(NAME)/node-all-browsers:$(TAG_VERSION) . ; \
	cd .. ; \
	cd ./NodeFirefox && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-all-browsers --build-arg FIREFOX_DOWNLOAD_URL=$(FIREFOX_DOWNLOAD_URL) -t $(NAME)/node-all-browsers:$(TAG_VERSION) . ; \
	cd .. ; \
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-all-browsers -t $(NAME)/node-all-browsers:$(TAG_VERSION) . || true ; \
	cd .. ; \
	cd ./NodeEdge && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-all-browsers -t $(NAME)/node-all-browsers:$(TAG_VERSION) . || true ; \
	cd .. ; \
	cd ./NodeAllBrowsers && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-all-browsers -t $(NAME)/node-all-browsers:$(TAG_VERSION) . ; \
	cd .. ;

standalone_all_browsers: all_browsers
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-all-browsers -t $(NAME)/standalone-all-browsers:$(TAG_VERSION) .

fetch_grid_scaler_resources:
	mkdir -p ./.keda/scalers \
	&& cd ./.keda/scalers \
	&& curl -L https://raw.githubusercontent.com/$(KEDA_BASED_NAME)/keda/v$(KEDA_BASED_TAG)/pkg/scalers/selenium_grid_scaler.go -o selenium_grid_scaler.go \
	&& curl -L https://raw.githubusercontent.com/$(KEDA_BASED_NAME)/keda/v$(KEDA_BASED_TAG)/pkg/scalers/selenium_grid_scaler_test.go -o selenium_grid_scaler_test.go \
	&& curl -L https://raw.githubusercontent.com/$(KEDA_BASED_NAME)/keda-docs/main/content/docs/2.18/scalers/selenium-grid-scaler.md -o selenium-grid-scaler.md

fetch_grid_scaler_images:
	docker pull --platform linux/amd64 --platform linux/arm64 $(KEDA_BASED_NAME)/keda:$(KEDA_BASED_TAG)
	docker pull --platform linux/amd64 --platform linux/arm64 $(KEDA_BASED_NAME)/keda-metrics-apiserver:$(KEDA_BASED_TAG)
	docker pull --platform linux/amd64 --platform linux/arm64 $(KEDA_BASED_NAME)/keda-admission-webhooks:$(KEDA_BASED_TAG)

# Build the standalone Selenium Grid KEDA external scaler image, following the same
# build/tag/release convention as the other grid components (e.g. Hub). Tagged with the
# Selenium Grid version ($(TAG_VERSION)) and released via the standard release* targets.
keda_external_scaler:
	cd ./.keda-external-scaler && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) \
		-t $(NAME)/keda-external-scaler:$(TAG_VERSION) .

release_grid_scaler: fetch_grid_scaler_images
	docker buildx imagetools create -t $(NAME)/keda:$(KEDA_TAG_VERSION)-$(BUILD_DATE) $(KEDA_BASED_NAME)/keda:$(KEDA_BASED_TAG)
	docker buildx imagetools create -t $(NAME)/keda-metrics-apiserver:$(KEDA_TAG_VERSION)-$(BUILD_DATE) $(KEDA_BASED_NAME)/keda-metrics-apiserver:$(KEDA_BASED_TAG)
	docker buildx imagetools create -t $(NAME)/keda-admission-webhooks:$(KEDA_TAG_VERSION)-$(BUILD_DATE) $(KEDA_BASED_NAME)/keda-admission-webhooks:$(KEDA_BASED_TAG)

release_grid_scaler_latest: fetch_grid_scaler_images
	docker buildx imagetools create -t $(NAME)/keda:latest $(KEDA_BASED_NAME)/keda:$(KEDA_BASED_TAG)
	docker buildx imagetools create -t $(NAME)/keda-metrics-apiserver:latest $(KEDA_BASED_NAME)/keda-metrics-apiserver:$(KEDA_BASED_TAG)
	docker buildx imagetools create -t $(NAME)/keda-admission-webhooks:latest $(KEDA_BASED_NAME)/keda-admission-webhooks:$(KEDA_BASED_TAG)

release_grid_scaler_nightly: fetch_grid_scaler_images
	docker buildx imagetools create -t $(NAME)/keda:nightly $(KEDA_BASED_NAME)/keda:$(KEDA_BASED_TAG)
	docker buildx imagetools create -t $(NAME)/keda-metrics-apiserver:nightly $(KEDA_BASED_NAME)/keda-metrics-apiserver:$(KEDA_BASED_TAG)
	docker buildx imagetools create -t $(NAME)/keda-admission-webhooks:nightly $(KEDA_BASED_NAME)/keda-admission-webhooks:$(KEDA_BASED_TAG)

count_image_layers:
	docker history $(NAME)/base:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/hub:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/distributor:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/router:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/sessions:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/session-queue:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/event-bus:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-base:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-chrome:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-chromium:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-chrome-for-testing:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-edge:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-firefox:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-docker:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-kubernetes:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/node-all-browsers:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-chrome:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-chromium:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-edge:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-firefox:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-docker:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-kubernetes:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/standalone-all-browsers:$(TAG_VERSION) -q | wc -l
	docker history $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) -q | wc -l

chrome_upgrade_version:
	cd ./NodeChrome && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg NAMESPACE=$(NAMESPACE) --build-arg VERSION=$(VERSION) --build-arg AUTHORS=$(AUTHORS) -t $(NAME)/node-chrome:$(TAG_VERSION) .
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-chrome -t $(NAME)/standalone-chrome:$(TAG_VERSION) .
	docker run --rm $(NAME)/standalone-chrome:$(TAG_VERSION) /opt/selenium/selenium-server.jar info --version
	docker run --rm $(NAME)/standalone-chrome:$(TAG_VERSION) google-chrome --version
	docker run --rm $(NAME)/standalone-chrome:$(TAG_VERSION) chromedriver --version

firefox_upgrade_version:
	cd ./NodeFirefox && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg NAMESPACE=$(NAMESPACE) --build-arg VERSION=$(VERSION) --build-arg AUTHORS=$(AUTHORS) -t $(NAME)/node-firefox:$(TAG_VERSION) .
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-firefox -t $(NAME)/standalone-firefox:$(TAG_VERSION) .
	docker run --rm $(NAME)/standalone-firefox:$(TAG_VERSION) /opt/selenium/selenium-server.jar info --version
	docker run --rm $(NAME)/standalone-firefox:$(TAG_VERSION) firefox --version
	docker run --rm $(NAME)/standalone-firefox:$(TAG_VERSION) geckodriver --version

edge_upgrade_version:
	cd ./NodeEdge && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) --build-arg NAMESPACE=$(NAMESPACE) --build-arg VERSION=$(VERSION) --build-arg AUTHORS=$(AUTHORS) -t $(NAME)/node-edge:$(TAG_VERSION) .
	cd ./Standalone && docker buildx build --platform $(PLATFORMS) $(BUILD_ARGS) $(FROM_IMAGE_ARGS) --build-arg BASE=node-edge -t $(NAME)/standalone-edge:$(TAG_VERSION) .
	docker run --rm $(NAME)/standalone-edge:$(TAG_VERSION) /opt/selenium/selenium-server.jar info --version
	docker run --rm $(NAME)/standalone-edge:$(TAG_VERSION) microsoft-edge --version
	docker run --rm $(NAME)/standalone-edge:$(TAG_VERSION) msedgedriver --version

# https://github.com/SeleniumHQ/docker-selenium/issues/992
# Additional tags for browser images
tag_and_push_browser_images: tag_and_push_chrome_images tag_and_push_chrome-for-testing_images tag_and_push_chromium_images tag_and_push_firefox_images tag_and_push_edge_images

tag_and_push_chrome_images:
	./tag_and_push_browser_images.sh $(VERSION) $(BUILD_DATE) $(NAMESPACE) $(PUSH_IMAGE) chrome $(RELEASE_OLD_VERSION)

tag_and_push_chrome-for-testing_images:
	./tag_and_push_browser_images.sh $(VERSION) $(BUILD_DATE) $(NAMESPACE) $(PUSH_IMAGE) chrome-for-testing $(RELEASE_OLD_VERSION)

tag_and_push_chromium_images:
	./tag_and_push_browser_images.sh $(VERSION) $(BUILD_DATE) $(NAMESPACE) $(PUSH_IMAGE) chromium $(RELEASE_OLD_VERSION)

tag_and_push_edge_images:
	./tag_and_push_browser_images.sh $(VERSION) $(BUILD_DATE) $(NAMESPACE) $(PUSH_IMAGE) edge $(RELEASE_OLD_VERSION)

tag_and_push_firefox_images:
	./tag_and_push_browser_images.sh $(VERSION) $(BUILD_DATE) $(NAMESPACE) $(PUSH_IMAGE) firefox $(RELEASE_OLD_VERSION)

tag_and_push_browser_images_ghcr:
	for image in node-chrome standalone-chrome \
		node-chromium standalone-chromium \
		node-chrome-for-testing standalone-chrome-for-testing \
		node-edge standalone-edge \
		node-firefox standalone-firefox; do \
		docker images --format "{{.Tag}}" "$(NAME)/$$image" | grep -v "^<none>$$" | while IFS= read -r tag; do \
		docker buildx imagetools create \
		--tag $(GHCR_NAMESPACE)/$$image:$$tag docker.io/$(NAME)/$$image:$$tag ; \
	done ; \
	done

mirror_browser_images_ghcr:
	for image in node-$(BROWSER_NAME) standalone-$(BROWSER_NAME); do \
		docker images --format "{{.Tag}}" "$(NAME)/$$image" | grep -v "^<none>$$" | while IFS= read -r tag; do \
		docker buildx imagetools create \
		--tag $(GHCR_NAMESPACE)/$$image:$$tag docker.io/$(NAME)/$$image:$$tag ; \
	done ; \
	done

mirror_browser_channel_image_ghcr:
	for image in node-$(BROWSER_NAME) standalone-$(BROWSER_NAME); do \
		docker buildx imagetools create \
		--tag $(GHCR_NAMESPACE)/$$image:$(BROWSER_TAG) docker.io/$(NAME)/$$image:$(BROWSER_TAG) ; \
	done

tag_ffmpeg_latest:
	docker tag $(NAME)/ffmpeg:$(FFMPEG_VERSION)-$(BUILD_DATE) $(NAME)/ffmpeg:latest
	docker tag $(NAME)/ffmpeg:$(FFMPEG_VERSION)-$(BUILD_DATE) $(NAME)/ffmpeg:$(FFMPEG_VERSION)

tag_latest:
	docker tag $(NAME)/base:$(TAG_VERSION) $(NAME)/base:latest
	docker tag $(NAME)/hub:$(TAG_VERSION) $(NAME)/hub:latest
	docker tag $(NAME)/distributor:$(TAG_VERSION) $(NAME)/distributor:latest
	docker tag $(NAME)/router:$(TAG_VERSION) $(NAME)/router:latest
	docker tag $(NAME)/sessions:$(TAG_VERSION) $(NAME)/sessions:latest
	docker tag $(NAME)/session-queue:$(TAG_VERSION) $(NAME)/session-queue:latest
	docker tag $(NAME)/event-bus:$(TAG_VERSION) $(NAME)/event-bus:latest
	docker tag $(NAME)/node-base:$(TAG_VERSION) $(NAME)/node-base:latest
	docker tag $(NAME)/node-chrome:$(TAG_VERSION) $(NAME)/node-chrome:latest
	docker tag $(NAME)/node-chromium:$(TAG_VERSION) $(NAME)/node-chromium:latest
	docker tag $(NAME)/node-firefox:$(TAG_VERSION) $(NAME)/node-firefox:latest
	docker tag $(NAME)/node-docker:$(TAG_VERSION) $(NAME)/node-docker:latest
	docker tag $(NAME)/node-kubernetes:$(TAG_VERSION) $(NAME)/node-kubernetes:latest
	docker tag $(NAME)/node-all-browsers:$(TAG_VERSION) $(NAME)/node-all-browsers:latest
	docker tag $(NAME)/standalone-chrome:$(TAG_VERSION) $(NAME)/standalone-chrome:latest
	docker tag $(NAME)/standalone-chromium:$(TAG_VERSION) $(NAME)/standalone-chromium:latest
	docker tag $(NAME)/standalone-firefox:$(TAG_VERSION) $(NAME)/standalone-firefox:latest
	docker tag $(NAME)/standalone-docker:$(TAG_VERSION) $(NAME)/standalone-docker:latest
	docker tag $(NAME)/standalone-kubernetes:$(TAG_VERSION) $(NAME)/standalone-kubernetes:latest
	docker tag $(NAME)/standalone-all-browsers:$(TAG_VERSION) $(NAME)/standalone-all-browsers:latest
	docker tag $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) $(NAME)/video:latest
	docker tag $(NAME)/keda-external-scaler:$(TAG_VERSION) $(NAME)/keda-external-scaler:latest
	case "$(PLATFORMS)" in *linux/amd64*) \
		docker tag $(NAME)/node-chrome-for-testing:$(TAG_VERSION) $(NAME)/node-chrome-for-testing:latest && \
		docker tag $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION) $(NAME)/standalone-chrome-for-testing:latest && \
		docker tag $(NAME)/node-edge:$(TAG_VERSION) $(NAME)/node-edge:latest && \
		docker tag $(NAME)/standalone-edge:$(TAG_VERSION) $(NAME)/standalone-edge:latest \
		;; \
		*) \
		echo "Tagged other images, except Chrome for Testing and Edge Node/Standalone don't support platform $(PLATFORMS)" ; \
		;; \
	esac

release_ffmpeg_latest:
	docker push $(NAME)/ffmpeg:latest
	docker push $(NAME)/ffmpeg:$(FFMPEG_VERSION)
	docker push $(NAME)/ffmpeg:$(FFMPEG_VERSION)-$(BUILD_DATE)

release_ffmpeg_ghcr_latest:
	for tag in latest $(FFMPEG_VERSION) $(FFMPEG_VERSION)-$(BUILD_DATE); do \
		docker buildx imagetools create \
		--tag $(GHCR_NAMESPACE)/ffmpeg:$$tag docker.io/$(NAME)/ffmpeg:$$tag ; \
	done

release_latest:
	docker push $(NAME)/base:latest
	docker push $(NAME)/hub:latest
	docker push $(NAME)/keda-external-scaler:latest
	docker push $(NAME)/distributor:latest
	docker push $(NAME)/router:latest
	docker push $(NAME)/sessions:latest
	docker push $(NAME)/session-queue:latest
	docker push $(NAME)/event-bus:latest
	docker push $(NAME)/node-base:latest
	docker push $(NAME)/node-chrome:latest
	docker push $(NAME)/node-chromium:latest
	docker push $(NAME)/node-chrome-for-testing:latest
	docker push $(NAME)/node-edge:latest
	docker push $(NAME)/node-firefox:latest
	docker push $(NAME)/node-docker:latest
	docker push $(NAME)/node-kubernetes:latest
	docker push $(NAME)/node-all-browsers:latest
	docker push $(NAME)/standalone-chrome:latest
	docker push $(NAME)/standalone-chromium:latest
	docker push $(NAME)/standalone-chrome-for-testing:latest
	docker push $(NAME)/standalone-edge:latest
	docker push $(NAME)/standalone-firefox:latest
	docker push $(NAME)/standalone-docker:latest
	docker push $(NAME)/standalone-kubernetes:latest
	docker push $(NAME)/standalone-all-browsers:latest
	docker push $(NAME)/video:latest

release_ghcr_latest:
	for image in base hub distributor router sessions session-queue event-bus \
		node-base node-chrome node-chromium node-chrome-for-testing node-edge \
		node-firefox node-docker node-kubernetes node-all-browsers \
		standalone-chrome standalone-chromium standalone-chrome-for-testing \
		standalone-edge standalone-firefox standalone-docker \
		standalone-kubernetes standalone-all-browsers keda-external-scaler video; do \
		docker buildx imagetools create \
		--tag $(GHCR_NAMESPACE)/$$image:latest docker.io/$(NAME)/$$image:latest ; \
	done

generate_latest_sbom:
	NAME=$(NAME) FILTER_IMAGE_TAG=latest OUTPUT_FILE=$(SBOM_OUTPUT) ./generate_sbom.sh

tag_nightly:
	docker tag $(NAME)/base:$(TAG_VERSION) $(NAME)/base:nightly
	docker tag $(NAME)/hub:$(TAG_VERSION) $(NAME)/hub:nightly
	docker tag $(NAME)/keda-external-scaler:$(TAG_VERSION) $(NAME)/keda-external-scaler:nightly
	docker tag $(NAME)/distributor:$(TAG_VERSION) $(NAME)/distributor:nightly
	docker tag $(NAME)/router:$(TAG_VERSION) $(NAME)/router:nightly
	docker tag $(NAME)/sessions:$(TAG_VERSION) $(NAME)/sessions:nightly
	docker tag $(NAME)/session-queue:$(TAG_VERSION) $(NAME)/session-queue:nightly
	docker tag $(NAME)/event-bus:$(TAG_VERSION) $(NAME)/event-bus:nightly
	docker tag $(NAME)/node-base:$(TAG_VERSION) $(NAME)/node-base:nightly
	docker tag $(NAME)/node-chrome:$(TAG_VERSION) $(NAME)/node-chrome:nightly
	docker tag $(NAME)/node-chromium:$(TAG_VERSION) $(NAME)/node-chromium:nightly
	docker tag $(NAME)/node-chrome-for-testing:$(TAG_VERSION) $(NAME)/node-chrome-for-testing:nightly
	docker tag $(NAME)/node-firefox:$(TAG_VERSION) $(NAME)/node-firefox:nightly
	docker tag $(NAME)/node-docker:$(TAG_VERSION) $(NAME)/node-docker:nightly
	docker tag $(NAME)/node-kubernetes:$(TAG_VERSION) $(NAME)/node-kubernetes:nightly
	docker tag $(NAME)/node-all-browsers:$(TAG_VERSION) $(NAME)/node-all-browsers:nightly
	docker tag $(NAME)/standalone-chrome:$(TAG_VERSION) $(NAME)/standalone-chrome:nightly
	docker tag $(NAME)/standalone-chromium:$(TAG_VERSION) $(NAME)/standalone-chromium:nightly
	docker tag $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION) $(NAME)/standalone-chrome-for-testing:nightly
	docker tag $(NAME)/standalone-firefox:$(TAG_VERSION) $(NAME)/standalone-firefox:nightly
	docker tag $(NAME)/standalone-docker:$(TAG_VERSION) $(NAME)/standalone-docker:nightly
	docker tag $(NAME)/standalone-kubernetes:$(TAG_VERSION) $(NAME)/standalone-kubernetes:nightly
	docker tag $(NAME)/standalone-all-browsers:$(TAG_VERSION) $(NAME)/standalone-all-browsers:nightly
	docker tag $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) $(NAME)/video:nightly
	case "$(PLATFORMS)" in *linux/amd64*) \
		docker tag $(NAME)/node-edge:$(TAG_VERSION) $(NAME)/node-edge:nightly && \
		docker tag $(NAME)/standalone-edge:$(TAG_VERSION) $(NAME)/standalone-edge:nightly \
		;; \
		*) \
		echo "Tagged other images, except Edge Node/Standalone don't support platform $(PLATFORMS)" ; \
		;; \
	esac

release_nightly:
	docker push $(NAME)/base:nightly
	docker push $(NAME)/hub:nightly
	docker push $(NAME)/keda-external-scaler:nightly
	docker push $(NAME)/distributor:nightly
	docker push $(NAME)/router:nightly
	docker push $(NAME)/sessions:nightly
	docker push $(NAME)/session-queue:nightly
	docker push $(NAME)/event-bus:nightly
	docker push $(NAME)/node-base:nightly
	docker push $(NAME)/node-chrome:nightly
	docker push $(NAME)/node-chromium:nightly
	docker push $(NAME)/node-chrome-for-testing:nightly
	docker push $(NAME)/node-edge:nightly
	docker push $(NAME)/node-firefox:nightly
	docker push $(NAME)/node-docker:nightly
	docker push $(NAME)/node-kubernetes:nightly
	docker push $(NAME)/node-all-browsers:nightly
	docker push $(NAME)/standalone-chrome:nightly
	docker push $(NAME)/standalone-chromium:nightly
	docker push $(NAME)/standalone-chrome-for-testing:nightly
	docker push $(NAME)/standalone-edge:nightly
	docker push $(NAME)/standalone-firefox:nightly
	docker push $(NAME)/standalone-docker:nightly
	docker push $(NAME)/standalone-kubernetes:nightly
	docker push $(NAME)/standalone-all-browsers:nightly
	docker push $(NAME)/video:nightly

release_ghcr_nightly:
	for image in base hub distributor router sessions session-queue event-bus \
		node-base node-chrome node-chromium node-chrome-for-testing node-edge \
		node-firefox node-docker node-kubernetes node-all-browsers \
		standalone-chrome standalone-chromium standalone-chrome-for-testing \
		standalone-edge standalone-firefox standalone-docker \
		standalone-kubernetes standalone-all-browsers keda-external-scaler video; do \
		docker buildx imagetools create \
		--tag $(GHCR_NAMESPACE)/$$image:nightly docker.io/$(NAME)/$$image:nightly ; \
	done

generate_nightly_sbom:
	NAME=$(NAME) FILTER_IMAGE_TAG=nightly OUTPUT_FILE=$(SBOM_OUTPUT) ./generate_sbom.sh

tag_major_minor:
	docker tag $(NAME)/base:$(TAG_VERSION) $(NAME)/base:$(MAJOR)
	docker tag $(NAME)/hub:$(TAG_VERSION) $(NAME)/hub:$(MAJOR)
	docker tag $(NAME)/keda-external-scaler:$(TAG_VERSION) $(NAME)/keda-external-scaler:$(MAJOR)
	docker tag $(NAME)/distributor:$(TAG_VERSION) $(NAME)/distributor:$(MAJOR)
	docker tag $(NAME)/router:$(TAG_VERSION) $(NAME)/router:$(MAJOR)
	docker tag $(NAME)/sessions:$(TAG_VERSION) $(NAME)/sessions:$(MAJOR)
	docker tag $(NAME)/session-queue:$(TAG_VERSION) $(NAME)/session-queue:$(MAJOR)
	docker tag $(NAME)/event-bus:$(TAG_VERSION) $(NAME)/event-bus:$(MAJOR)
	docker tag $(NAME)/node-base:$(TAG_VERSION) $(NAME)/node-base:$(MAJOR)
	docker tag $(NAME)/node-chrome:$(TAG_VERSION) $(NAME)/node-chrome:$(MAJOR)
	docker tag $(NAME)/node-chromium:$(TAG_VERSION) $(NAME)/node-chromium:$(MAJOR)
	docker tag $(NAME)/node-chrome-for-testing:$(TAG_VERSION) $(NAME)/node-chrome-for-testing:$(MAJOR)
	docker tag $(NAME)/node-edge:$(TAG_VERSION) $(NAME)/node-edge:$(MAJOR)
	docker tag $(NAME)/node-firefox:$(TAG_VERSION) $(NAME)/node-firefox:$(MAJOR)
	docker tag $(NAME)/node-docker:$(TAG_VERSION) $(NAME)/node-docker:$(MAJOR)
	docker tag $(NAME)/node-kubernetes:$(TAG_VERSION) $(NAME)/node-kubernetes:$(MAJOR)
	docker tag $(NAME)/node-all-browsers:$(TAG_VERSION) $(NAME)/node-all-browsers:$(MAJOR)
	docker tag $(NAME)/standalone-chrome:$(TAG_VERSION) $(NAME)/standalone-chrome:$(MAJOR)
	docker tag $(NAME)/standalone-chromium:$(TAG_VERSION) $(NAME)/standalone-chromium:$(MAJOR)
	docker tag $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION) $(NAME)/standalone-chrome-for-testing:$(MAJOR)
	docker tag $(NAME)/standalone-edge:$(TAG_VERSION) $(NAME)/standalone-edge:$(MAJOR)
	docker tag $(NAME)/standalone-firefox:$(TAG_VERSION) $(NAME)/standalone-firefox:$(MAJOR)
	docker tag $(NAME)/standalone-docker:$(TAG_VERSION) $(NAME)/standalone-docker:$(MAJOR)
	docker tag $(NAME)/standalone-kubernetes:$(TAG_VERSION) $(NAME)/standalone-kubernetes:$(MAJOR)
	docker tag $(NAME)/standalone-all-browsers:$(TAG_VERSION) $(NAME)/standalone-all-browsers:$(MAJOR)
	docker tag $(NAME)/base:$(TAG_VERSION) $(NAME)/base:$(MAJOR).$(MINOR)
	docker tag $(NAME)/hub:$(TAG_VERSION) $(NAME)/hub:$(MAJOR).$(MINOR)
	docker tag $(NAME)/keda-external-scaler:$(TAG_VERSION) $(NAME)/keda-external-scaler:$(MAJOR).$(MINOR)
	docker tag $(NAME)/distributor:$(TAG_VERSION) $(NAME)/distributor:$(MAJOR).$(MINOR)
	docker tag $(NAME)/router:$(TAG_VERSION) $(NAME)/router:$(MAJOR).$(MINOR)
	docker tag $(NAME)/sessions:$(TAG_VERSION) $(NAME)/sessions:$(MAJOR).$(MINOR)
	docker tag $(NAME)/session-queue:$(TAG_VERSION) $(NAME)/session-queue:$(MAJOR).$(MINOR)
	docker tag $(NAME)/event-bus:$(TAG_VERSION) $(NAME)/event-bus:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-base:$(TAG_VERSION) $(NAME)/node-base:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-chrome:$(TAG_VERSION) $(NAME)/node-chrome:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-chromium:$(TAG_VERSION) $(NAME)/node-chromium:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-chrome-for-testing:$(TAG_VERSION) $(NAME)/node-chrome-for-testing:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-edge:$(TAG_VERSION) $(NAME)/node-edge:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-firefox:$(TAG_VERSION) $(NAME)/node-firefox:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-docker:$(TAG_VERSION) $(NAME)/node-docker:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-kubernetes:$(TAG_VERSION) $(NAME)/node-kubernetes:$(MAJOR).$(MINOR)
	docker tag $(NAME)/node-all-browsers:$(TAG_VERSION) $(NAME)/node-all-browsers:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-chrome:$(TAG_VERSION) $(NAME)/standalone-chrome:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-chromium:$(TAG_VERSION) $(NAME)/standalone-chromium:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION) $(NAME)/standalone-chrome-for-testing:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-edge:$(TAG_VERSION) $(NAME)/standalone-edge:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-firefox:$(TAG_VERSION) $(NAME)/standalone-firefox:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-docker:$(TAG_VERSION) $(NAME)/standalone-docker:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-kubernetes:$(TAG_VERSION) $(NAME)/standalone-kubernetes:$(MAJOR).$(MINOR)
	docker tag $(NAME)/standalone-all-browsers:$(TAG_VERSION) $(NAME)/standalone-all-browsers:$(MAJOR).$(MINOR)
	docker tag $(NAME)/base:$(TAG_VERSION) $(NAME)/base:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/hub:$(TAG_VERSION) $(NAME)/hub:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/keda-external-scaler:$(TAG_VERSION) $(NAME)/keda-external-scaler:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/distributor:$(TAG_VERSION) $(NAME)/distributor:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/router:$(TAG_VERSION) $(NAME)/router:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/sessions:$(TAG_VERSION) $(NAME)/sessions:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/session-queue:$(TAG_VERSION) $(NAME)/session-queue:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/event-bus:$(TAG_VERSION) $(NAME)/event-bus:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-base:$(TAG_VERSION) $(NAME)/node-base:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-chrome:$(TAG_VERSION) $(NAME)/node-chrome:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-chromium:$(TAG_VERSION) $(NAME)/node-chromium:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-chrome-for-testing:$(TAG_VERSION) $(NAME)/node-chrome-for-testing:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-edge:$(TAG_VERSION) $(NAME)/node-edge:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-firefox:$(TAG_VERSION) $(NAME)/node-firefox:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-docker:$(TAG_VERSION) $(NAME)/node-docker:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-kubernetes:$(TAG_VERSION) $(NAME)/node-kubernetes:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/node-all-browsers:$(TAG_VERSION) $(NAME)/node-all-browsers:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-chrome:$(TAG_VERSION) $(NAME)/standalone-chrome:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-chromium:$(TAG_VERSION) $(NAME)/standalone-chromium:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION) $(NAME)/standalone-chrome-for-testing:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-edge:$(TAG_VERSION) $(NAME)/standalone-edge:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-firefox:$(TAG_VERSION) $(NAME)/standalone-firefox:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-docker:$(TAG_VERSION) $(NAME)/standalone-docker:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-kubernetes:$(TAG_VERSION) $(NAME)/standalone-kubernetes:$(MAJOR_MINOR_PATCH)
	docker tag $(NAME)/standalone-all-browsers:$(TAG_VERSION) $(NAME)/standalone-all-browsers:$(MAJOR_MINOR_PATCH)

release: tag_major_minor
	@if ! docker images --format table $(NAME)/base | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/base version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/hub | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/hub version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/keda-external-scaler | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/keda-external-scaler version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/distributor | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/distributor version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/router | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/router version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/sessions | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/sessions version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/session-queue | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/session-queue version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/event-bus | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/event-bus version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-base | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-base version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-chrome | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-chrome version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-chromium | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-chromium version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-chrome-for-testing | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-chrome-for-testing version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-edge | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-edge version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-firefox | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-firefox version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-docker | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-docker version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-kubernetes | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-kubernetes version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/node-all-browsers | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/node-all-browsers version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-chrome | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-chrome version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-chromium | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-chromium version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-chrome-for-testing | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-chrome-for-testing version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-edge | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-edge version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-firefox | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-firefox version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-docker | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-docker version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-kubernetes | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-kubernetes version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	@if ! docker images --format table $(NAME)/standalone-all-browsers | awk '{ print $$2 }' | grep -q -F $(TAG_VERSION); then echo "$(NAME)/standalone-all-browsers version $(TAG_VERSION) is not yet built. Please run 'make build'"; false; fi
	docker push $(NAME)/base:$(TAG_VERSION)
	docker push $(NAME)/hub:$(TAG_VERSION)
	docker push $(NAME)/keda-external-scaler:$(TAG_VERSION)
	docker push $(NAME)/distributor:$(TAG_VERSION)
	docker push $(NAME)/router:$(TAG_VERSION)
	docker push $(NAME)/sessions:$(TAG_VERSION)
	docker push $(NAME)/session-queue:$(TAG_VERSION)
	docker push $(NAME)/event-bus:$(TAG_VERSION)
	docker push $(NAME)/node-base:$(TAG_VERSION)
	docker push $(NAME)/node-chrome:$(TAG_VERSION)
	docker push $(NAME)/node-chromium:$(TAG_VERSION)
	docker push $(NAME)/node-chrome-for-testing:$(TAG_VERSION)
	docker push $(NAME)/node-edge:$(TAG_VERSION)
	docker push $(NAME)/node-firefox:$(TAG_VERSION)
	docker push $(NAME)/node-docker:$(TAG_VERSION)
	docker push $(NAME)/node-kubernetes:$(TAG_VERSION)
	docker push $(NAME)/node-all-browsers:$(TAG_VERSION)
	docker push $(NAME)/standalone-chrome:$(TAG_VERSION)
	docker push $(NAME)/standalone-chromium:$(TAG_VERSION)
	docker push $(NAME)/standalone-chrome-for-testing:$(TAG_VERSION)
	docker push $(NAME)/standalone-edge:$(TAG_VERSION)
	docker push $(NAME)/standalone-firefox:$(TAG_VERSION)
	docker push $(NAME)/standalone-docker:$(TAG_VERSION)
	docker push $(NAME)/standalone-kubernetes:$(TAG_VERSION)
	docker push $(NAME)/standalone-all-browsers:$(TAG_VERSION)
	docker push $(NAME)/base:$(MAJOR)
	docker push $(NAME)/hub:$(MAJOR)
	docker push $(NAME)/keda-external-scaler:$(MAJOR)
	docker push $(NAME)/distributor:$(MAJOR)
	docker push $(NAME)/router:$(MAJOR)
	docker push $(NAME)/sessions:$(MAJOR)
	docker push $(NAME)/session-queue:$(MAJOR)
	docker push $(NAME)/event-bus:$(MAJOR)
	docker push $(NAME)/node-base:$(MAJOR)
	docker push $(NAME)/node-chrome:$(MAJOR)
	docker push $(NAME)/node-chromium:$(MAJOR)
	docker push $(NAME)/node-chrome-for-testing:$(MAJOR)
	docker push $(NAME)/node-edge:$(MAJOR)
	docker push $(NAME)/node-firefox:$(MAJOR)
	docker push $(NAME)/node-docker:$(MAJOR)
	docker push $(NAME)/node-kubernetes:$(MAJOR)
	docker push $(NAME)/node-all-browsers:$(MAJOR)
	docker push $(NAME)/standalone-chrome:$(MAJOR)
	docker push $(NAME)/standalone-chromium:$(MAJOR)
	docker push $(NAME)/standalone-chrome-for-testing:$(MAJOR)
	docker push $(NAME)/standalone-edge:$(MAJOR)
	docker push $(NAME)/standalone-firefox:$(MAJOR)
	docker push $(NAME)/standalone-docker:$(MAJOR)
	docker push $(NAME)/standalone-kubernetes:$(MAJOR)
	docker push $(NAME)/standalone-all-browsers:$(MAJOR)
	docker push $(NAME)/base:$(MAJOR).$(MINOR)
	docker push $(NAME)/hub:$(MAJOR).$(MINOR)
	docker push $(NAME)/keda-external-scaler:$(MAJOR).$(MINOR)
	docker push $(NAME)/distributor:$(MAJOR).$(MINOR)
	docker push $(NAME)/router:$(MAJOR).$(MINOR)
	docker push $(NAME)/sessions:$(MAJOR).$(MINOR)
	docker push $(NAME)/session-queue:$(MAJOR).$(MINOR)
	docker push $(NAME)/event-bus:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-base:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-chrome:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-chromium:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-chrome-for-testing:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-edge:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-firefox:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-docker:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-kubernetes:$(MAJOR).$(MINOR)
	docker push $(NAME)/node-all-browsers:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-chrome:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-chromium:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-chrome-for-testing:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-edge:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-firefox:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-docker:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-kubernetes:$(MAJOR).$(MINOR)
	docker push $(NAME)/standalone-all-browsers:$(MAJOR).$(MINOR)
	docker push $(NAME)/base:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/hub:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/keda-external-scaler:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/distributor:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/router:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/sessions:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/session-queue:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/event-bus:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-base:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-chrome:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-chromium:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-chrome-for-testing:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-edge:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-firefox:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-docker:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-kubernetes:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/node-all-browsers:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-chrome:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-chromium:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-chrome-for-testing:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-edge:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-firefox:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-docker:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-kubernetes:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/standalone-all-browsers:$(MAJOR_MINOR_PATCH)
	docker push $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE)

release_ghcr:
	for image in base hub distributor router sessions session-queue event-bus \
		node-base node-chrome node-chromium node-chrome-for-testing node-edge \
		node-firefox node-docker node-kubernetes node-all-browsers \
		standalone-chrome standalone-chromium standalone-chrome-for-testing \
		standalone-edge standalone-firefox standalone-docker \
		standalone-kubernetes standalone-all-browsers keda-external-scaler; do \
		for tag in $(TAG_VERSION) $(MAJOR) $(MAJOR).$(MINOR) $(MAJOR_MINOR_PATCH); do \
			docker buildx imagetools create \
			--tag $(GHCR_NAMESPACE)/$$image:$$tag docker.io/$(NAME)/$$image:$$tag ; \
		done ; \
	done
	docker buildx imagetools create \
	  --tag $(GHCR_NAMESPACE)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) docker.io/$(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE)

start_test_site:
	@docker rm -f the-internet 2>/dev/null || true
	@docker run --rm --name the-internet -d -p 5001:5000 ndviet/the-internet:latest
	@echo "Test site started at http://localhost:5001"

test: test_chrome \
	test_chrome_standalone \
	test_chrome_standalone_java \
	test_chromium \
	test_chromium_standalone \
	test_chromium_standalone_java \
	test_chrome-for-testing \
	test_chrome-for-testing_standalone \
	test_chrome-for-testing_standalone_java \
	test_firefox \
	test_firefox_standalone \
	test_firefox_standalone_java \
	test_edge \
	test_edge_standalone \
	test_edge_standalone_java \
	test_node_all_browsers \
	test_standalone_all_browsers

test_chrome:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh NodeChrome

test_chrome_standalone:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneChrome

test_chrome_standalone_java:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/SeleniumJavaTests/bootstrap_java.sh chrome standalone-chrome

test_edge:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Microsoft Edge is only supported on linux/amd64" \
		&& PLATFORMS=linux/amd64 VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh NodeEdge \
		;; \
		*) \
		echo "Microsoft Edge doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

test_edge_standalone:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Microsoft Edge is only supported on linux/amd64" \
		&& PLATFORMS=linux/amd64 VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneEdge \
		;; \
		*) \
		echo "Microsoft Edge doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

test_edge_standalone_java:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Microsoft Edge is only supported on linux/amd64" \
		&& PLATFORMS=linux/amd64 VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/SeleniumJavaTests/bootstrap_java.sh edge standalone-edge \
		;; \
		*) \
		echo "Microsoft Edge doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

test_firefox_download_lang_packs:
	FIREFOX_VERSION=$(or $(FIREFOX_VERSION), $$(curl -sk https://product-details.mozilla.org/1.0/firefox_versions.json | jq -r '.LATEST_FIREFOX_VERSION')) ; \
	./NodeFirefox/get_lang_package.sh $$FIREFOX_VERSION ./tests/target/firefox_lang_packs

test_firefox: test_firefox_download_lang_packs
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true \
	TEST_FIREFOX_INSTALL_LANG_PACKAGE=$(or $(TEST_FIREFOX_INSTALL_LANG_PACKAGE), "true") ./tests/bootstrap.sh NodeFirefox

test_firefox_standalone:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneFirefox

test_firefox_standalone_java:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/SeleniumJavaTests/bootstrap_java.sh firefox standalone-firefox

test_chromium:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh NodeChromium

test_chromium_standalone:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneChromium

test_chromium_standalone_java:
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/SeleniumJavaTests/bootstrap_java.sh chrome standalone-chromium

test_chrome-for-testing:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Google Chrome is only supported on linux/amd64" \
		&& PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh NodeChrome-for-testing \
		;; \
		*) \
		echo "Google Chrome doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

test_chrome-for-testing_standalone:
	case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Google Chrome is only supported on linux/amd64" \
		&& PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneChrome-for-testing \
		;; \
		*) \
		echo "Google Chrome doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

test_chrome-for-testing_standalone_java:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Google Chrome is only supported on linux/amd64" \
		&& PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/SeleniumJavaTests/bootstrap_java.sh chrome standalone-chrome-for-testing \
		;; \
		*) \
		echo "Google Chrome doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac

test_node_all_browsers:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Microsoft Edge is only supported on linux/amd64" \
		&& PLATFORMS=linux/amd64 VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh NodeAllEdge \
		;; \
		*) \
		echo "Microsoft Edge doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh NodeAllChrome
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true \
	./tests/bootstrap.sh NodeAllFirefox

test_standalone_all_browsers:
	set -e; case "$(PLATFORMS)" in \
		*linux/amd64*) \
		echo "Microsoft Edge is only supported on linux/amd64" \
		&& PLATFORMS=linux/amd64 VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneAllEdge \
		;; \
		*) \
		echo "Microsoft Edge doesn't support platform $(PLATFORMS)" ; \
		;; \
	esac
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneAllFirefox
	PLATFORMS=$(PLATFORMS) VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BASE_RELEASE=$(BASE_RELEASE) BASE_VERSION=$(BASE_VERSION) BINDING_VERSION=$(BINDING_VERSION) SKIP_BUILD=true ./tests/bootstrap.sh StandaloneAllChrome

test_parallel: hub chrome firefox edge chromium video
	sudo rm -rf ./tests/tests
	sudo rm -rf ./tests/videos; mkdir -p ./tests/videos
	sudo cp -r ./charts/selenium-grid/certs ./tests/videos
	for node in DeploymentAutoscaling JobAutoscaling ; do \
		cd ./tests || true ; \
		echo TAG=$(TAG_VERSION) > .env ; \
		echo VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) >> .env ; \
		echo TEST_DELAY_AFTER_TEST=$(or $(TEST_DELAY_AFTER_TEST), 0) >> .env ; \
		echo TEST_DRAIN_AFTER_SESSION_COUNT=$(or $(TEST_DRAIN_AFTER_SESSION_COUNT), 2) >> .env ; \
		echo TEST_PARALLEL_HARDENING=$(or $(TEST_PARALLEL_HARDENING), "true") >> .env ; \
		echo TEST_PARALLEL_COUNT=$(or $(TEST_PARALLEL_COUNT), 5) >> .env ; \
		echo HUB_CHECKS_INTERVAL=$(or $(HUB_CHECKS_INTERVAL), 45) >> .env ; \
		echo LOG_LEVEL=$(or $(LOG_LEVEL), "INFO") >> .env ; \
		echo REQUEST_TIMEOUT=$(or $(REQUEST_TIMEOUT), 600) >> .env ; \
		echo NODE=$$node >> .env ; \
		echo UID=$$(id -u) >> .env ; \
		echo BINDING_VERSION=$(BINDING_VERSION) >> .env ; \
		echo BASE_VERSION=$(BASE_VERSION) >> .env ; \
		if [ "$(PLATFORMS)" = "linux/amd64" ]; then \
			echo NODE_CHROME=chrome >> .env ; \
		else \
			echo NODE_CHROME=chromium >> .env ; \
		fi; \
			echo TEST_PLATFORMS=$(PLATFORMS) >> .env ; \
			echo SELENIUM_GRID_PROTOCOL=https >> .env ; \
			echo CHART_CERT_PATH=$$(readlink -f ./videos/certs/tls.crt) >> .env ; \
			export $$(cat .env | xargs) ; \
			DOCKER_DEFAULT_PLATFORM=$(PLATFORMS) docker compose --profile $(PLATFORMS) -f docker-compose-v3-test-parallel.yml up -d --remove-orphans --no-log-prefix ; \
			RUN_IN_DOCKER_COMPOSE=true TEST_SITE=the-internet:5000 bash ./bootstrap.sh $$node ; \
			docker compose -f docker-compose-v3-test-parallel.yml down ; \
	done
	make test_video_integrity

test_video_standalone: standalone_chrome standalone_chromium standalone_firefox standalone_edge
	DOCKER_COMPOSE_FILE=docker-compose-v3-test-standalone.yml TEST_DELAY_AFTER_TEST=0 HUB_CHECKS_INTERVAL=45 make test_video

test_video_dynamic_name:
	VIDEO_FILE_NAME=auto TEST_DELAY_AFTER_TEST=0 HUB_CHECKS_INTERVAL=45 TEST_ADD_CAPS_RECORD_VIDEO=false \
	make test_video

# This should run on its own CI job. There is no need to combine it with the other tests.
# Its main purpose is to check that a video file was generated.
test_video: video hub chrome firefox edge chromium
	sudo rm -rf ./tests/tests
	sudo rm -rf ./tests/videos; mkdir -p ./tests/videos/upload
	sudo chmod -R 777 ./tests/videos
	docker_compose_file=$(or $(DOCKER_COMPOSE_FILE), docker-compose-v3-test-video.yml) ; \
	list_of_tests_amd64=$(or $(LIST_OF_TESTS_AMD64), "NodeChrome NodeChromium NodeFirefox NodeEdge") ; \
	list_of_tests_arm64=$(or $(LIST_OF_TESTS_ARM64), "NodeFirefox NodeChromium") ; \
	TEST_FIREFOX_INSTALL_LANG_PACKAGE=$(or $(TEST_FIREFOX_INSTALL_LANG_PACKAGE), "true") ; \
	if [ "$${TEST_FIREFOX_INSTALL_LANG_PACKAGE}" = "true" ]; then \
		make test_firefox_download_lang_packs ; \
	fi ; \
	if [ "$(PLATFORMS)" = "linux/amd64" ]; then \
		list_nodes="$${list_of_tests_amd64}" ; \
	else \
		list_nodes="$${list_of_tests_arm64}" ; \
	fi; \
	for node in $${list_nodes}; do \
		cd ./tests || true ; \
		echo VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) > .env ; \
		echo TAG=$(TAG_VERSION) >> .env ; \
		echo NODE=$$node >> .env ; \
		echo UID=$$(id -u) >> .env ; \
		echo BINDING_VERSION=$(BINDING_VERSION) >> .env ; \
		echo BASE_VERSION=$(BASE_VERSION) >> .env ; \
		echo TEST_DELAY_AFTER_TEST=$(or $(TEST_DELAY_AFTER_TEST), 0) >> .env ; \
		echo HUB_CHECKS_INTERVAL=$(or $(HUB_CHECKS_INTERVAL), 45) >> .env ; \
		echo SELENIUM_ENABLE_MANAGED_DOWNLOADS=$(or $(SELENIUM_ENABLE_MANAGED_DOWNLOADS), "true") >> .env ; \
		echo TEST_FIREFOX_INSTALL_LANG_PACKAGE=$${TEST_FIREFOX_INSTALL_LANG_PACKAGE} >> .env ; \
		echo BASIC_AUTH_USERNAME=$(or $(BASIC_AUTH_USERNAME), "admin") >> .env ; \
		echo BASIC_AUTH_PASSWORD=$(or $(BASIC_AUTH_PASSWORD), "admin") >> .env ; \
		echo SUB_PATH=$(or $(SUB_PATH), "/selenium") >> .env ; \
		echo TEST_ADD_CAPS_RECORD_VIDEO=$(or $(TEST_ADD_CAPS_RECORD_VIDEO), "true") >> .env ; \
		echo TEST_RETAIN_ON_FAILURE=$(or $(TEST_RETAIN_ON_FAILURE), "false") >> .env ; \
		if [ $$node = "NodeChrome" ] ; then \
			echo BROWSER=chrome >> .env ; \
			echo VIDEO_FILE_NAME=$${VIDEO_FILE_NAME:-"chrome_video.mp4"} >> .env ; \
			echo VIDEO_FILE_NAME_SUFFIX=$${VIDEO_FILE_NAME_SUFFIX:-"true"} >> .env ; \
		fi ; \
			if [ $$node = "NodeChromium" ] ; then \
				echo BROWSER=chromium >> .env ; \
				echo VIDEO_FILE_NAME=$${VIDEO_FILE_NAME:-"chromium_video.mp4"} >> .env ; \
				echo VIDEO_FILE_NAME_SUFFIX=$${VIDEO_FILE_NAME_SUFFIX:-"true"} >> .env ; \
				echo SELENIUM_GRID_TEST_HEADLESS=true >> .env ; \
			fi ; \
			if [ $$node = "NodeEdge" ] ; then \
				echo BROWSER=edge >> .env ; \
				echo VIDEO_FILE_NAME=$${VIDEO_FILE_NAME:-"edge_video.mp4"} >> .env ; \
				echo VIDEO_FILE_NAME_SUFFIX=$${VIDEO_FILE_NAME_SUFFIX:-"false"} >> .env ; \
			fi ; \
			if [ $$node = "NodeFirefox" ] ; then \
				echo BROWSER=firefox >> .env ; \
				echo VIDEO_FILE_NAME=$${VIDEO_FILE_NAME:-"firefox_video.mp4"} >> .env ; \
				echo VIDEO_FILE_NAME_SUFFIX=$${VIDEO_FILE_NAME_SUFFIX:-"true"} >> .env ; \
			fi ; \
			DOCKER_DEFAULT_PLATFORM=$(PLATFORMS) docker compose -f $${docker_compose_file} up --remove-orphans --build  --exit-code-from tests ; \
	done
	make test_video_integrity

test_node_relay: hub node_base standalone_firefox
	sudo rm -rf ./tests/tests ./tests/videos; mkdir -p ./tests/videos ; \
	if [ "$(PLATFORMS)" = "linux/amd64" ]; then \
		list_nodes="Android NodeFirefox" ; \
	else \
		list_nodes="NodeFirefox" ; \
	fi; \
	for node in $${list_nodes} ; do \
		cd ./tests || true ; \
		echo TAG=$(TAG_VERSION) > .env ; \
		echo NAMESPACE=$(NAME) >> .env ; \
		echo LOG_LEVEL=$(or $(LOG_LEVEL), "INFO") >> .env ; \
		echo REQUEST_TIMEOUT=$(or $(REQUEST_TIMEOUT), 300) >> .env ; \
		echo SESSION_TIMEOUT=$(or $(SESSION_TIMEOUT), 300) >> .env ; \
		echo ANDROID_BASED_NAME=$(or $(ANDROID_BASED_NAME),budtmo) >> .env ; \
		echo ANDROID_BASED_IMAGE=$(or $(ANDROID_BASED_IMAGE),docker-android) >> .env ; \
		echo ANDROID_BASED_TAG=$(or $(ANDROID_BASED_TAG),emulator_14.0) >> .env ; \
		echo ANDROID_PLATFORM_API=$(or $(ANDROID_PLATFORM_API),14) >> .env ; \
		echo TEST_DELAY_AFTER_TEST=$(or $(TEST_DELAY_AFTER_TEST), 0) >> .env ; \
		echo NODE=$$node >> .env ; \
		echo TEST_NODE_RELAY=$$node >> .env ; \
		echo UID=$$(id -u) >> .env ; \
		echo BINDING_VERSION=$(BINDING_VERSION) >> .env ; \
		echo BASE_VERSION=$(BASE_VERSION) >> .env ; \
		if [ $$node = "Android" ] ; then \
			echo BROWSER=firefox >> .env \
			&& echo BROWSER_NAME=firefox >> .env \
			&& echo SELENIUM_ENABLE_MANAGED_DOWNLOADS=false >> .env ; \
		fi ; \
			if [ $$node = "NodeChrome" ] ; then \
				echo BROWSER=chrome >> .env \
				&& BROWSER_NAMEchrome >> .env ; \
			fi ; \
			if [ $$node = "NodeChromium" ] ; then \
				echo BROWSER=chromium >> .env \
				&& echo BROWSER_NAME=chrome >> .env ; \
				echo SELENIUM_GRID_TEST_HEADLESS=true >> .env ; \
			fi ; \
			if [ $$node = "NodeEdge" ] ; then \
				echo BROWSER=edge >> .env \
				&& echo BROWSER_NAME=MicrosoftEdge >> .env ; \
			fi ; \
			if [ $$node = "NodeFirefox" ] ; then \
				echo BROWSER=firefox >> .env \
				&& echo BROWSER_NAME=firefox >> .env \
				&& echo SELENIUM_ENABLE_MANAGED_DOWNLOADS=$(or $(SELENIUM_ENABLE_MANAGED_DOWNLOADS), true) >> .env ; \
			fi ; \
			export $$(cat .env | xargs) ; \
			envsubst < relay_config.toml > ./videos/relay_config.toml ; \
			DOCKER_DEFAULT_PLATFORM=$(PLATFORMS) docker compose --profile $$node -f docker-compose-v3-test-node-relay.yml up --remove-orphans --no-log-prefix --build --exit-code-from tests ; \
			if [ $$? -ne 0 ]; then exit 1; fi ; \
			done

test_standalone_docker: standalone_docker
	DOCKER_COMPOSE_FILE=docker-compose-v3-test-standalone-docker.yaml CONFIG_FILE=standalone_docker_config.toml HUB_CHECKS_INTERVAL=45 TEST_CUSTOM_SPECIFIC_NAME=true \
	RECORD_STANDALONE=true GRID_URL=http://0.0.0.0:4444 LIST_OF_TESTS_AMD64="DeploymentAutoscaling" TEST_PARALLEL_HARDENING=true TEST_DELAY_AFTER_TEST=0 \
	SE_UPLOAD_RETAIN_LOCAL_FILE=true CHECK_VIDEO_SESSION_LAYOUT=true \
	SELENIUM_ENABLE_MANAGED_DOWNLOADS=true LOG_LEVEL=SEVERE SKIP_CHECK_DOWNLOADS_VOLUME=true make test_node_docker

test_standalone_docker_video_sidecar: standalone_docker
	DOCKER_COMPOSE_FILE=docker-compose-v3-test-standalone-docker.yaml CONFIG_FILE=standalone_docker_video_sidecar_config.toml HUB_CHECKS_INTERVAL=45 TEST_CUSTOM_SPECIFIC_NAME=true \
	RECORD_STANDALONE=true GRID_URL=http://0.0.0.0:4444 LIST_OF_TESTS_AMD64="DeploymentAutoscaling" TEST_PARALLEL_HARDENING=true TEST_DELAY_AFTER_TEST=0 \
	SE_UPLOAD_RETAIN_LOCAL_FILE=true CHECK_VIDEO_SESSION_LAYOUT=true \
	SELENIUM_ENABLE_MANAGED_DOWNLOADS=true LOG_LEVEL=SEVERE SKIP_CHECK_DOWNLOADS_VOLUME=true make test_node_docker

test_node_docker_video_sidecar:
	CONFIG_FILE=config_video_sidecar.toml SE_UPLOAD_RETAIN_LOCAL_FILE=true CHECK_VIDEO_SESSION_LAYOUT=true make test_node_docker

test_node_docker: hub standalone_docker standalone_chrome standalone_firefox standalone_edge standalone_chromium video
	sudo rm -rf ./tests/tests
	sudo rm -rf ./tests/videos; mkdir -p ./tests/videos/Downloads; mkdir -p ./tests/videos/upload
	sudo chmod -R 777 ./tests/videos
	docker_compose_file=$(or $(DOCKER_COMPOSE_FILE), docker-compose-v3-test-node-docker.yaml) ; \
	config_file=$(or $(CONFIG_FILE), config.toml) ; \
	list_of_tests_amd64=$(or $(LIST_OF_TESTS_AMD64), "NodeChrome NodeChromium NodeFirefox NodeEdge") ; \
	list_of_tests_arm64=$(or $(LIST_OF_TESTS_ARM64), "NodeFirefox NodeChromium") ; \
	if [ "$(PLATFORMS)" = "linux/amd64" ]; then \
		list_nodes="$${list_of_tests_amd64}" ; \
	else \
		list_nodes="$${list_of_tests_arm64}" ; \
	fi; \
	for node in $${list_nodes} ; do \
		cd tests || true ; \
		DOWNLOADS_DIR="./videos/Downloads" ; \
		sudo rm -rf $$DOWNLOADS_DIR/* ; \
		echo NAMESPACE=$(NAME) > .env ; \
		echo TAG=$(TAG_VERSION) >> .env ; \
		echo VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) >> .env ; \
		echo TEST_DRAIN_AFTER_SESSION_COUNT=$(or $(TEST_DRAIN_AFTER_SESSION_COUNT), 0) >> .env ; \
		echo TEST_PARALLEL_HARDENING=$(or $(TEST_PARALLEL_HARDENING), "false") >> .env ; \
		echo LOG_LEVEL=$(or $(LOG_LEVEL), "INFO") >> .env ; \
		echo REQUEST_TIMEOUT=$(or $(REQUEST_TIMEOUT), 300) >> .env ; \
		echo SELENIUM_ENABLE_MANAGED_DOWNLOADS=$(or $(SELENIUM_ENABLE_MANAGED_DOWNLOADS), "true") >> .env ; \
		echo TEST_DELAY_AFTER_TEST=$(or $(TEST_DELAY_AFTER_TEST), 0) >> .env ; \
		echo RECORD_STANDALONE=$(or $(RECORD_STANDALONE), "true") >> .env ; \
		echo SE_UPLOAD_RETAIN_LOCAL_FILE=$(or $(SE_UPLOAD_RETAIN_LOCAL_FILE), "false") >> .env ; \
		echo GRID_URL=$(or $(GRID_URL), "") >> .env ; \
		echo HUB_CHECKS_INTERVAL=$(or $(HUB_CHECKS_INTERVAL), 20) >> .env ; \
		echo TEST_CUSTOM_SPECIFIC_NAME=$(or $(TEST_CUSTOM_SPECIFIC_NAME), "true") >> .env ; \
		echo TEST_RETAIN_ON_FAILURE=$(or $(TEST_RETAIN_ON_FAILURE), "false") >> .env ; \
		echo NODE=$$node >> .env ; \
		echo UID=$$(id -u) >> .env ; \
		echo BINDING_VERSION=$(BINDING_VERSION) >> .env ; \
		echo BASE_VERSION=$(BASE_VERSION) >> .env ; \
		echo VIDEO_EVENT_DRIVEN=$(or $(VIDEO_EVENT_DRIVEN), "true") >> .env ; \
		if [ "$$(uname)" != "Darwin" ]; then \
			echo HOST_IP=$$(hostname -I | awk '{print $$1}') >> .env ; \
		else \
			echo HOST_IP=127.0.0.1 >> .env ; \
		fi; \
		BASIC_AUTH_USER=admin ; \
		BASIC_AUTH_PASSWORD=admin ; \
		if [ "$(PLATFORMS)" = "linux/amd64" ]; then \
			NODE_EDGE=edge ; \
			NODE_CHROME=chrome ; \
		else \
			NODE_EDGE=chromium ; \
			NODE_CHROME=chromium ; \
		fi; \
			echo BASIC_AUTH_USER=$${BASIC_AUTH_USER} >> .env ; \
			echo BASIC_AUTH_PASSWORD=$${BASIC_AUTH_PASSWORD} >> .env ; \
			echo NODE_EDGE=$${NODE_EDGE} >> .env ; \
			if [ $$node = "NodeChrome" ] ; then \
				echo NODE_CHROME=$${NODE_CHROME} >> .env ; \
			fi ; \
			if [ $$node = "NodeChromium" ] ; then \
				echo NODE_CHROME=chromium >> .env ; \
				echo SELENIUM_GRID_TEST_HEADLESS=true >> .env ; \
			else \
				echo NODE_CHROME=$${NODE_CHROME} >> .env ; \
			fi ; \
			export $$(cat .env | xargs) ; \
			envsubst < $${config_file} > ./videos/config.toml ; \
			DOCKER_DEFAULT_PLATFORM=$(PLATFORMS) docker compose -f $${docker_compose_file} up --remove-orphans --no-log-prefix --build --exit-code-from tests ; \
			if [ $$? -ne 0 ]; then exit 1; fi ; \
				if [ "$$SKIP_CHECK_DOWNLOADS_VOLUME" != "true" ] && [ "$$SELENIUM_ENABLE_MANAGED_DOWNLOADS" != "true" ] && [ -d "$$DOWNLOADS_DIR" ] && [ $$(ls -1q $$DOWNLOADS_DIR | wc -l) -eq 0 ]; then \
					echo "Mounted downloads directory is empty. Downloaded files could not be retrieved!" ; \
					exit 1 ; \
				fi ; \
	done
	if [ "$(CHECK_VIDEO_SESSION_LAYOUT)" = "true" ]; then \
		echo "Verify each recording is stored once per session under ./tests/videos/<sessionId>/" ; \
		echo "(inline must not scatter into the assets root; the external video sidecar must not double-nest)" ; \
		flat=$$(find ./tests/videos -maxdepth 1 -type f -name '*.mp4') ; \
		if [ -n "$$flat" ]; then echo "Recordings found flat in the assets root:" ; echo "$$flat" ; exit 1 ; fi ; \
			nested=$$(find ./tests/videos -mindepth 3 -type f -name '*.mp4' ! -path './tests/videos/upload/*' ! -path './tests/videos/Downloads/*') ; \
			if [ -n "$$nested" ]; then echo "Recordings nested below the per-session folder (double-nested <sessionId>/<sessionId>/):" ; echo "$$nested" ; exit 1 ; fi ; \
				session_videos=$$(find ./tests/videos -mindepth 2 -maxdepth 2 -type f -name '*.mp4' ! -path './tests/videos/upload/*' ! -path './tests/videos/Downloads/*') ; \
				if [ -z "$$session_videos" ]; then echo "No recordings found in per-session subfolders under ./tests/videos" ; exit 1 ; fi ; \
					echo "Recordings stored one per session:" ; echo "$$session_videos" ; \
				fi
	make test_video_integrity

test_custom_ca_cert:
	VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) ./tests/customCACert/bootstrap.sh

chart_cluster_setup:
	VERSION=$(TAG_VERSION) NAMESPACE=$(NAMESPACE) BUILD_DATE=$(BUILD_DATE) ./tests/charts/make/chart_cluster_setup.sh
	make set_containerd_image_store

chart_cluster_cleanup:
	./tests/charts/make/chart_cluster_cleanup.sh

chart_build_nightly: copy_dashboards
	VERSION=$(CHART_VERSION_NIGHTLY) ./tests/charts/make/chart_build.sh

chart_build: copy_dashboards
	VERSION=$(TAG_VERSION) ./tests/charts/make/chart_build.sh

chart_release:
	NAMESPACE=$(NAMESPACE) ./tests/charts/make/chart_release.sh

test_video_integrity:
	# Using ffmpeg to verify file integrity
	# https://superuser.com/questions/100288/how-can-i-check-the-integrity-of-a-video-file-avi-mpeg-mp4
	list_files=$$(find ./tests/videos -type f -name "*.mp4"); \
	echo "::warning:: Number of video files: $$(echo $$list_files | wc -w)"; \
	number_corrupted_files=0; \
	if [ -z "$$list_files" ]; then \
		echo "No video files found"; \
		exit 1; \
	fi; \
	for file in $$list_files; do \
		echo "Checking video file: $$file"; \
		docker run --rm -u $$(id -u) -v $$(pwd):$$(pwd) -w $$(pwd) --entrypoint="" $(NAME)/video:$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) ffmpeg -v error -i "$$file" -f null - ; \
		if [ $$? -ne 0 ]; then \
			echo "Video file $$file is corrupted"; \
			number_corrupted_files=$$((number_corrupted_files+1)); \
		fi; \
	  echo "------"; \
	done; \
	if [ $$((number_corrupted_files)) -gt 0 ]; then \
		echo "Number of corrupted video files: $$number_corrupted_files"; \
		exit 1; \
	fi

chart_test_template:
	./tests/charts/bootstrap.sh

chart_render_template:
	RENDER_HELM_TEMPLATE_ONLY=true NAMESPACE=$(NAME) KEDA_TAG_VERSION=$(KEDA_TAG_VERSION) BUILD_DATE=$(BUILD_DATE) make chart_test_autoscaling_disabled chart_test_autoscaling_deployment_https chart_test_autoscaling_deployment chart_test_autoscaling_job_https chart_test_autoscaling_job_hostname chart_test_autoscaling_job chart_test_autoscaling_job_externalScaler chart_test_autoscaling_playwright_connect_grid chart_test_autoscaling_job_relay

chart_test_autoscaling_disabled:
	PLATFORMS=$(PLATFORMS) TEST_CHROMIUM=true RELEASE_NAME=selenium SELENIUM_GRID_AUTOSCALING=false CHART_ENABLE_TRACING=true TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) TEST_CUSTOM_SPECIFIC_NAME=true SELENIUM_GRID_MONITORING=false \
	SECURE_INGRESS_ONLY_GENERATE=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -I | cut -d' ' -f1) SELENIUM_GRID_PORT=443 EXTERNAL_UPLOADER_CONFIG=true \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_nodeChromium_enableTracing_secureIngress_generateCerts_ingressPublicIP_subPath.yaml" \
	./tests/charts/make/chart_test.sh NoAutoscaling

chart_test_autoscaling_deployment_https:
	PLATFORMS=$(PLATFORMS) CHART_FULL_DISTRIBUTED_MODE=true CHART_ENABLE_BASIC_AUTH=true TEST_EXTERNAL_DATASTORE=postgresql TEST_MULTIPLE_VERSIONS=false AUTOSCALING_COOLDOWN_PERIOD=30 SELENIUM_GRID_MONITORING=false TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) \
	SECURE_INGRESS_ONLY_DEFAULT=true INGRESS_DISABLE_USE_HTTP2=true SELENIUM_GRID_PROTOCOL=https CHART_ENABLE_INGRESS_HOSTNAME=true SELENIUM_GRID_PORT=443 \
	SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=0 MAX_SESSIONS_FIREFOX=1 MAX_SESSIONS_EDGE=1 MAX_SESSIONS_CHROME=1 TEST_NODE_DRAIN_AFTER_SESSION_COUNT=3 TEST_NAME_OVERRIDE=true \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_fullDistributed_basicAuth_secureIngress_defaultCerts_ingressHostName_disableHttp2_autoScaling_patchKEDA_scaledObject_subPath.yaml" \
	./tests/charts/make/chart_test.sh DeploymentAutoscaling

chart_test_autoscaling_deployment:
	PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true RELEASE_NAME=selenium CHART_ENABLE_TRACING=true TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) AUTOSCALING_COOLDOWN_PERIOD=30 \
	TRACING_EXPORTER_ENDPOINT=$(TRACING_EXPORTER_ENDPOINT) TEST_CUSTOM_SPECIFIC_NAME=true \
	SECURE_CONNECTION_SERVER=true SECURE_USE_EXTERNAL_CERT=true SERVICE_TYPE_NODEPORT=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -I | cut -d' ' -f1) SELENIUM_GRID_PORT=31444 \
	SELENIUM_GRID_AUTOSCALING_MIN_REPLICA=1 SET_MAX_REPLICAS=3 TEST_DELAY_AFTER_TEST=0 TEST_NODE_DRAIN_AFTER_SESSION_COUNT=3 SELENIUM_GRID_MONITORING=false \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_prefixSelenium_enableTracing_secureServer_externalCerts_nodePort_autoScaling_scaledObject_existingKEDA_subPath.yaml" \
	./tests/charts/make/chart_test.sh DeploymentAutoscaling

chart_test_autoscaling_job_https:
	PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true TEST_CHROMIUM=true RELEASE_NAME=selenium CHART_ENABLE_BASIC_AUTH=true SELENIUM_GRID_MONITORING=false TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) TEST_MULTIPLE_PLATFORMS=true \
	SECURE_CONNECTION_SERVER=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_PORT=443 SUB_PATH=/ \
	MAX_SESSIONS_FIREFOX=1 MAX_SESSIONS_EDGE=2 MAX_SESSIONS_CHROME=3 TEST_NAME_OVERRIDE=true \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) EXTERNAL_UPLOADER_CONFIG=true \
	TEMPLATE_OUTPUT_FILENAME="k8s_prefixSelenium_basicAuth_secureServer_autoScaling_scaledJob_existingKEDA.yaml" \
	./tests/charts/make/chart_test.sh JobAutoscaling

chart_test_autoscaling_job_hostname:
	PLATFORMS=$(PLATFORMS) CHART_ENABLE_TRACING=true CHART_ENABLE_BASIC_AUTH=true BASIC_AUTH_EMBEDDED_URL=true TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) TEST_MULTIPLE_PLATFORMS=true \
	TRACING_EXPORTER_ENDPOINT=$(TRACING_EXPORTER_ENDPOINT) \
	SECURE_INGRESS_ONLY_DEFAULT=true SECURE_USE_EXTERNAL_CERT=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -I | cut -d' ' -f1) SELENIUM_GRID_PORT=443 \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_enableTracing_basicAuth_secureIngress_externalCerts_ingressPublicIP_autoScaling_originKEDA_scaledJob_subPath.yaml" \
	./tests/charts/make/chart_test.sh JobAutoscaling

chart_test_autoscaling_job_relay:
	PLATFORMS=$(PLATFORMS) CHART_ENABLE_TRACING=true CHART_ENABLE_BASIC_AUTH=true SELENIUM_GRID_MONITORING=false TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) \
	TEST_MULTIPLE_PLATFORMS=true TEST_MULTIPLE_PLATFORMS_RELAY=false CLEAR_POD_HISTORY=true TEST_SITE=the-internet.herokuapp.com \
	SECURE_INGRESS_ONLY_DEFAULT=true SECURE_USE_EXTERNAL_CERT=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -I | cut -d' ' -f1) SELENIUM_GRID_PORT=443 \
	SET_MAX_REPLICAS=3 SET_SESSION_REQUEST_TIMEOUT=600 \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_enableTracing_basicAuth_secureIngress_externalCerts_ingressPublicIP_autoScaling_relay_node_scaledJob_subPath.yaml" \
	./tests/charts/make/chart_test.sh JobAutoscaling

chart_test_autoscaling_job_multiple_versions_without_explicit:
	TEST_MULTIPLE_VERSIONS=false TEST_MULTIPLE_VERSIONS_EXPLICIT=false make chart_test_autoscaling_job

chart_test_autoscaling_job_without_multiple_versions:
	TEST_MULTIPLE_VERSIONS=false make chart_test_autoscaling_job

chart_test_autoscaling_job:
	PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true RELEASE_NAME=selenium CHART_ENABLE_TRACING=true CHART_FULL_DISTRIBUTED_MODE=true SELENIUM_GRID_MONITORING=false TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) \
	CLEAR_POD_HISTORY=true TEST_MULTIPLE_VERSIONS=$(or $(TEST_MULTIPLE_VERSIONS), "false") TEST_MULTIPLE_VERSIONS_EXPLICIT=$(or $(TEST_MULTIPLE_VERSIONS_EXPLICIT), "false") \
	SECURE_INGRESS_ONLY_CONFIG_INLINE=true SECURE_USE_EXTERNAL_CERT=true CHART_ENABLE_INGRESS_HOSTNAME=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=selenium-grid.prod SUB_PATH=/ SELENIUM_GRID_PORT=443 \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_fullDistributed_secureIngress_externalCerts_ingressHostName_ingressTLSInline_autoScaling_scaledJob_existingKEDA_prefixSelenium_nodeChromium_enableTracing.yaml" \
	./tests/charts/make/chart_test.sh JobAutoscaling

chart_test_autoscaling_playwright_connect_grid:
	PLATFORMS=$(PLATFORMS) CHART_FULL_DISTRIBUTED_MODE=true CHART_ENABLE_BASIC_AUTH=true TEST_EXTERNAL_DATASTORE=redis MATRIX_TESTS=CDPTests TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) TEST_MULTIPLE_PLATFORMS=true TEST_VIDEO_RECORDER_SIDECAR=true \
	BASIC_AUTH_USERNAME=docker-selenium BASIC_AUTH_PASSWORD=2NMI4jdBi6k7bENoeUfV25295VvzwAE9chM24a+2VL95uOHozo \
	SECURE_INGRESS_ONLY_DEFAULT=true SECURE_USE_EXTERNAL_CERT=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=$$(hostname -I | cut -d' ' -f1) SELENIUM_GRID_PORT=443 \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_playwright_connect_grid_basicAuth_secureIngress_ingressPublicIP_autoScaling_patchKEDA.yaml" \
	./tests/charts/make/chart_test.sh JobAutoscaling

chart_test_autoscaling_job_externalScaler:
	PLATFORMS=$(PLATFORMS) TEST_EXISTING_KEDA=true TEST_EXTERNAL_SCALER=true RELEASE_NAME=selenium CHART_ENABLE_TRACING=false CHART_FULL_DISTRIBUTED_MODE=false SELENIUM_GRID_MONITORING=false TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) SCALING_STRATEGY=accurate \
	CLEAR_POD_HISTORY=true TEST_MULTIPLE_VERSIONS=$(or $(TEST_MULTIPLE_VERSIONS), "false") TEST_MULTIPLE_VERSIONS_EXPLICIT=$(or $(TEST_MULTIPLE_VERSIONS_EXPLICIT), "false") \
	SECURE_INGRESS_ONLY_CONFIG_INLINE=true SECURE_USE_EXTERNAL_CERT=true CHART_ENABLE_INGRESS_HOSTNAME=true SELENIUM_GRID_PROTOCOL=https SELENIUM_GRID_HOST=selenium-grid.prod SUB_PATH=/ SELENIUM_GRID_PORT=443 \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	TEMPLATE_OUTPUT_FILENAME="k8s_fullDistributed_secureIngress_externalCerts_ingressHostName_ingressTLSInline_autoScaling_scaledJob_externalScaler_prefixSelenium_nodeChromium.yaml" \
	./tests/charts/make/chart_test.sh JobAutoscaling

test_k8s_autoscaling_job_count_strategy_default_in_chaos:
	MATRIX_TESTS=AutoScalingTestsScaleChaos \
	make test_k8s_autoscaling_job_count_strategy_default

test_k8s_autoscaling_job_count_strategy_default_with_node_max_sessions:
	TEST_NODE_MAX_SESSIONS=3 \
	make test_k8s_autoscaling_job_count_strategy_default

test_k8s_autoscaling_job_count_strategy_default:
	MATRIX_TESTS=$(or $(MATRIX_TESTS), "AutoscalingTestsScaleUp") SCALING_STRATEGY=$(or $(SCALING_STRATEGY), "default") TEST_MULTIPLE_PLATFORMS=true \
	PLATFORMS=$(PLATFORMS) RELEASE_NAME=selenium TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) SELENIUM_GRID_PROTOCOL=http SELENIUM_GRID_HOST=localhost SELENIUM_GRID_PORT=80 \
	SELENIUM_GRID_MONITORING=false CLEAR_POD_HISTORY=true SET_MAX_REPLICAS=100 ENABLE_VIDEO_RECORDER=false \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	./tests/charts/make/chart_test.sh JobAutoscaling

test_k8s_autoscaling_job_count_strategy_accurate_in_chaos:
	MATRIX_TESTS=AutoScalingTestsScaleChaos SCALING_STRATEGY=accurate \
	make test_k8s_autoscaling_job_count_strategy_default

test_k8s_autoscaling_job_count_strategy_accurate_with_node_max_sessions:
	TEST_NODE_MAX_SESSIONS=3 SCALING_STRATEGY=accurate \
	make test_k8s_autoscaling_job_count_strategy_default

test_k8s_autoscaling_job_count_strategy_accurate:
	SCALING_STRATEGY=accurate \
	make test_k8s_autoscaling_job_count_strategy_default

test_k8s_autoscaling_deployment_count_in_chaos:
	MATRIX_TESTS=AutoScalingTestsScaleChaos \
	make test_k8s_autoscaling_deployment_count

test_k8s_autoscaling_deployment_count_with_node_max_sessions:
	TEST_NODE_MAX_SESSIONS=3 \
	make test_k8s_autoscaling_deployment_count

test_k8s_autoscaling_deployment_count:
	MATRIX_TESTS=$(or $(MATRIX_TESTS), "AutoscalingTestsScaleUp") TEST_MULTIPLE_PLATFORMS=true \
	PLATFORMS=$(PLATFORMS) RELEASE_NAME=selenium TEST_PATCHED_KEDA=$(TEST_PATCHED_KEDA) SELENIUM_GRID_PROTOCOL=http SELENIUM_GRID_HOST=localhost SELENIUM_GRID_PORT=80 \
	SELENIUM_GRID_MONITORING=false CLEAR_POD_HISTORY=true SET_MAX_REPLICAS=100 ENABLE_VIDEO_RECORDER=false \
	VERSION=$(TAG_VERSION) VIDEO_TAG=$(FFMPEG_TAG_VERSION)-$(BUILD_DATE) KEDA_BASED_NAME=$(KEDA_BASED_NAME) KEDA_BASED_TAG=$(KEDA_BASED_TAG) NAMESPACE=$(NAMESPACE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	./tests/charts/make/chart_test.sh DeploymentAutoscaling

chart_test_delete:
	helm del test -n selenium || true
	helm del selenium -n selenium || true
	helm del keda -n keda || true

# Dynamic Grid on Kubernetes, deploys kubernetes/DynamicGrid manifests with the images built locally.
# Requires a cluster with those images available, see `make chart_cluster_setup`.
test_k8s_dynamic_grid: test_k8s_dynamic_grid_standalone test_k8s_dynamic_grid_hub_node

test_k8s_dynamic_grid_standalone:
	PLATFORMS=$(PLATFORMS) NAMESPACE=$(NAMESPACE) VERSION=$(TAG_VERSION) BUILD_DATE=$(BUILD_DATE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	./tests/k8s/make/dynamic_grid_test.sh Standalone

test_k8s_dynamic_grid_hub_node:
	PLATFORMS=$(PLATFORMS) NAMESPACE=$(NAMESPACE) VERSION=$(TAG_VERSION) BUILD_DATE=$(BUILD_DATE) BINDING_VERSION=$(BINDING_VERSION) BASE_VERSION=$(BASE_VERSION) \
	./tests/k8s/make/dynamic_grid_test.sh HubNode

.PHONY: \
	all \
	base \
	build \
	build_exporter \
	test_exporter \
	test_scaler \
	test_go_modules \
	update_go \
	ci \
	chrome \
	chromium \
	edge \
	firefox \
	docker \
	kubernetes \
	hub \
	distributor \
	router \
	sessions \
	sessionqueue \
	event_bus \
	node_base \
	release \
	standalone_chrome \
	standalone_chromium \
	standalone_edge \
	standalone_firefox \
	standalone_docker \
	standalone_kubernetes \
	tag_latest \
	tag_and_push_browser_images \
	test \
	video

# Placed last on purpose: GNU Make lets the last definition of a target win, so
# these no-ops must come after the real build recipes above. Defining them at all
# only happens when SKIP_BUILD=true, so an ordinary `make build` never sees them
# and never prints an override warning.
ifeq ($(strip $(SKIP_BUILD)),true)
$(SKIP_BUILD_TARGETS):
	@echo "SKIP_BUILD=true: using the prebuilt image for '$@'"
endif