Files
inecs 540675597a Add SemVer VERSION, Jenkins CI/CD, and release 0.1.1.
Ship Harbor/Hub push with latest+version tags, deploy to ovirt.devops.org.ru, and show the package version badge in Help → About.
2026-07-28 00:56:52 +03:00

263 lines
10 KiB
Makefile
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
COMPOSE ?= docker compose
SERVICE_DEV := dev
SERVICE_SIM := simulator
PYTEST_OFFLINE := -m "not integration and not compatibility"
# Docker Hub release image (runtime target only — not the local bind-mount "dev" image).
DOCKERHUB_USER ?= inecs
IMAGE_NAME ?= ovirt-api-simulator
VERSION ?= $(shell cat VERSION 2>/dev/null || echo 0.1.0)
DOCKER_IMAGE ?= $(DOCKERHUB_USER)/$(IMAGE_NAME)
PUSH_LATEST ?= 1
COMPOSE_RELEASE ?= $(COMPOSE) -f docker-compose.release.yml
HELM_CHART ?= ./helm/ovirt-api-simulator
LAB ?= ./pulumi-tests
# Remotes used by `make push` (GitHub + antropoff).
GIT_REMOTES ?= origin antropoff
# Preferred host ports for `make up-local` (override / .env stay gitignored).
LOCAL_ENGINE_PORT ?= 6443
LOCAL_UI_PORT ?= 6080
.PHONY: bump-patch bump-minor version-commit help install format lint typecheck test test-unit test-integration test-contract \
test-surface test-versions coverage up down restart logs seed seed-small seed-large seed-big seed-demo \
audit-seed-dump smoke clean ci shell \
helm-template generate-packs \
release release-build release-up release-down release-seed \
test-pulumi-smoke test-pulumi pulumi-tests \
test-smoke-all test-all clean-test-resources push up-local down-local
help: ## Show available commands
@awk 'BEGIN {FS = ":.*## "}; /^[a-zA-Z0-9_-]+:.*## / {printf "%-22s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
@echo
@echo "Version: $$(cat VERSION 2>/dev/null || echo 0.1.0) (make bump-patch | bump-minor)"
install: ## Build runtime and development images
@test -f .env || cp .env.example .env
$(COMPOSE) build simulator $(SERVICE_DEV)
generate-packs: ## Regenerate contracts/ovirt series packs
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) python tools/ovirt_api_inventory/generate_packs.py
format: ## Format Python sources
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) ruff format .
lint: ## Run Ruff lint checks
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) ruff check app tests
typecheck: ## Run strict mypy checks
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) mypy app/ovirt app/web/routes.py app/main.py app/config.py app/lifespan.py
test: ## Run offline unit and contract tests
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest $(PYTEST_OFFLINE)
test-unit: ## Run unit tests
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest tests/unit tests/ovirt -q
test-integration: ## Run tests that require PostgreSQL
@test -f .env || cp .env.example .env
$(COMPOSE) up -d postgres migrate
$(COMPOSE) run --rm $(SERVICE_DEV) pytest -m integration tests/ovirt -q
test-contract: ## Validate oVirt contract packs
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest -m contract tests/ovirt -q
test-surface: ## Probe Engine API surface across series
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
$(COMPOSE) run --rm --no-deps --entrypoint python $(SERVICE_SIM) -m pytest tests/ovirt -q --tb=line
test-versions: ## All Engine series packs with seeded inventory assertions
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --wait
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile minimal
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest -m integration tests/ovirt/test_api_versions.py -q --tb=short
coverage: ## Offline coverage
$(COMPOSE) run --rm --no-deps $(SERVICE_DEV) pytest $(PYTEST_OFFLINE) --cov=app/ovirt --cov-report=term-missing
up: ## Start PostgreSQL, simulator, and Engine gateway
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --build --wait
# Writes gitignored docker-compose.override.yml (+ syncs ports into .env) when
# default 443/5000 are busy (common on macOS). Compose auto-merges the override.
up-local: ## Start stack with local port override (not committed)
@set -e; \
test -f .env || cp .env.example .env; \
pick_port() { \
preferred="$$1"; shift; \
for p in "$$preferred" "$$@"; do \
if ! lsof -nP -iTCP:"$$p" -sTCP:LISTEN >/dev/null 2>&1; then \
echo "$$p"; return 0; \
fi; \
done; \
echo "No free port among: $$preferred $$*" >&2; exit 1; \
}; \
engine_port=$$(pick_port "$(LOCAL_ENGINE_PORT)" 6443 7443 8443 16443); \
ui_port=$$(pick_port "$(LOCAL_UI_PORT)" 6080 7080 8080 16080); \
printf '%s\n' \
'# Generated by `make up-local` — gitignored, do not commit.' \
'services:' \
' api-gateway:' \
' ports:' \
" - \"$${engine_port}:443\"" \
" - \"$${ui_port}:5000\"" \
> docker-compose.override.yml; \
if grep -q '^OVIRT_ENGINE_PORT=' .env; then \
sed -i.bak -e "s/^OVIRT_ENGINE_PORT=.*/OVIRT_ENGINE_PORT=$${engine_port}/" \
-e "s/^OVIRT_UI_PORT=.*/OVIRT_UI_PORT=$${ui_port}/" .env && rm -f .env.bak; \
else \
printf '\nOVIRT_ENGINE_PORT=%s\nOVIRT_UI_PORT=%s\n' "$$engine_port" "$$ui_port" >> .env; \
fi; \
echo "Local ports → Engine https://127.0.0.1:$${engine_port} UI http://127.0.0.1:$${ui_port}"; \
echo "Wrote docker-compose.override.yml (gitignored)"; \
$(COMPOSE) up -d --build --wait; \
echo "up-local ok"
down-local: ## Stop stack and remove gitignored local port override
@$(COMPOSE) down
@rm -f docker-compose.override.yml
@if [ -f .env ]; then \
if grep -q '^OVIRT_ENGINE_PORT=' .env; then \
sed -i.bak -e 's/^OVIRT_ENGINE_PORT=.*/OVIRT_ENGINE_PORT=443/' \
-e 's/^OVIRT_UI_PORT=.*/OVIRT_UI_PORT=5000/' .env && rm -f .env.bak; \
fi; \
fi
@echo "down-local ok (removed docker-compose.override.yml)"
down: ## Stop local services
$(COMPOSE) down
restart: ## Rebuild and restart the stack
@test -f .env || cp .env.example .env
$(COMPOSE) up -d --build --force-recreate --wait
logs: ## Follow logs
$(COMPOSE) logs -f
seed: ## Seed minimal lab
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile minimal
seed-small: ## Seed small cluster (3 hosts · 50 VMs)
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile small
seed-large: ## Seed large cluster (10 hosts · 1000 VMs)
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile large
seed-big: ## Seed big cluster (30 hosts · 2000 VMs)
$(COMPOSE) run --rm --entrypoint python $(SERVICE_SIM) -m app.ovirt.seed_cli --profile big
seed-demo: seed-large ## Alias: large cluster (legacy name)
audit-seed-dump: ## Contract dump audit (collections+entities) vs live Engine
@set -a; [ -f .env ] && . ./.env; set +a; \
python3 tools/audit_seed_dump.py \
"https://127.0.0.1:$${OVIRT_ENGINE_PORT:-443}" \
"$${OVIRT_SERIES:-4.5}"
smoke: ## Quick Engine auth + list VMs smoke
@set -a; [ -f .env ] && . ./.env; set +a; \
curl -skf -u 'admin@internal:secret' -H 'Accept: application/json' -H 'Version: 4' \
"https://127.0.0.1:$${OVIRT_ENGINE_PORT:-443}/ovirt-engine/api/vms" >/dev/null
@echo "smoke ok"
helm-template: ## Render Helm chart
helm template ovirt-sim $(HELM_CHART)
clean: ## Remove caches
rm -rf .pytest_cache .mypy_cache .ruff_cache .coverage coverage.xml
find . -type d -name __pycache__ -prune -exec rm -rf {} +
ci: format lint test-unit ## Local CI gate
shell: ## Dev shell in container
$(COMPOSE) run --rm $(SERVICE_DEV) bash
release-build: ## Build the runtime image tagged for Docker Hub (no push)
@test -n "$(VERSION)" || (echo "VERSION is empty; set VERSION=... or version in pyproject.toml" >&2; exit 1)
@echo "Building $(DOCKER_IMAGE):$(VERSION) (target=runtime)"
docker build \
--target runtime \
--build-arg APP_VERSION=$(VERSION) \
-t $(DOCKER_IMAGE):$(VERSION) \
$(if $(filter 1 true yes,$(PUSH_LATEST)),-t $(DOCKER_IMAGE):latest,) \
.
release: release-build ## Build and push the runtime image to Docker Hub
@echo "Pushing $(DOCKER_IMAGE):$(VERSION)"
@docker push $(DOCKER_IMAGE):$(VERSION)
@if [ "$(PUSH_LATEST)" = "1" ] || [ "$(PUSH_LATEST)" = "true" ] || [ "$(PUSH_LATEST)" = "yes" ]; then \
echo "Pushing $(DOCKER_IMAGE):latest"; \
docker push $(DOCKER_IMAGE):latest; \
fi
@echo "Released $(DOCKER_IMAGE):$(VERSION)$(if $(filter 1 true yes,$(PUSH_LATEST)), and $(DOCKER_IMAGE):latest,)"
release-up: ## Pull and start the published Hub stack (docker-compose.release.yml)
IMAGE_TAG="$${IMAGE_TAG:-$(VERSION)}" DOCKER_IMAGE="$(DOCKER_IMAGE)" $(COMPOSE_RELEASE) pull
IMAGE_TAG="$${IMAGE_TAG:-$(VERSION)}" DOCKER_IMAGE="$(DOCKER_IMAGE)" $(COMPOSE_RELEASE) up -d --wait
release-down: ## Stop the published Hub stack
$(COMPOSE_RELEASE) down
release-seed: ## Seed the published Hub stack (PROFILE=minimal by default)
SEED_PROFILE="$${PROFILE:-minimal}" IMAGE_TAG="$${IMAGE_TAG:-$(VERSION)}" DOCKER_IMAGE="$(DOCKER_IMAGE)" \
$(COMPOSE_RELEASE) run --rm --entrypoint python simulator -m app.ovirt.seed_cli --profile "$${PROFILE:-minimal}"
# --- Pulumi contract-coverage lab (pulumi-tests) ---
test-pulumi-smoke: ## Pulumi contract-coverage smoke
$(MAKE) -C $(LAB) test-pulumi-smoke
test-pulumi: ## Pulumi full contract coverage (all series × all ops)
$(MAKE) -C $(LAB) test-pulumi
pulumi-tests: test-pulumi ## Alias: full Pulumi contract coverage suite
test-smoke-all: ## Client lab smoke
$(MAKE) -C $(LAB) test-smoke-all
test-all: ## Client lab full suite (Pulumi contract coverage)
$(MAKE) -C $(LAB) test-all
clean-test-resources: ## Cleanup lab-created resources
$(MAKE) -C $(LAB) clean-test-resources
# --- Git: stage, commit (prompt), push to both remotes ---
# Multi-line commit: paste message, then Ctrl-D (same UX as proxmox-api-simulator).
# Optional: make push MSG='one-line message'
bump-patch: ## VERSION +0.0.1 (pyproject + Helm)
@PYTHONPATH=. python3 scripts/bump_version.py patch
@echo "VERSION → $$(cat VERSION)"
bump-minor: ## VERSION +0.1.0 (pyproject + Helm)
@PYTHONPATH=. python3 scripts/bump_version.py minor
@echo "VERSION → $$(cat VERSION)"
version-commit: ## Stage version files and commit "Bump version to …"
@git add VERSION pyproject.toml helm/ovirt-api-simulator/Chart.yaml helm/ovirt-api-simulator/values.yaml
@if git diff --cached --quiet; then \
echo "Nothing to commit for version files."; \
else \
git commit -m "Bump version to $$(cat VERSION)."; \
fi
push: ## bump-patch + commit version + push origin
@$(MAKE) bump-patch
@$(MAKE) version-commit
@set -e; \
git add .; \
echo "=== staged ==="; \
git status --short; \
echo; \
if git diff --cached --quiet; then \
echo "Nothing else to commit — pushing current branch."; \
else \
echo "Enter commit message for remaining changes, then Ctrl-D:"; \
msg=$$(cat </dev/tty); \
if [ -z "$$msg" ]; then echo "Empty commit message, aborting." >&2; exit 1; fi; \
git commit -m "$$msg"; \
fi; \
echo "Pushing to both remotes:"; \
git remote get-url --push --all origin | sed 's/^/ - /'; \
git push origin HEAD