> ## Documentation Index
> Fetch the complete documentation index at: https://api-documentation.kare-app.fr/llms.txt
> Use this file to discover all available pages before exploring further.

# Déployer sur staging

> Auto-deploy au merge, deploy manuel, targets, rollback

## Le pipeline partagé

Auto-deploy, deploy manuel et rollback appellent tous `deploy-stack.yml`. Le déploiement est écrit
**une seule fois**.

```mermaid theme={null}
flowchart TD
    P[parse target] --> QF[qa-front<br/>turbo lint/typecheck/test]
    P --> QA[qa-api<br/>Postgres + Redis éphémères]
    QF --> DA[deploy-api<br/>build → migrate → update image]
    QA --> DA
    QF --> DF[deploy-fronts<br/>build → update image]
    QA --> DF
    DA --> H[health gate]
    DF --> H
    H --> PR["promote staging-latest"]
    PR --> V[verdict]
```

* Les images sont taguées avec le **SHA7 court, immuable**. Aucun build ne pousse `staging-latest`.
* Les migrations Prisma tournent dans le job `migrate`, **avant** l'update d'image.
* Le health gate sonde `https://api.<audience>.staging.kare-app.fr/health/ready` et
  `https://<sub>.staging.kare-app.fr/health`. Un target mutant dont le gate n'a résolu aucune URL est
  considéré comme **non gardé** et échoue.
* `promote` déplace `staging-latest` seulement pour les composants réellement sur le tag de ce run :
  un run dépassé ou un déploiement API partiel laisse l'alias en place au lieu de le reculer.

<Warning>
  Aucun rollback automatique, ni d'image ni de schéma. Une migration destructive ne peut pas être
  défaite sans risque — c'est pour cela que la règle expand/contract est obligatoire, voir
  [Migrations](/devops/migrations). La reprise est `rollback.yml`, manuelle.
</Warning>

## Auto-deploy au merge

`cd-staging.yml` part sur chaque push de `main`, détecte les composants touchés (`dorny/paths-filter`)
et appelle le stack **une fois par composant affecté**.

<Warning>
  Il ne mute staging que si la variable de repo **`STAGING_AUTO_DEPLOY_ENABLED`** vaut exactement
  `true`. Sinon le run affiche `disabled` et réussit sans rien construire ni changer. Garde-la à `false`
  pendant un cutover d'infra ou tant qu'un container cible n'existe pas.
</Warning>

Les filtres de chemins incluent les manifestes racine (`package.json`, `yarn.lock`, `.yarnrc.yml`) :
les Dockerfiles copient la racine du repo et font l'install dans l'image, donc un bump de lockfile
change ce qui est livré.

## Deploy manuel

**Actions → Deploy (manual) → Run workflow**. Staging uniquement.

| Entrée   | Valeur                                                                   |
| -------- | ------------------------------------------------------------------------ |
| `target` | voir le tableau ci-dessous                                               |
| `ref`    | branche, tag, ou SHA **complet de 40 caractères**. Vide = HEAD de `main` |

### Les targets

| Target                                                               | API déployée     | Fronts déployés                                           |
| -------------------------------------------------------------------- | ---------------- | --------------------------------------------------------- |
| `all`                                                                | `rs,bo,ad,pr`    | `backoffice,audit,kare,provider`                          |
| `api`                                                                | `rs,bo,ad,pr`    | —                                                         |
| `api-rs` / `api-bo` / `api-ad` / `api-pr`                            | l'audience seule | —                                                         |
| `front-backoffice` / `front-audit` / `front-kare` / `front-provider` | —                | le front seul                                             |
| `pair-backoffice`                                                    | `bo`             | `backoffice`                                              |
| `pair-audit`                                                         | `ad`             | `audit`                                                   |
| `pair-kare`                                                          | `rs`             | `kare`                                                    |
| `pair-provider`                                                      | `pr`             | `provider`                                                |
| `seed-kare` / `seed-provider`                                        | —                | build + alias seulement, **aucune mutation de container** |

`api` fait un seul build, un seul `qa-api` et une seule migration, puis fan-out des audiences dans la
matrice interne — c'est ce que `cd-staging` utilise pour un changement API.

### Les targets `seed-*`

Un `seed-*` sert à **ajouter un front à un stage déjà opérationnel** :

<Steps>
  <Step title="Seed">
    Lancer `deploy.yml` avec `target=seed-kare` : QA, build, push et création de l'alias
    `staging-latest` s'il est absent (il ne déplace jamais un alias existant).
  </Step>

  <Step title="Créer le container">
    `tofu apply` revu dans `infrastructure/` — le container est créé sur `staging-latest`.
  </Step>

  <Step title="Déployer normalement">
    Ensuite seulement, utiliser `front-kare` ou `pair-kare`.
  </Step>
</Steps>

Pour reconstruire un stage entier, c'est le runbook infra qui s'applique, pas `seed-*` : voir
[Infrastructure](/devops/infrastructure).

## Rollback

**Actions → Rollback → Run workflow**. Staging uniquement (le stage est codé en dur dans le workflow).

| Entrée      | Valeur                                                           |
| ----------- | ---------------------------------------------------------------- |
| `target`    | même topologie que `deploy.yml` (hors `seed-*`)                  |
| `image_tag` | un tag SHA7 **existant** dans le registry, par exemple `a7cbd84` |

Séquence : `parse` → `preflight` (vérifie que **toutes** les images sélectionnées existent, avant
toute mutation) → rollout par composant → sonde HTTP → `staging-latest` déplacé seulement si le
résultat est sain.

<Warning>
  Le rollback ne touche **pas** la base. Ne choisis une image ancienne que si elle est compatible avec
  le schéma actuel.
</Warning>

Les tags disponibles se lisent dans le registry Scaleway, ou dans le résumé du run de déploiement qui
les a poussés.

## Concurrency

Pas de concurrency au niveau du run de `cd-staging` : un groupe unique ferait annuler par GitHub le
run en attente lors de merges rapprochés, en abandonnant ses déploiements. La sérialisation vit au
niveau **job** sur les jobs mutants (`deploy-api-mutate-staging-<audience>`,
`deploy-frontend-mutate-staging-<app>`) — c'est ce qui empêche un run `cd-staging` et un
`deploy.yml` manuel de se courir dessus.
