# Azaion UI — CI/CD Pipeline

> Synthesis output of `/document` Step 3d (ci_cd_pipeline). Derived from
> `.woodpecker/build-arm.yml`.

## 1. Triggers

| Branch | Triggers | Image tag |
|--------|----------|-----------|
| `dev` | every push | `${REGISTRY_HOST}/azaion/ui:dev-arm` |
| `stage` | every push | `${REGISTRY_HOST}/azaion/ui:stage-arm` |
| `main` | every push | `${REGISTRY_HOST}/azaion/ui:main-arm` |

Other branches do NOT build (PR builds, feature-branch builds, tag builds — none configured today).

## 2. Steps

| # | Step | What | Notes |
|---|------|------|-------|
| 1 | Checkout | `git clone` + `git checkout $CI_COMMIT_SHA` | Standard Woodpecker behaviour |
| 2 | Build + Push image | Multi-stage Dockerfile produces `nginx:alpine` image with `dist/` baked in | Pushes to `${REGISTRY_HOST}/azaion/ui:${branch}-arm` with OCI labels (revision, created, source) |

**Missing steps** (recommended for autodev Steps 5–7):

| Step | Purpose | Tool candidates |
|------|---------|-----------------|
| `bun install --frozen-lockfile` smoke | Catch lockfile drift before build | First few seconds of the build stage cover this |
| `tsc --noEmit` | Type-check the whole project | Already part of `bun run build` (`tsc -b && vite build`) |
| `bun test` (or vitest / jest) | Run test suite | **Required** — there is no test runner today |
| `eslint` / `biome` | Lint | Not configured today |
| `bun audit --severity high` | Block build on new HIGH/CRITICAL CVEs in deps | Tracked as Phase B follow-up F-INF-1 (cycle 2 security audit). Today the audit is run manually; without a CI gate the dev-only Vite/PostCSS HIGH advisories that AZ-502 closed could re-enter the lockfile undetected. |
| Vulnerability scan (image) | CVE scan on the image | `trivy` or `grype` candidates — Phase B follow-up F-INF-3 |
| SBOM emission | Software bill of materials | `syft` candidate — Phase B follow-up F-INF-4 |
| Image signing | Supply-chain trust | `cosign` candidate — Phase B follow-up F-INF-4 |
| Multi-arch build | Add AMD64 alongside ARM64 | `docker buildx` candidates |

These are tracked as Step 4–7 deliverables under autodev; the current pipeline is correct but minimal.

## 2a. Dependency overrides (AZ-502, cycle 2)

Both `package.json` and `mission-planner/package.json` carry an `overrides` block:

```json
"overrides": {
  "vite": ">=6.4.2",
  "postcss": ">=8.5.10"
}
```

**Why**: `bun audit` flagged 3 advisories (1 HIGH, 2 MODERATE) in `vite <= 6.4.1` and `postcss < 8.5.10` introduced via nested transitive copies through `vitest` / `vite-node`. A direct `bun update vite` did not displace those nested copies. Forcing a floor via `overrides` plus a clean reinstall (`rm -rf node_modules bun.lock && bun install`) cleared the advisories.

**Maintenance rule**: do NOT remove these overrides until both `vite` and `postcss` are direct (non-transitive) at safe versions everywhere — verify with `bun pm ls vite postcss` before deleting. The `bun audit` CI gate (F-INF-1) will catch regressions if the overrides drift.

## 3. Secrets & registry

- `${REGISTRY_HOST}` — provided by Woodpecker secrets at runtime.
- Registry credentials — stored as Woodpecker secrets; not in this repo.
- No GPG/TLS signing keys today.

## 4. Branch model

- `dev` is the active development branch (per `.cursor/rules/git-workflow.mdc`).
- `stage` is for pre-production validation.
- `main` is production.
- No `release/*` long-lived branches.
- PR builds are not configured (Woodpecker build only fires on push, not on PR open).

## 5. Build artifact

The output of the pipeline is exactly one OCI image per push: `${REGISTRY_HOST}/azaion/ui:${branch}-arm`. There is **no** versioned image tag (e.g., `1.2.3-arm`); branch tags are mutable. The OCI `revision` label is the deterministic anchor (= `$CI_COMMIT_SHA`).

**Future**: when this UI ships under a versioned suite release, the pipeline should also tag images with `vMAJOR.MINOR.PATCH-arm` derived from `package.json` `version`.
