# Deployment And Release Management

This project now has a GitHub Actions CD workflow at `.github/workflows/cd.yml`.

## What The Workflow Does

- Runs backend tests with PostgreSQL and `go vet`.
- Runs security gates: Gitleaks secret scan, Go `govulncheck`, npm audit and Trivy container image scan.
- Builds the React frontend, runs Playwright e2e/accessibility checks and uploads `fronted/dist` as an artifact.
- Builds the backend API image from `backend/Dockerfile`.
- Pushes the image to GitHub Container Registry.
- Signs the pushed API image with keyless Cosign and records GitHub/BuildKit provenance.
- Requires a production migration approval gate before publishing production releases.
- Writes a deployment manifest artifact.
- Optionally deploys over SSH to a `staging`, `preprod` or `production` GitHub Environment.

GitHub environments can enforce approvals, branch restrictions and protected secrets before a deploy job runs. GitHub deployment concurrency prevents overlapping deploys for the same release target.

## Required GitHub Settings

Create these environments in GitHub:

- `staging`
- `preprod`
- `production`
- `production-migration-approval`

Recommended environment protection:

- `staging`: allow `main` or `master`, optional reviewer.
- `preprod`: require reviewer approval, use production-like config and signed digest deploys.
- `production`: allow tags matching `v*.*.*`, require reviewer approval, prevent self-review where available.
- `production-migration-approval`: require database owner or release manager approval before production image publishing.

Environment secrets:

- `DEPLOY_HOST`
- `DEPLOY_USER`
- `DEPLOY_SSH_KEY`
- `DEPLOY_PORT` optional, defaults to `22`

Environment variables:

- `APP_URL` optional, shown on the GitHub deployment.
- `DEPLOY_PATH` optional, defaults to `/opt/swiftnet`.
- `DEPLOY_COMMAND` optional. If omitted, the workflow runs:

```bash
cd $DEPLOY_PATH && APP_IMAGE=$APP_IMAGE docker compose pull api && APP_IMAGE=$APP_IMAGE docker compose up -d api
```

## Remote Server Layout

Copy `deploy/docker-compose.remote.yml` to the server as `docker-compose.yml`, then create a `.env` file with environment name, production/staging secrets and database settings. Set `BANKING_APP_ENV=staging` on staging hosts, `BANKING_APP_ENV=preprod` on pre-production hosts and `BANKING_APP_ENV=production` on production hosts.

Example remote update:

```bash
APP_IMAGE=ghcr.io/OWNER/REPO/banking-api:SHORT_SHA docker compose pull api
APP_IMAGE=ghcr.io/OWNER/REPO/banking-api:SHORT_SHA docker compose up -d api
```

For preprod and production, use a managed PostgreSQL instance with HA, PITR backups and tested restore. Keep `BANKING_RUN_MIGRATIONS=false` unless migrations are intentionally run by the release pipeline. The app validates `BANKING_POSTGRES_HA_ENABLED`, `BANKING_POSTGRES_PITR_ENABLED` and `BANKING_RESTORE_DRILL_REFERENCE` before boot in preprod/production.

High-risk product feature flags are explicit in `deploy/docker-compose.remote.yml` and default to `false` there. Enable only approved product surfaces per environment:

```bash
BANKING_FEATURE_PAYMENTS_ENABLED=true
BANKING_FEATURE_CARDS_ENABLED=false
BANKING_FEATURE_FX_ENABLED=true
BANKING_FEATURE_CRYPTO_ENABLED=false
BANKING_FEATURE_SAVINGS_ENABLED=true
BANKING_FEATURE_ADMIN_MONEY_MOVEMENT_ENABLED=false
```

Production CD runs require `migration_plan_reviewed=true` and a `migration_approval_reference` for manual workflow dispatches. Tag-triggered releases still pass through the protected `production-migration-approval` environment. Use `docs/release-notes-template.md` for every release so risk, migrations, toggles and runbook links are captured before approval.

The CD migration approval job generates and uploads `release/migration-plan.json` with ordered migration checksums and rollback coverage. CI and CD also run:

```bash
cd backend
go run ./cmd/migration-plan -dir migrations -format json -require-rollback
```

Use `docs/runbooks/database-migration-release.md` for dry-run, approval and rollback evidence. Use `docs/runbooks/database-backup-restore-drill.md` for restore-drill evidence.

Use `docs/runbooks/deploy.md` for the controlled deployment sequence, financial verification and closure evidence. Use `docs/runbooks/rollback.md` for API, frontend, configuration and database compatibility rollback decisions.

See `docs/infrastructure-runtime.md` for the production hosting architecture, private networking, internal metrics, resource limits, worker profile, healthchecks and blue/green/canary rollout contract. See `docs/observability-incident-response.md` and `deploy/observability/` for dashboards, alerting, incident runbooks and resilience drills.

## Staging Smoke Environment

Staging has a repeatable local/container smoke setup in `deploy/docker-compose.staging.yml`. It starts PostgreSQL and the API with `BANKING_APP_ENV=staging`, PostgreSQL-backed rate limiting, migrations enabled, non-dev secrets and the same distroless backend image used by release builds.

Create the env file:

```powershell
Copy-Item deploy\.env.staging.example deploy\.env.staging
```

For a shared staging server, replace every secret in `deploy/.env.staging` with generated values before exposing it to other users. The checked-in example is only for isolated smoke runs.

Run the full smoke flow on Windows:

```powershell
powershell -ExecutionPolicy Bypass -File deploy\staging-smoke.ps1
```

Run the same flow on Linux/macOS:

```bash
bash deploy/staging-smoke.sh
```

The smoke flow:

- Builds the API container from `backend/Dockerfile`.
- Starts `postgres` and `api`.
- Waits for `/readyz`.
- Runs the idempotent staging seed profile.
- Runs `go test ./e2e -count=1` against the live API.
- Logs in as the seeded customer and verifies authenticated account access.

Optional staging observability stack:

```powershell
docker compose --env-file deploy\.env.staging.example -f deploy\docker-compose.staging.yml -f deploy\docker-compose.observability.yml config
```

Replace the Grafana password and webhook URLs before shared use. The stack renders Prometheus, Alertmanager and Grafana with the banking dashboard and alert rules.

Default seeded users:

- Admin: `admin.staging@swiftnet.test`
- Customer: `customer.staging@swiftnet.test`
- Password: `very-secure-passphrase`

The seed command refuses to run in production and also refuses to run unless `BANKING_ALLOW_STAGING_SEED=true` is set.

## Branch Protection

Branch protection cannot be fully enforced from this repository file alone. Configure it in GitHub repository settings or with the GitHub API.

Recommended `main` or `master` rules:

- Require pull request before merge.
- Require at least one approving review.
- Require status checks:
  - `Backend Tests`
  - `Frontend Build`
  - `Docker Build`
  - `Dependency Review`
  - `Secret Scan`
  - `Go Vulnerability Scan`
  - `Frontend Dependency Audit`
  - `Container Image Scan`
- Require branches to be up to date before merging.
- Block force pushes and branch deletion.
- Require conversation resolution.

Recommended release flow:

1. Merge through PR into `main` or `master`.
2. Let `CI` pass, including dependency review, secret scan, vulnerability scans and container image scan.
3. Run `CD` manually to deploy `staging`.
4. Complete release notes from `docs/release-notes-template.md`, including migration approval reference and feature flag values.
5. Tag a release as `vX.Y.Z`.
6. Run `CD` manually to deploy `production` after migration and deployment environment approval.

## Rollback

Use the manual `CD` workflow and set `rollback_image` to a previous image reference, for example:

```text
ghcr.io/OWNER/REPO/banking-api:abc123def456
```

The workflow will deploy that image instead of the newly built image when `deploy` is enabled.
