# Upgrade your solution

> Pull a more recent release, sync updated images, and redeploy using shdctl

> **Warning:**
>
> The upgrade process generates new configuration files and charts. Before you upgrade, commit your current configuration to source control so that you can roll back to the previous configuration if necessary.

The upgrade process uses shdctl to pull a more recent release and redeploy the solution.

To upgrade your solution, complete these steps:

## 1. Check the migration guide

Before you start, read the [migration guide](./migration.md) for every release after your current one, up to and including your target. Note the items that apply to your deployment: each one says at which of the following steps to complete it. For everything else that changed, refer to the [release notes](../release-notes).

## 2. Update the manifest version

Update the `releaseVersion` key in your `manifest.yaml` file to the desired version:

```yaml
releaseVersion: 2.0.0
```

> **Note:**
>
> Each release declares the minimum required version of shdctl in the `compatibility.yaml` file. If your shdctl is too old, the `artifact sync`, `secret export`, `secret generate`, and `release generate` commands stop with an upgrade message. Reinstall shdctl to a compatible version before continuing.

If the new release needs other configuration changes, update your `manifest.yaml` file too. For details about manifest fields and examples, refer to the [Manifest reference](../../shdctl/manifest). For a history of shdctl command changes, including new flags and breaking changes, refer to the [shdctl changelog](../../shdctl/changelog).

## 3. Validate the cluster

A release can raise the minimum Kubernetes version or add a requirement that your cluster didn't need before. To check that the cluster still meets the deployment prerequisites:

```sh
shdctl cluster check
```

Resolve every failure before you continue.

The command reads from the cluster and doesn't change it. For the full list of checks, refer to [shdctl cluster command](../../shdctl/commands/cluster).

## 4. Pull the new release

Run this command:

```sh
shdctl release pull --clean-output
```

## 5. Sync the updated artifacts

If you pull container images directly from the Unity source registry, skip this step. Otherwise, authenticate to both registries, then sync Docker images and ORAS artifacts to your private registry:

```sh
docker login uccmpprivatecloud.azurecr.io
docker login <your-registry-url>

shdctl artifact sync preflight
shdctl artifact sync images --skip-existing --cleanup
shdctl artifact sync oras
```

The `--skip-existing` flag skips images that are already in your registry, and `--cleanup` removes local images after each push.

Then check that your registry holds every image the new release needs:

```sh
shdctl artifact sync verify
```

## 6. Regenerate and deploy the secrets

Regenerate the secrets on every upgrade: a release can add secrets that its services need. Start from a file that holds every value your cluster already uses. shdctl generates afresh any value the file lacks, and `secret deploy` replaces the live secrets. Regenerating from an incomplete file therefore changes the database passwords, which breaks the services that use them, and the automation encryption key, without which data already encrypted at rest can't be read.

If you persisted the generated values with shdctl at first install, use that file. A file that vpctl persisted needs rebuilding first: refer to [Rebuild a secrets file that vpctl persisted](./migration.md#rebuild-a-secrets-file-that-vpctl-persisted). Otherwise, rebuild the file from the cluster. `shdctl secret export` replaces an existing file only with `--force`, so if the file you installed with is still there, keep a copy of it first; skip the `cp` if you no longer have it:

```sh
cp secrets.import.yaml secrets.import.installed.yaml
shdctl secret export --output secrets.import.yaml --force
```

The command lists any value it can't read back from the cluster: supply those by hand, from the copy where it holds them, unless they belong to a secret the new release introduces.

The generated secrets include the image pull secret. If something else in your cluster creates it, set `imagePullSecret.generate: false` in the manifest before you generate. Refer to [The image pull secret](../../shdctl/commands/secret#the-image-pull-secret).

Then generate with `--persist`, so that the file also records the new values, and deploy:

```sh
shdctl secret generate --import secrets.import.yaml --use-defaults --persist secrets.import.yaml
shdctl secret deploy
```

## 7. Regenerate and deploy the charts

### Helm deployment

Generate the charts:

```sh
shdctl release generate --clean-output
```

Then deploy:

```sh
shdctl release deploy --dry-run
shdctl release deploy
```

The deployment waits for the monitoring stack before it installs the rest of the release, and allows 10 minutes for each component. If a slow first image pull exceeds that, run the deployment again with a longer allowance, for example `shdctl release deploy --timeout 20m`.

### ArgoCD deployment

> **Note:**
>
> A full regeneration removes the application of any chart that the release no longer contains or that your manifest disables, and ArgoCD deletes its workloads on the next sync. If you rely on a disabled chart's workloads, enable the chart again before you regenerate.

```sh
shdctl release generate --format argocd --clean-output
git add generated-charts/
git commit -m "Upgrade to release v2.0.0"
git push
shdctl release deploy --format argocd
```

## 8. Verify the upgrade

Check that all pods are running:

```sh
kubectl get pods -n <namespace> --watch
```

Ensure that all pods eventually move to the **Running** state, except the pods of one-off jobs, such as `novu-manager-job`, which finish as **Completed**. If a pod is in any other state, describe it and check its logs to find the issue.

The upgrade process results in these changes:

* Updated container images are deployed.
* New or modified Helm charts are applied.
* Configuration changes from the new release take effect.
