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

# Deployment

> Environments, the release pipeline, migrations, and what happens on a production push.

## Environments

| Environment | Source              | Purpose                           |
| ----------- | ------------------- | --------------------------------- |
| Local       | `docker compose up` | Development.                      |
| Staging     | `develop`           | Integration verification.         |
| Production  | `main`              | The customer's live installation. |

`develop` is the integration branch **and** the repository's default branch. `main` is
the release branch: only `develop → main` integration PRs land there, cut as a frozen
`release/YYYY-MM-DD` snapshot by a workflow a human dispatches. There is no scheduled
daily integration.

<Warning>
  Never open a `develop → main` PR by hand, and never re-point the snapshot ref of an open
  integration PR. Pushes to `develop` land in the next cut.
</Warning>

## The pipeline

A push to `main` builds and deploys:

<Steps>
  <Step title="Build and test">
    The full gate runs in CI on the same major Node version the application ships on — kept in sync
    between the CI workflow, the deploy workflows and `package.json` engines.
  </Step>

  <Step title="Container image">Built and published to the GitHub Container Registry.</Step>

  <Step title="Migrations">
    `prisma migrate deploy` applies committed migration files. It never generates one — a schema
    change without a committed migration simply does not reach production.
  </Step>

  <Step title="Deploy">The App Service pulls the new image.</Step>

  <Step title="Health check">
    The pipeline waits for the health endpoint to report healthy before considering the deploy
    complete.
  </Step>
</Steps>

Production deployments are **serialised** — a concurrency group prevents two from
overlapping, and a running deploy is not cancelled by a newer push.

Documentation-only changes are excluded from the production deploy trigger: pushes
touching only markdown, `docs/` or `.gitignore` do not rebuild the image.

## Infrastructure

Terraform, with per-environment configurations and remote state. The CI service
principal needs role-assignment permissions; a `roleAssignments/write` or `/delete` 403
on apply has its own playbook.

## Secrets

Production secrets live in **Key Vault**, not in App Service configuration. The App
Service managed identity holds `Key Vault Secrets User` on the vault, and the
application bootstraps the field-encryption key from it at start-up.

There is a documented migration path for moving an installation from App Service
environment variables to Key Vault.

## Database migrations in practice

| Situation                         | What happens                                                       |
| --------------------------------- | ------------------------------------------------------------------ |
| Schema change with a migration    | Applied by `migrate deploy` on the next release.                   |
| Schema change without a migration | CI blocks the PR on drift.                                         |
| Enum addition                     | Must be its own preceding migration.                               |
| Duplicate migration               | Fails on apply — check `prisma/migrations/` before generating one. |

## Rolling back

A bad deploy in production has its own playbook — see [Runbooks](/operations/runbooks).
The short version: redeploy the previous image, and treat a database migration as
forward-only. Rolling a migration back is a restore, not a redeploy.

## Post-launch checks

The `docs/operations/` playbooks cover what to verify after a release: the health
endpoint, the scheduled jobs, a real sign-in on both surfaces, and one mail send. The
smoke tests are automated; the sign-in is worth doing by hand on a release that touched
authentication.

## New customer environments

Standing up an installation for a new customer — Azure resources, Entra registration,
mailbox, branding, seed data, first administrator — has a dedicated onboarding
checklist. See [Runbooks](/operations/runbooks).
