Add Gitea Actions workflows, CI config, and docs
Some checks failed
Docker / docker (push) Successful in 6s
Security / security (push) Successful in 6s
Deploy / deploy-local-runner (push) Has been cancelled
CI / ci (push) Successful in 1m42s
Deploy / deploy-ssh (push) Successful in 7s

This commit is contained in:
2026-02-28 20:40:14 +01:00
parent 3b48b39561
commit 8cadb2d216
35 changed files with 3216 additions and 0 deletions

132
Makefile Normal file
View File

@@ -0,0 +1,132 @@
# =============================================================================
# Makefile — Common development targets
# =============================================================================
# Reads .ci/config.env for settings. All targets are fail-safe:
# they skip gracefully if tools or files are not present.
# =============================================================================
SHELL := /bin/bash
.DEFAULT_GOAL := help
# Load config if it exists
-include .ci/config.env
export
# Defaults if config is missing
ENABLE_DOCKER ?= false
DOCKER_PUSH ?= false
REGISTRY_HOST ?= git.hiddenden.cafe
IMAGE_OWNER ?= auto
IMAGE_NAME ?= auto
# Derive image owner/name dynamically if set to "auto"
_OWNER := $(if $(filter auto,$(IMAGE_OWNER)),$(shell basename $$(dirname $$(pwd))),$(IMAGE_OWNER))
_NAME := $(if $(filter auto,$(IMAGE_NAME)),$(shell basename $$(pwd)),$(IMAGE_NAME))
_IMAGE := $(REGISTRY_HOST)/$(_OWNER)/$(_NAME)
# ---------------------------------------------------------------------------
.PHONY: help
help: ## Show this help message
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
# ---------------------------------------------------------------------------
# Code quality
# ---------------------------------------------------------------------------
.PHONY: fmt
fmt: ## Format code (Python: black/ruff; JS: prettier)
@if command -v ruff >/dev/null 2>&1; then \
echo ">>> ruff format ."; ruff format .; \
elif command -v black >/dev/null 2>&1; then \
echo ">>> black ."; black .; \
else \
echo "SKIP: no Python formatter found (install ruff or black)"; \
fi
@if [ -f package.json ] && command -v npx >/dev/null 2>&1; then \
if npx --no-install prettier --version >/dev/null 2>&1; then \
echo ">>> npx prettier --write ."; npx prettier --write .; \
else \
echo "SKIP: prettier not installed"; \
fi \
fi
.PHONY: lint
lint: ## Run linters (Python: ruff/flake8; JS: eslint)
@if command -v ruff >/dev/null 2>&1; then \
echo ">>> ruff check ."; ruff check .; \
elif command -v flake8 >/dev/null 2>&1; then \
echo ">>> flake8 ."; flake8 .; \
else \
echo "SKIP: no Python linter found (install ruff or flake8)"; \
fi
@if [ -f package.json ] && command -v npx >/dev/null 2>&1; then \
if npx --no-install eslint --version >/dev/null 2>&1; then \
echo ">>> npx eslint ."; npx eslint .; \
else \
echo "SKIP: eslint not installed"; \
fi \
fi
.PHONY: test
test: ## Run tests (Python: pytest; JS: npm test)
@if [ -d tests ] || [ -f pytest.ini ] || [ -f pyproject.toml ]; then \
if command -v pytest >/dev/null 2>&1; then \
echo ">>> pytest"; pytest; \
else \
echo "SKIP: pytest not installed"; \
fi \
else \
echo "SKIP: no Python tests detected"; \
fi
@if [ -f package.json ]; then \
if grep -q '"test"' package.json 2>/dev/null; then \
echo ">>> npm test"; npm test; \
else \
echo "SKIP: no 'test' script in package.json"; \
fi \
fi
# ---------------------------------------------------------------------------
# Build
# ---------------------------------------------------------------------------
.PHONY: build
build: ## Build the project (JS: npm run build; Python: pip install -e .)
@if [ -f package.json ] && grep -q '"build"' package.json 2>/dev/null; then \
echo ">>> npm run build"; npm run build; \
elif [ -f setup.py ] || [ -f pyproject.toml ]; then \
echo ">>> pip install -e ."; pip install -e .; \
else \
echo "SKIP: no build step detected"; \
fi
# ---------------------------------------------------------------------------
# Docker
# ---------------------------------------------------------------------------
.PHONY: docker-build
docker-build: ## Build Docker image
@if [ "$(ENABLE_DOCKER)" != "true" ]; then \
echo "SKIP: ENABLE_DOCKER is not true"; exit 0; \
fi
@if [ -f Dockerfile ]; then \
echo ">>> docker build -t $(_IMAGE):local ."; \
docker build -t "$(_IMAGE):local" .; \
elif [ -f docker-compose.yml ]; then \
echo ">>> docker compose build"; \
docker compose build; \
else \
echo "SKIP: no Dockerfile or docker-compose.yml found"; \
fi
.PHONY: docker-push
docker-push: ## Push Docker image (requires DOCKER_PUSH=true)
@if [ "$(DOCKER_PUSH)" != "true" ]; then \
echo "ABORT: DOCKER_PUSH is not true in .ci/config.env"; \
echo "Set DOCKER_PUSH=true to enable pushing."; \
exit 1; \
fi
@echo ">>> docker push $(_IMAGE):local"
docker push "$(_IMAGE):local"