> ## Documentation Index
> Fetch the complete documentation index at: https://docs.emergence.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Package and Deploy

> Wrap a multi-component solution in a Helm chart, manage per-environment overlays, and ship the image to your registry.

# Package and Deploy

The [Quickstart](/guides/solution-dev/quickstart) deploys a single-component solution. This page extends to multi-component (api + worker + scheduler + agent…), per-environment overlays, image-publish workflows, and where ArgoCD picks up from there.

## Single vs multi-component

`em-service` (v0.0.15) is the base chart for *one* deployable workload — one Deployment, one Service, one set of probes. Solutions that need more than one workload include `em-service` multiple times as subchart dependencies, each with a unique `alias`.

```mermaid theme={null}
%%{init: {'theme': 'base', 'themeVariables': {'lineColor': '#555555', 'fontFamily': 'sans-serif', 'edgeLabelBackground': '#ffffff'}}}%%
flowchart TB
    subgraph Parent["Your chart: charts/&lt;solution&gt;"]
        CHART["Chart.yaml<br/>(declares subcharts)"]
        VAL["values.yaml<br/>+ values.&lt;env&gt;.yaml"]
    end

    subgraph EM["em-service v0.0.15 (per alias)"]
        API["alias: api<br/>Deployment + Service + probes"]
        WORKER["alias: worker<br/>Deployment + probes"]
        SCHED["alias: scheduler<br/>Deployment (singleton)"]
    end

    CHART --> API
    CHART --> WORKER
    CHART --> SCHED
    VAL -->|"merge: defaults +<br/>values.&lt;env&gt;.yaml"| API
    VAL --> WORKER
    VAL --> SCHED

    classDef parent fill:#56B4E9,stroke:#555555,color:#000
    classDef act fill:#E69F00,stroke:#555555,color:#000
    classDef infra fill:#0072B2,stroke:#555555,color:#fff
    class CHART,VAL parent
    class API,WORKER,SCHED infra
```

**Read top-down**: one umbrella chart per solution; one `em-service` instance per workload (api / worker / scheduler / agent); per-environment values overlay-merge with the defaults. Add a fourth alias and you've added a fourth deployable component — no other moving parts change.

See [em-service Chart › Using as a subchart](/deployment/helm/em-service#using-as-a-subchart) for the canonical reference.

## Multi-component layout

A typical "API + worker" solution:

```yaml charts/<solution>/Chart.yaml theme={null}
apiVersion: v2
name: <solution>
description: <solution> on CRAFT
type: application
version: 0.1.0
appVersion: "0.1.0"
dependencies:
  - name: em-service
    alias: api
    version: 0.0.15
    repository: oci://ghcr.io/emergenceai/em-charts
  - name: em-service
    alias: worker
    version: 0.0.15
    repository: oci://ghcr.io/emergenceai/em-charts
  - name: em-service
    alias: scheduler   # optional Prefect / cron component
    version: 0.0.15
    repository: oci://ghcr.io/emergenceai/em-charts
```

Each alias has its own values block in `values.yaml`:

```yaml charts/<solution>/values.yaml theme={null}
api:
  image:
    repository: ghcr.io/<org>/<solution>-api
    tag: 0.1.0
  service:
    type: ClusterIP
    port: 8000
  env:
    LOG_LEVEL: "INFO"
  envVars:
    - name: DATABASE_URL
      valueFrom: { secretKeyRef: { name: <solution>-secrets, key: database-url } }
  readinessProbe: { httpGet: { path: /healthz, port: 8000 } }
  livenessProbe:  { httpGet: { path: /healthz, port: 8000 } }
  autoscaling:
    enabled: true
    minReplicas: 2
    maxReplicas: 10
    targetCPUUtilizationPercentage: 70

worker:
  image:
    repository: ghcr.io/<org>/<solution>-worker
    tag: 0.1.0
  service:
    enabled: false   # workers don't expose HTTP
  env:
    LOG_LEVEL: "INFO"
    QUEUE_NAME: "<solution>-jobs"
  envVars:
    - name: DATABASE_URL
      valueFrom: { secretKeyRef: { name: <solution>-secrets, key: database-url } }

scheduler:
  image:
    repository: ghcr.io/<org>/<solution>-scheduler
    tag: 0.1.0
  service:
    enabled: false
  replicaCount: 1   # singleton — never scale schedulers horizontally
```

## Per-environment overlays

Use one `values.yaml` for shared defaults, plus `values.<env>.yaml` overlays for things that change between environments (image tags, replica counts, host names, log levels). Apply with `helm -f`:

```bash theme={null}
helm upgrade --install <solution> ./charts/<solution> \
  --namespace em-<solution> --create-namespace \
  --values ./charts/<solution>/values.yaml \
  --values ./charts/<solution>/values.dev.yaml \
  --wait --timeout 5m
```

Example dev overlay:

```yaml charts/<solution>/values.dev.yaml theme={null}
api:
  image: { tag: dev }
  replicaCount: 1
  autoscaling: { enabled: false }
  env: { LOG_LEVEL: "DEBUG" }
worker:
  image: { tag: dev }
  replicaCount: 1
```

Production overlay (just the deltas):

```yaml charts/<solution>/values.prod.yaml theme={null}
api:
  image: { tag: 1.4.7 }
  autoscaling: { minReplicas: 3, maxReplicas: 20 }
  ingress:
    enabled: true
    className: nginx
    hosts:
      - host: <solution>.example.com
        paths: [{ path: /, pathType: Prefix }]
worker:
  image: { tag: 1.4.7 }
  replicaCount: 4
```

## Build and publish images

Per-component, multi-stage `Dockerfile` (one image per workload). Use the same Dockerfile parametrized via `--target` if your components share a build base; or one Dockerfile per component if they diverge significantly.

```bash theme={null}
# Build
docker build -t ghcr.io/<org>/<solution>-api:1.4.7    --target api    .
docker build -t ghcr.io/<org>/<solution>-worker:1.4.7 --target worker .

# Login (whatever registry you use)
docker login ghcr.io -u <user> -p $GITHUB_TOKEN

# Publish
docker push ghcr.io/<org>/<solution>-api:1.4.7
docker push ghcr.io/<org>/<solution>-worker:1.4.7
```

For private registries, configure `imagePullSecrets` in `values.yaml`:

```yaml theme={null}
api:
  imagePullSecrets: [{ name: ghcr-pull }]
worker:
  imagePullSecrets: [{ name: ghcr-pull }]
```

## Versioning

Keep the Helm chart `version` and the image `tag` independent:

| What                              | Bumped when                                                           |
| --------------------------------- | --------------------------------------------------------------------- |
| Chart `version` (in `Chart.yaml`) | Chart structure changes (added/removed/renamed values, alias changes) |
| `appVersion`                      | Default app version this chart targets — informational                |
| Image `tag` (in `values.yaml`)    | Application code changes                                              |

Use [semver](https://semver.org/) for both. See [Helm › Upgrades](/deployment/helm/upgrades) for the upgrade policy (which chart-version bumps are breaking, how to roll back, etc.).

## Deploy

### Local

```bash theme={null}
helm dependency update ./charts/<solution>
helm upgrade --install <solution> ./charts/<solution> \
  --namespace em-<solution> --create-namespace \
  -f ./charts/<solution>/values.yaml \
  -f ./charts/<solution>/values.dev.yaml \
  --wait --timeout 5m

kubectl -n em-<solution> get pods -w
```

Verify all components are running and probes are passing.

### CI/CD

For automated deploys, use whatever CI/CD your team prefers; the chart itself is environment-agnostic.

## Air-gapped deployments

If the target cluster has no internet access (some customer environments), pre-stage:

1. The chart tarball (`helm pull oci://ghcr.io/emergenceai/em-charts/em-service --version 0.0.15`)
2. All component images (`docker save | docker load` on the air-gapped side)
3. The pull-secret pointing at the customer's internal registry

## Verification

```bash theme={null}
# Chart renders cleanly with the production overlay
helm template <solution> ./charts/<solution> \
  -f ./charts/<solution>/values.yaml \
  -f ./charts/<solution>/values.prod.yaml | head -50

# All declared components have running pods
kubectl -n em-<solution> get deployments
kubectl -n em-<solution> get pods

# Image tags match what you intended to deploy
kubectl -n em-<solution> get pods -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u
```

## Next steps

<CardGroup cols={2}>
  <Card title="em-service Chart" icon="dharmachakra" href="/deployment/helm/em-service">
    Full values reference for the base chart.
  </Card>

  <Card title="Helm › Configuration" icon="gear" href="/deployment/helm/configuration">
    Platform-wide chart configuration.
  </Card>

  <Card title="Helm › Upgrades" icon="arrow-up-right-dots" href="/deployment/helm/upgrades">
    Upgrade and rollback policy.
  </Card>

  <Card title="Starter templates" icon="file-code" href="/guides/solution-dev/starter-templates">
    Pre-built scaffolds for common solution shapes.
  </Card>
</CardGroup>
