# Rollout Features

Everything the chart renders under `rolloutStrategy` besides the steps/analysis (covered in
[Steps & background analysis](steps-and-background-analysis.md)). All of it is gated by
`rolloutStrategy.enabled` (default `false`).

## Enabling the rollout

```yaml
rolloutStrategy:
  enabled: true
  deploymentName: "my-svc"           # Rollout + workloadRef name (the Deployment it wraps)
  deploymentMatchLabels:             # selector.matchLabels for the Rollout
    app.kubernetes.io/instance: "my-svc"
  replicaCount: 3
```

The chart renders an Argo `Rollout` with `workloadRef` pointing at the Deployment named
`deploymentName`, using the canary strategy.

## Canary traffic & scaling

Under `rolloutStrategy.canary`:

| Key | Purpose |
|-----|---------|
| `stableService` | Stable Service name; the chart also wires `canaryService: <stableService>-canary`. |
| `maxSurge` / `maxUnavailable` | Standard canary surge settings (default `25%` / `25%`). |
| `scaleDownDelaySeconds` | Delay before scaling down the old stable ReplicaSet (default `75`). |
| `dynamicStableScale` | Scale stable down as canary scales up (default `false`). |
| `stableIngresses` | nginx `trafficRouting.nginx.stableIngresses` for ingress-based traffic routing. |
| `canaryByHeader` | Header-based canary routing (see below). |

**Header-based canary** (`rolloutStrategy.canary.canaryByHeader`): when `enabled` and `stableIngresses`
are set, the chart adds nginx canary-by-header annotations so requests carrying the configured header
go to the canary:

```yaml
rolloutStrategy:
  canary:
    canaryByHeader:
      enabled: true
      canaryByHeaderKey: "X-JFrog-Canary"
      canaryByHeaderValue: "always"      # injected by saas-deployer per cell
    stableIngresses:
      - my-svc
```

## Rollback window & history

```yaml
rolloutStrategy:
  rollbackWindow:
    revisions: 1          # how many prior revisions are eligible for fast rollback
  revisionHistoryLimit: 3 # how many old ReplicaSets to retain
```

## HPA

When `rolloutStrategy.hpa.enabled` is true, the chart renders a `HorizontalPodAutoscaler` whose
`scaleTargetRef` is the **Rollout** (`<deploymentName>`), not a Deployment:

```yaml
rolloutStrategy:
  hpa:
    enabled: true
    minReplicas: 3
    maxReplicas: 10
    targetCPUUtilizationPercentage: 90
```

## Notifications

`rolloutStrategy.notifications` adds Argo Rollouts notification subscription annotations to the Rollout
(`notifications.argoproj.io/subscribe.<trigger>.slack: <channels>`), so rollout events post to Slack
(requires the Argo Rollouts notifications controller + a configured `slack` service):

```yaml
rolloutStrategy:
  notifications:
    enabled: true
    slackChannels: "my-channel"   # multiple allowed, separated by ';'
    triggers:
      - on-rollout-aborted
      - on-analysis-run-failed
      - on-analysis-run-error
      - on-rollout-completed
```

## Stable / canary pod metadata

The chart always renders `stableMetadata` and `canaryMetadata` under `spec.strategy.canary` (each with
`labels` and `annotations`). Add your own via values:

```yaml
rolloutStrategy:
  canary:
    stableMetadata:
      labels:    { team: platform }
      annotations: { example.com/env: prod }
    canaryMetadata:
      labels:    { team: platform }
```

**Merge behavior:** your `labels`/`annotations` are merged first, then the chart applies `role: stable`
or `role: canary` **last** on both maps — so the chart always wins on `role` (you can't override it).
Defaults are empty maps; the rendered Rollout still contains both sub-keys with at least the enforced
`role` entry.
