Multi-Repo Workflow¶
Cloud-Native DCS is split across two repositories:
| Repo | What's there | Visibility |
|---|---|---|
cloud-native-dcs |
CRDs, operators, gateway, CLI, Helm chart source, docs | Private (license model TBD, #278) |
cndcs-deploy-demo |
One verified production-quality example deployment: Terraform, Flux GitOps, bootstrap scripts | Private (license model TBD, #278) |
All CNDCS repos are private by default. Going public is a deliberate future decision gated on the license-model resolution in #278.
The Helm chart source lives in this repo. The deploy-reference repo only consumes
a pinned chart version published to oci://ghcr.io/cloud-native-dcs/charts/cloud-native-dcs.
Tracking issue: #265.
Sibling checkout layout¶
Both repos assume sibling checkouts under a common parent directory. The
canonical path is ~/cloud-native-dcs/, revised there on 2026-08-10
(cndcs-claude-harness#41, and portable/docs/machine-onboarding.md § 1 for
the reasoning):
~/cloud-native-dcs/cloud-native-dcs/— this repo~/cloud-native-dcs/cndcs-deploy-demo/— deployment example
If you clone with a different layout, override the sibling path when running the sync target:
make sync-deploy-ref DEPLOY_REF_DIR=/path/to/cndcs-deploy-demo
Bumping the chart-version pin¶
After cutting a release of this repo (which publishes a new chart version to ghcr), sync the pin in the deploy-reference repo:
# from this repo's root, with the sibling clone alongside:
make sync-deploy-ref
What it does (see scripts/sync-deploy-ref.sh):
- Reads the chart version from
deploy/helm/cloud-native-dcs/Chart.yaml. - Refuses to run if
../cndcs-deploy-demo/has uncommitted changes. - Creates a branch
bump-chart-<version>in the deploy repo. - Updates every
flux/**/dcs-release.yamlwhosechart:iscloud-native-dcs, replacing theversion:line in the chart spec. - Commits the bump locally — does not push and does not open a PR.
You finish the flow by hand:
git -C ../cndcs-deploy-demo push -u origin bump-chart-<version>
gh -R cloud-native-dcs/cndcs-deploy-demo pr create
The deploy repo's CI (.github/workflows/version-pin-drift.yml) will fail the
PR if the pinned version isn't actually published to ghcr, catching the gap
before Flux reconciles a non-existent chart.
Where do plant CRs live?¶
A frequent question after the split: when a customer authors Phase, ControlModule,
Recipe, Unit, etc. manifests, where do those YAML files belong?
| Bucket | What's in it | Lives in |
|---|---|---|
| Syntax reference | Small, self-contained "here's what a Phase looks like" snippets, one CRD per file or directory. Referenced from docs. Evolves in lockstep with CRD schema changes. |
cloud-native-dcs/examples/ |
| Working customer | A complete, GitOps-reconciled plant: Enterprise → Site → Area → ProcessCell → Unit → ControlModule → Phase → Recipe. Mirrors what a real customer's deploy repo would look like. |
cndcs-deploy-demo/flux/clusters/<env>/dcs/ |
The mental model: examples/ is syntax reference, and cndcs-deploy-demo is a
working customer. A real pharma customer forks/copies the deploy-reference shape and drops their
own plant CRs in, occasionally cribbing from examples/ for syntax.
Rules¶
- Never put a
kind: Batchmanifest in a Flux-reconciled directory. Applying aBatchtriggers immediate execution. Batches are per-run operational artifacts. They are not declarative desired state. Keep them out of GitOps. Create them via thedcsCLI, the gateway UI, or a controlled CronJob. If you need to ship example batch manifests, they belong inexamples/with a clear "do not bulk-apply" note. - CRDs reconcile before plant CRs. Any Flux Kustomization that applies plant CRs must
dependsOnthedcs-releaseKustomization (or whatever path installs the chart and its CRDs). - Beware prune cascade when restructuring. Renaming or moving a Kustomization path
under
prune: truecascade-deletes everything that Kustomization owns. See the cutover post-mortem in the GitOps Runbook. - Cluster-scoped vs namespaced.
EnterpriseandSiteare cluster-scoped — scope them carefully when there are multiple environments sharing a cluster. Most other plant resources land insite-<sitename>namespaces created by the Site controller.
Reference deployment: dual-mode¶
The hosted reference deployment runs two parallel provisioning flows on the same cluster, with no overlap in site-name space:
- Multi-tenant
autoProvision— each authenticated user gets a per-tenantSitenameddemo-<username>, provisioned at first login from the bundledplant-01scenario. That is the same reference plant the documentation describes, so an evaluator finds the units the Quickstart names on their own tenant. Each tenant's site is minted at runtime. Nothing in Git declares it. - Flux-reconciled
golden-pathsite — a single, dedicated site reconciled fromcndcs-deploy-demo/flux/clusters/demo/dcs/sites/golden-path/. This is the worked example of the customer GitOps pattern that real customers fork.
The two coexist because they serve different jobs. autoProvision is a tenant
onboarding shortcut for the hosted reference deployment, and the golden-path overlay
is how the platform itself is operated. Site names never collide (demo-<username> vs
golden-path), and the cluster-scoped ControlModuleTemplates used by
golden-path are gp-*-prefixed so they don't fight the tenants for ownership.
A single-tenant customer cluster would simply omit the autoProvision side: set
gateway.demo.autoProvision: false, leave gateway.demo.scenarioDir empty, and
reconcile their plant via Flux exactly the way golden-path demonstrates.
When to cross-cut both repos¶
| Change | Touches | How |
|---|---|---|
| New chart values default | this repo | normal PR; bump chart version: in Chart.yaml; cut release; make sync-deploy-ref |
| Reference deployment value override | deploy-reference | direct PR in deploy-reference; pin stays |
| New CRD field used by the reference deployment | both | this repo first → release → make sync-deploy-ref → deploy-reference PR adds value |
| Run docs gain a new section | this repo (requirements) + deploy-reference (worked example) | this repo describes "you must…"; deploy-reference paths are linked from docs/deploy-your-own.md. See #264. |
Out of scope¶
- No chart split. The chart stays in this repo as product code. The deploy repo never forks it.
- No multi-environment Flux. One reference cluster, one example. Forks pile on their own envs.
- No paid tier and no "enterprise edition" split. The product license model is undecided (see #278). When a license model is chosen it applies uniformly across both repos. The deploy reference is a worked example. It is not a separately-licensed tier.