CI/CD
This document covers the GitHub Actions and TeamCity pipelines for quant-app.
For how Gradle tasks and JKube manifests are produced, see build-system.md. For Terraform edge and deployment environments, see infrastructure.md.
GitHub Actions
The default workflow lives in .github/workflows/build.yml and runs on pushes and pull requests targeting main.
Resource Caps
The build job sets NODE_OPTIONS=--max-old-space-size=1536 at job scope and writes the following into ~/.gradle/gradle.properties so all Gradle invocations share the same limits:
org.gradle.jvmargs=-Xmx2g -XX:+UseParallelGC -Dfile.encoding=UTF-8
kotlin.daemon.jvmargs=-Xmx1536m -XX:+UseParallelGC
org.gradle.workers.max=2
Pipeline Steps
- Generate and validate the TeamCity DSL before running Gradle verification tasks.
./gradlew test allTests— unit tests and KMPallTests../gradlew :backend-recorder:dbIntegrationTest :backend-sync:dbIntegrationTest— database-backed integration tests../gradlew :backend-web-app:serverIntegrationTest./gradlew :backend-database:k8sIntegrationTest :backend-sync:k8sIntegrationTest :backend-web-app:k8sIntegrationTest— real-cluster bootstrap tests. UsesCONTAINER_REGISTRY=ghcr.io/timemanx.- Build and push deploy artifacts for
backend-app,backend-server,backend-sync, andbackend-web-app. Generates Kubernetes resources withCONTAINER_REGISTRY=ghcr.io/timemanx.
On failure, both HTML reports and raw JUnit results are uploaded from **/build/reports/tests/ and **/build/test-results/.
The GitHub-hosted Ubuntu runner already provides Docker for Docker-dependent steps.
TeamCity
DSL lives in .teamcity/. Each TeamCity-managed module has its own subproject and a three-stage pipeline.
Pipeline Stages Per Module
- Build Artifacts — runs tests and builds the deployable artifact. JVM application modules publish their fat JARs with an explicit destination path (e.g.
+:{module}/build/libs/{module}-all.jar => {module}/build/libs) so TeamCity preserves the directory structure instead of flattening the artifact root.backend-web-apppublishes its staged Caddy web root underbuild/caddy/dist/. - Push Images —
k8sBuild+k8sPush, requiresCONTAINER_REGISTRYenv var on the agent. Consumes artifacts from stage 1 using their preserved directory structures. - Deploy Staging / Deploy Production —
k8sResource+k8sApply, runs on environment-matched agents (env.AGENT_ENV=stgorenv.AGENT_ENV=prod).
Project Structure
- The "All Modules" and "Selective" pipelines remain in the root project.
- Each module pipeline lives in its own TeamCity subproject declared from
.teamcity/settings.kts, with IDs like<ModuleId>_Projectand generated config directories liketarget/generated-configs/RootProjectId_<ModuleId>_Project/. - Module project metadata is written to
target/generated-configs/RootProjectId_<ModuleId>_Project/project-config.xml. - Module build type XML files live under
target/generated-configs/RootProjectId_<ModuleId>_Project/buildTypes/. - Even inside those subproject directories, build type IDs and XML filenames still use the rooted
RootProjectId_*prefix — e.g.RootProjectId_Build_BackendApp.xml, notRootProjectId_BackendApp_Project_Build_BackendApp.xml.
Validation
Run .teamcity/validate-generated-configs.sh after regenerating TeamCity configs to verify key invariants in target/generated-configs, including:
- agent requirements and deployment environment requirements
- selective/relay parameter propagation
- preserved deploy-artifact rule mappings
- module subproject placement and parent/root wiring in generated
project-config.xml - the expected rooted build type XML names inside each module subproject directory
Related Documents
- build-system.md — Gradle build types, JKube tasks, and key properties
- infrastructure.md — Terraform edge and deployment environments
- testing.md — test suite types and how to run them