7.0 KiB
UniDesk CI On D601 k3s
UniDesk CI is hosted on the D601 native k3s cluster with Tekton Pipelines and Tekton Triggers. It is CI only. CD remains separate from Tekton; D601 service deployment must go through the DevOps control plane, while maintenance-channel direct D601 apply is reserved for DevOps bootstrap/repair. No Tekton task may roll out production services.
Components
- Tekton Pipelines:
v1.12.0. - Tekton Triggers:
v0.34.0. - UniDesk CI namespace:
unidesk-ci. - Manifests:
src/components/microservices/k3sctl-adapter/k3s/ci/. - CLI entry:
bun scripts/cli.ts ci install|status|run|run-dev-e2e|logs. - DevOps control service:
src/components/microservices/devops, normally installed inunidesk-ciand reached through the k3s service-proxy path.
Bootstrap and recovery may reach D601 through backend-core /api/dispatch with the existing host.ssh provider capability, then run native KUBECONFIG=/etc/rancher/k3s/k3s.yaml kubectl ... on D601. That maintenance path is limited to DevOps bootstrap/repair and CI bootstrap checks; it must not deploy backend-core, frontend, Code Queue, Decision Center, k3sctl-adapter or other direct/managed microservices. Normal CI/CD control should move to CLI -> backend-core -> k3sctl-adapter -> DevOps -> Kubernetes API/Tekton after DevOps is healthy. No new public port is exposed.
Pipeline Scope
Each commit CI run performs:
git cloneand checkout of the requested repository revision.bun install --frozen-lockfileat the repo root andsrc/, becausebun scripts/cli.ts checkcompiles allsrc/componentsand needs the component workspace lockfile for frontend React dependencies.bun scripts/cli.ts check.- Temporary
code-queue-ci-readDeployment and ClusterIP Service inunidesk-ci. - Code Queue read performance checks against the production PostgreSQL through
d601-tcp-egress-gateway.
ci install also prewarms the D601 k3s containerd runtime with the Tekton entrypoint/workingdir helper images, oven/bun:1-debian, alpine/git:2.45.2 and unidesk-code-queue:dev. Missing images are pulled through the node-local provider-gateway WS egress proxy and then imported into native k3s containerd with digests preserved, so PipelineRun pods do not hang on external registry pulls.
Git clone and dependency downloads inside the repo check task use d601-provider-egress-proxy.unidesk.svc.cluster.local:18789; the NO_PROXY list keeps the in-cluster read service, D601 TCP egress gateway and any in-cluster CI Git mirror on the cluster network.
Steps that call the Kubernetes API directly clear inherited proxy variables so service-account HTTPS calls to kubernetes.default.svc do not accidentally use the Code Queue image's Docker Compose proxy defaults.
The rollout poll reads the Deployment main resource rather than the /status subresource, keeping CI RBAC limited to the same app/service resources it creates and deletes.
The performance probe scans recent Code Queue tasks until it finds one with trace steps, so a newly selected task without persisted step detail does not make the whole gate fail before measuring the trace endpoints.
The temporary Code Queue service uses:
CODE_QUEUE_SERVICE_ROLE=read.CODE_QUEUE_SCHEDULER_ENABLED=false.CODE_QUEUE_STARTUP_OA_BACKFILL_ENABLED=false.CODE_QUEUE_NOTIFY_CLAUDEQQ_ENABLED=false.CODE_QUEUE_CODEX_SQLITE_LOG_EXPORT_ENABLED=false.- D601 k3s
d601-provider-egress-proxyfor external/OA Event Flow fetches, withd601-tcp-egress-gatewayand the CI read service inNO_PROXY. - EmptyDir state/log mounts.
This means the CI service can read existing tasks, Trace summaries, Trace steps and Trace step details from the main database, but it must not schedule, mutate, notify, backfill or become deployment truth.
Dev Namespace E2E
ci run-dev-e2e is the manual CI entry for the dev desired-state smoke flow. The CLI fetches origin/master:deploy.json, reads environments.dev, records the origin/master commit that supplied the manifest, then normally calls DevOps through the existing microservice proxy to create a Tekton PipelineRun. The Pipeline verifies that the in-cluster Git fetch sees the same master commit before it reads deploy.json.
ci run-dev-e2e --direct is reserved for CI bootstrap and recovery when DevOps is not healthy yet. It creates only the CI PipelineRun through the maintenance Host SSH path, does not deploy any direct/managed microservice, and must not become the normal CI control path.
The first CI stage creates a temporary namespace named unidesk-ci-e2e-<run-id>, stores the selected desired manifest in a ConfigMap, starts an in-namespace smoke target, calls its /health endpoint through the Kubernetes Service DNS name, verifies the dev service commit IDs carried into the target, and deletes the namespace unless --keep-namespace is set. This stage proves the manual trigger, master desired-state pinning, namespace lifecycle, in-cluster Service DNS and e2e result path without mutating unidesk, unidesk-dev, production PostgreSQL, or any production workload.
The current dev namespace e2e is a harness and smoke gate, not a full frontend/backend/code-queue stack rollout. Full-stack temporary namespace deployment can be added behind the same run-dev-e2e command after image build/import and per-run database bootstrap are promoted into CI.
Performance Gate
The initial budgets live in unidesk-ci/unidesk-ci-budgets:
- Code Queue first overview payload through the temporary read service, used as the service-side first-paint proxy:
10000ms. GET /api/tasks/{id}/trace-summary:10000ms.GET /api/tasks/{id}/trace-steps:20000msdiagnostic, reported but not blocking while the existing production TraceView step query is being optimized.GET /api/tasks/{id}/trace-step:20000msdiagnostic, reported but not blocking while the existing production TraceView step query is being optimized.GET /api/tasks/overviewp95 over 10 samples:20000ms.
These are absolute budgets. Historical relative baselines can be added later by writing metrics to a dedicated CI table or object store; they should not be mixed into production task tables.
Commands
Install or refresh CI:
bun scripts/cli.ts ci install
Check status:
bun scripts/cli.ts ci status
Run CI manually for a commit:
bun scripts/cli.ts ci run --revision <commit>
Run the dev namespace e2e harness manually:
bun scripts/cli.ts ci run-dev-e2e --wait-ms 600000
Inspect a run:
bun scripts/cli.ts ci logs <pipelineRunName>
Trigger Boundary
unidesk-ci.triggers.yaml installs the EventListener, TriggerBinding and TriggerTemplate, but the EventListener remains a normal in-cluster Service. Do not expose it through NodePort, LoadBalancer or an unrestricted public ingress. If GitHub or another Git remote needs webhook delivery, add a UniDesk-controlled frontend/backend route with secret verification and then proxy to the EventListener; keep frontend and provider ingress as the only unrestricted public entry points.