Skip to content

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):

  1. Reads the chart version from deploy/helm/cloud-native-dcs/Chart.yaml.
  2. Refuses to run if ../cndcs-deploy-demo/ has uncommitted changes.
  3. Creates a branch bump-chart-<version> in the deploy repo.
  4. Updates every flux/**/dcs-release.yaml whose chart: is cloud-native-dcs, replacing the version: line in the chart spec.
  5. 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: Batch manifest in a Flux-reconciled directory. Applying a Batch triggers immediate execution. Batches are per-run operational artifacts. They are not declarative desired state. Keep them out of GitOps. Create them via the dcs CLI, the gateway UI, or a controlled CronJob. If you need to ship example batch manifests, they belong in examples/ with a clear "do not bulk-apply" note.
  • CRDs reconcile before plant CRs. Any Flux Kustomization that applies plant CRs must dependsOn the dcs-release Kustomization (or whatever path installs the chart and its CRDs).
  • Beware prune cascade when restructuring. Renaming or moving a Kustomization path under prune: true cascade-deletes everything that Kustomization owns. See the cutover post-mortem in the GitOps Runbook.
  • Cluster-scoped vs namespaced. Enterprise and Site are cluster-scoped — scope them carefully when there are multiple environments sharing a cluster. Most other plant resources land in site-<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:

  1. Multi-tenant autoProvision — each authenticated user gets a per-tenant Site named demo-<username>, provisioned at first login from the bundled plant-01 scenario. 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.
  2. Flux-reconciled golden-path site — a single, dedicated site reconciled from cndcs-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.