Files
cameleer-server/.claude/rules/cicd.md
hsiegeln dbf67e7298
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 3m12s
CI / docker (push) Successful in 2m36s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 52s
docs(rules): document the buildtime/public registry split
Future-proofs against well-meaning "fixes" that would re-align inconsistent
hostnames. CI keeps pushing to gitea.siegeln.net; runtime defaults speak
registry.cameleer.io (the public alias of the same registry). Both forms
of the same image coexist intentionally during the institutionalization
period.

- CLAUDE.md: new "Registry naming (buildtime vs public)" section between
  Related Project and Modules; loader-image default mention now says
  registry.cameleer.io with an inline cross-reference; license-API note
  flags that com.cameleer:cameleer-common stays on the agent repo's
  groupId until that project follows the same flip
- .claude/rules/cicd.md: registry line now names both hostnames and points
  at the new CLAUDE.md section

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 16:50:37 +02:00

3.6 KiB

paths
paths
.gitea/**
deploy/**
Dockerfile
docker-entrypoint.sh

CI/CD & Deployment

  • CI workflow: .gitea/workflows/ci.yml — build -> docker -> deploy on push to main or feature branches. paths-ignore skips the whole pipeline for docs-only / .planning/ / .claude/ / *.md changes (push and PR triggers).
  • Build step skips integration tests (-DskipITs) — Testcontainers needs Docker daemon
  • Build caches (parallel actions/cache@v4 steps in the build job): ~/.m2/repository (key on all pom.xml), ~/.npm (key on ui/package-lock.json), ui/node_modules/.vite (key on ui/package-lock.json + ui/vite.config.ts). UI install uses npm ci --prefer-offline --no-audit --fund=false so the npm cache is the primary source.
  • Maven build performance (set in pom.xml and cameleer-server-app/pom.xml): useIncrementalCompilation=true on the compiler plugin; Surefire uses forkCount=1C + reuseForks=true (one JVM per CPU core, reused across test classes); Failsafe keeps forkCount=1 + reuseForks=true. Unit tests must not rely on per-class JVM isolation.
  • UI build script (ui/package.json): build is vite build only — the type-check pass was split out into npm run typecheck (run separately when you want a full tsc --noEmit sweep).
  • Docker: multi-stage build (Dockerfile), $BUILDPLATFORM for native Maven on ARM64 runner, amd64 runtime. docker-entrypoint.sh imports /certs/ca.pem into JVM truststore before starting the app (supports custom CAs for OIDC discovery without CAMELEER_SERVER_SECURITY_OIDCTLSSKIPVERIFY).
  • REGISTRY_TOKEN build arg required for cameleer-common dependency resolution
  • Registry: gitea.siegeln.net/cameleer/cameleer-server (container images — CI push target, internal hostname). The same registry is reachable as registry.cameleer.io/cameleer/cameleer-server for customer pulls; the server's compiled-in image defaults target the public alias. See CLAUDE.md § Registry naming.
  • cameleer-runtime-loader image (init container that fetches the deployable JAR before the runtime container starts) is built and pushed by cameleer-saas CI (docker/runtime-loader/ in that repo) — it lives alongside the other sidecar/infra images (runtime-base, postgres, clickhouse, traefik, logto). cameleer-server consumes the image via DockerRuntimeOrchestrator but does not build it. Cross-repo contract is regression-tested by LoaderHardeningIT here, which pulls the published :latest and asserts exit 0 under the orchestrator's hardening contract.
  • K8s manifests in deploy/ — Kustomize base + overlays (main/feature), shared infra (PostgreSQL, ClickHouse, Logto) as top-level manifests
  • Deployment target: k3s at 192.168.50.86, namespace cameleer (main), cam-<slug> (feature branches)
  • Feature branches: isolated namespace, PG schema; Traefik Ingress at <slug>-api.cameleer.siegeln.net
  • Secrets managed in CI deploy step (idempotent --dry-run=client | kubectl apply): cameleer-auth, cameleer-postgres-credentials, cameleer-clickhouse-credentials
  • K8s probes: server uses /api/v1/health, PostgreSQL uses pg_isready -U "$POSTGRES_USER" (env var, not hardcoded)
  • K8s security: server and database pods run with securityContext.runAsNonRoot. UI (nginx) runs without securityContext (needs root for entrypoint setup).
  • Docker: server Dockerfile has no default credentials — all DB config comes from env vars at runtime
  • Docker build uses buildx registry cache + --provenance=false for Gitea compatibility
  • CI: branch slug sanitization extracted to .gitea/sanitize-branch.sh, sourced by docker and deploy-feature jobs