12 KiB
CI/CD Standardization Precheck
This document classifies CI/CD paths while UniDesk converges on image-artifact delivery. It is a precheck and guardrail document, not a mass-deletion plan.
Target Shape
The standard release shape is:
- CI builds or locks the artifact from a pushed commit or verified upstream digest.
- The artifact is published to the D601 artifact registry or a controlled mirror.
- Dev validation consumes that same artifact.
- Production CD is pull-only and verifies live commit or upstream digest.
- Runtime metadata can be traced back to a live Git commit or upstream image digest.
backend-core and D601 code-queue may be validated only in dev in this phase. This document must not be used to introduce production deploy validation for either service.
Upstream Image Consumers
filebrowser and filebrowser-d601 are upstream-image consumers, not source-built UniDesk services.
| Service | Upstream image | Source revision | Catalog home | CI Dockerfile build | Digest / mirror strategy | CD validation |
|---|---|---|---|---|---|---|
filebrowser |
docker.io/filebrowser/filebrowser:v2.63.3 |
ca5e249e3c0c94159c2136a0cd431a424eb18472 |
CI.json.upstreamImageConsumers[] and config.json.microservices[].repository.artifactSource |
forbidden | resolve tag to docker.io/filebrowser/filebrowser@sha256:<manifest-digest>, then optionally mirror to 127.0.0.1:5000/upstream/filebrowser/filebrowser@sha256:<manifest-digest> |
pull by digest or mirror digest, verify OCI labels, container image id/digest, and private proxy health |
filebrowser-d601 |
docker.io/filebrowser/filebrowser:v2.63.3 |
ca5e249e3c0c94159c2136a0cd431a424eb18472 |
CI.json.upstreamImageConsumers[] and config.json.microservices[].repository.artifactSource |
forbidden | same as filebrowser |
same as filebrowser |
The current precheck could inspect the locally cached image labels and image id, but Docker Hub and registry HTTP requests timed out from this container. Therefore the catalog records digestPin.status=pending-network-verification; rollout must remain blocked until a reachable registry path resolves the manifest digest and records the mirror digest. The locally cached image shows org.opencontainers.image.version=2.63.3, org.opencontainers.image.revision=ca5e249e3c0c94159c2136a0cd431a424eb18472, linux/amd64, and image id sha256:6a4d051140ef9313ad87b443f55ccb1cd6331e7463b4becbec2174b494ea533c, but a local image id is not a registry digest pin.
Upstream Image Evidence
The catalog expression is intentionally minimal and parseable:
| Evidence command | Required result shape |
|---|---|
| `jq '.upstreamImageConsumers[] | {serviceId, upstreamImageRef, digestPin, mirrorStrategy, ciBuild, pullOnlyCdValidation}' CI.json` |
bun scripts/cli.ts config show with the File Browser artifactSource projection |
both services parse as kind=upstream-image, digestPinRequired=true, mirrorRepository=127.0.0.1:5000/upstream/filebrowser/filebrowser, ciDockerfileBuild=false, and pullOnlyCd=true |
docker image inspect filebrowser/filebrowser:v2.63.3 |
local cache evidence may show the image id and OCI labels for version 2.63.3 and revision ca5e249e3c0c94159c2136a0cd431a424eb18472; this is not a registry digest |
docker manifest inspect --verbose docker.io/filebrowser/filebrowser:v2.63.3 |
must resolve an upstream manifest digest before rollout; when the registry request times out, rollout remains blocked and the catalog stays at pending-network-verification |
bun scripts/cli.ts ci publish-user-service --service filebrowser --commit <full-sha> --dry-run |
returns ok=false with the message that File Browser is an upstream image consumer and must not be built by Dockerfile CI |
The digest/mirror dry-run contract is:
- Resolve
docker.io/filebrowser/filebrowser:v2.63.3todocker.io/filebrowser/filebrowser@sha256:<manifest-digest>. - Mirror only that resolved digest to
127.0.0.1:5000/upstream/filebrowser/filebrowser@sha256:<manifest-digest>. - Record the digest ref used by CD; do not promote a mutable tag as release truth.
- Refuse pull-only CD while the digest is unknown or the mirror digest differs from the upstream digest.
Pull-only CD validation must be expressed as concrete checks:
| Check | Form |
|---|---|
| Pull source | docker pull docker.io/filebrowser/filebrowser@sha256:<manifest-digest> or docker pull 127.0.0.1:5000/upstream/filebrowser/filebrowser@sha256:<manifest-digest> |
| Runtime identity | docker inspect reports the expected image id/digest and OCI labels org.opencontainers.image.version=2.63.3 and org.opencontainers.image.revision=ca5e249e3c0c94159c2136a0cd431a424eb18472 |
| Service health | UniDesk private proxy health succeeds for filebrowser and filebrowser-d601; direct public exposure remains forbidden |
| Build absence | no docker build, docker compose up --build, CI Dockerfile producer, or source checkout is used for these services |
Legacy Path Classification
| Path | Classification | Current guardrail | Cleanup condition |
|---|---|---|---|
deploy apply --env prod for services without a reviewed artifact consumer |
Must stay disabled/degraded | returns structured unsupported and refuses maintenance-channel fallback | enable only after each service has a documented artifact producer, dev consumer, prod consumer and live verification |
Local-manifest deploy apply for prod artifact consumers (backend-core, frontend, baidu-netdisk, decision-center) |
Must stay disabled/degraded as a standard prod path | blocked before source build; operator is pointed to deploy apply --env prod |
remove only after all production deploys use env-ref artifact consumers and no recovery runbook depends on local manifests |
artifact-registry deploy-backend-core |
Legacy compatibility entry | returns structured deprecated result; replacement is deploy apply --env prod --service backend-core |
remove after callers and docs use only deploy apply --env prod |
server rebuild frontend and server rebuild baidu-netdisk |
Maintenance / non-standard | docs classify as maintenance-only; standard release requires CI artifact plus dev/prod artifact consumer | keep until recovery runbooks have equivalent pull-only repair commands |
server rebuild backend-core |
Diagnostic/recovery only; not Rust iteration or prod CD | docs forbid Rust iteration and prod backend-core artifact CD through this command | keep for bootstrap/recovery until backend-core artifact CD and rollback are proven under outage conditions |
server rebuild dev-frontend-proxy, code-queue-mgr, project-manager, oa-event-flow, todo-note, provider-gateway on main-server Compose |
Bootstrap / recovery / diagnostic | still serialized through Compose lock and post-up validation | reassess service by service after artifact consumers exist |
provider.upgrade mode=schedule for provider-gateway |
Must be retained | protected upgrade path with validation; Host SSH self-rebuild remains forbidden | do not delete; it is the provider-gateway recovery path |
D601 direct docker build, kubectl apply, docker compose up --build used by deploy executor for allowed dev/backend bootstrap and native k3s setup |
Bootstrap / recovery / controlled dev | limited to allowed target-side executor, native k3s initialization, and dev backend-core; Code Queue prod is not enabled | convert only after artifact consumers or native bootstrap replacements exist |
D601 direct Code Queue / old codex deploy |
Must stay disabled/degraded | compatibility command throws; docs classify direct deployment as forbidden | wait for controlled Code Queue dev/prod CD worker |
File Browser docker run image-only path |
Needs later worker | now cataloged as upstream-image consumer; no CI Dockerfile build allowed | implement digest-resolved pull-only/mirror CD before treating it as standard deployment |
Guardrails Added
- Upstream-image services are represented in
CI.json.upstreamImageConsumers[]and inconfig.json.microservices[].repository.artifactSource; they are explicitly outsideCI.json.artifacts[]. ci publish-user-servicerejects registeredupstream-imageservices instead of trying to interpretrepository.dockerfileas a source Dockerfile.- Local-manifest production deploy for reviewed artifact consumers is blocked before source materialization/build, so prod cannot silently fall back to target-side source build or a dirty worktree.
artifact-registry deploy-backend-coreis demoted to a structured deprecated result; backend-core production CD must enter throughdeploy apply --env prod.
Guardrail Evidence Matrix
| Guardrail name / result key | Command evidence | Legacy path covered | Deletion status |
|---|---|---|---|
upstream-image CI publish rejection |
bun scripts/cli.ts ci publish-user-service --service filebrowser --commit <full-sha> --dry-run returns ok=false and says not to build an upstream image consumer |
File Browser accidentally entering CI.json.artifacts[] or Dockerfile CI |
keep; deletion of docker-run repair waits for digest/mirror CD |
prod-artifact-consumer-local-manifest-blocked |
bun scripts/cli.ts deploy apply --file deploy.json --service frontend --dry-run returns ok=false, this error key, and points to deploy apply --env prod --service <service-id> --commit <full-sha> |
prod source-build fallback for reviewed artifact consumers | keep; local manifest mode may still be needed for non-prod/recovery until runbooks are replaced |
artifact-registry deploy-backend-core deprecated result |
bun scripts/cli.ts artifact-registry deploy-backend-core --commit <full-sha> returns ok=false, deprecated=true, and replacement deploy apply --env prod --service backend-core --commit <full-sha> |
backend-core prod CD bypassing deploy reconciler guardrails | keep name only as compatibility until all callers stop using it |
| prod unsupported result for services without artifact consumers | deploy apply --env prod --service <unsupported-service> --dry-run must return unsupported instead of falling back to source build |
target-side source build/maintenance-channel prod deploy | keep disabled until service-specific artifact consumers exist |
| backend-core/code-queue prod boundary | docs and deploy support matrix allow backend-core and D601 Code Queue only in dev validation for this phase | accidental prod validation entrypoints for backend-core or Code Queue | do not add executable prod test/deploy validation in this precheck |
The guarded-but-not-deletable paths are: server rebuild backend-core, server rebuild frontend, server rebuild baidu-netdisk, provider-gateway protected upgrade, native k3s bootstrap, k3sctl-adapter bridge repair, File Browser provider-local docker-run repair, and D601 dev/backend target-side rollout. They remain because they are bootstrap, recovery, diagnostic, or controlled dev paths; deleting them requires replacement runbooks or reviewed artifact consumers.
Not Removed Yet
Bootstrap and repair paths remain because they still protect recovery: native k3s initialization, provider-gateway protected upgrade, k3sctl-adapter control bridge repair, main-server Compose maintenance rebuilds, and File Browser docker-run operations. These paths must be replaced by reviewed artifact consumers or explicit recovery runbooks before deletion.
Validation Boundary
This precheck uses lightweight parsing and dry-run evidence only. It intentionally does not run full check, e2e, Playwright, or other broad browser/runtime test suites on the master server because those are outside the precheck scope and may exceed master-server resource limits. backend-core and D601 code-queue production validation are also out of scope; backend-core dev rollout can be attempted only through the existing D601 dev path, and a provider-offline result is an infrastructure blocker rather than permission to validate production.