# CI/CD Pipeline

## Platform

**CI Server**: Woodpecker CI (self-hosted) — see suite [`_infra/ci/README.md`](../../../../_infra/ci/README.md) for agent install and registry wiring.

| Agent pool | Woodpecker label | Host | Role for this repo |
|------------|------------------|------|-------------------|
| ARM64 | `platform: arm64` | Colocated with CI server (Jetson) | Unit tests (`01-test`); builds `{branch}-arm` images |
| AMD64 | `platform: amd64` | Separate remote host | Builds `{branch}-amd64` images consumed by production deploy |

**Developer machine**: Apple Silicon Mac (M1/M2/M3, `darwin/arm64`). Local Docker runs native `linux/arm64` — see [tests/environment.md](../tests/environment.md) § Platform.

## Pipeline Stages

```mermaid
flowchart LR
    Push[Push/PR to dev/stage/main] --> Test[01-test arm64]
    Test --> BuildArm[02-build-push arm64]
    Test --> BuildAmd[02-build-push amd64]
    BuildArm --> RegistryArm["registry … :branch-arm"]
    BuildAmd --> RegistryAmd["registry … :branch-amd64"]
```

### 01-test (Unit Tests)

| Property | Value |
|----------|-------|
| Trigger | push, pull_request, manual |
| Branches | dev, stage, main |
| Agent | `platform: arm64` only (unit tests are arch-neutral; suite convention) |
| Image | `mcr.microsoft.com/dotnet/sdk:10.0` |
| Steps | `dotnet restore` → `dotnet test` (Release config) |
| Output | TRX test results |

Integration and perf suites are **not** run in CI — they run locally via `scripts/run-tests.sh` and `scripts/run-performance-tests.sh` (Docker Compose).

### 02-build-push (Docker Build & Push)

| Property | Value |
|----------|-------|
| Trigger | push, manual |
| Branches | dev, stage, main |
| Depends on | `01-test` (must pass) |
| Agent | `matrix:` fans out to `arm64` and `amd64` |
| Image | docker (DinD via socket mount) |
| Dockerfile | `SatelliteProvider.Api/Dockerfile` (same file for both arches — multi-arch base images) |
| Tag format | `{branch}-arm` (arm64 agent), `{branch}-amd64` (amd64 agent) |
| Registry | Gitea OCI via Caddy TLS (`registry_host`, `registry_user`, `registry_token` secrets) |

## Multi-Architecture Strategy

Follows the suite Woodpecker contract (`matrix:` + `labels: platform: ${PLATFORM}`):

| Matrix entry | Agent | Registry tag | Deploy consumer |
|--------------|-------|--------------|-----------------|
| `PLATFORM: arm64`, `TAG_SUFFIX: arm` | Colocated Jetson agent | e.g. `dev-arm` | Not used by current deploy profiles |
| `PLATFORM: amd64`, `TAG_SUFFIX: amd64` | Remote amd64 agent | e.g. `dev-amd64` | [`suite/_infra/deploy/satellite-provider/`](../../../../_infra/deploy/satellite-provider/) — Watchtower tracks `${BRANCH}-amd64` |

Production deploy is **amd64-only** (dedicated satellite-provider host). The arm64 build validates that the Dockerfile and gRPC proto codegen path work on the colocated agent.

## Secrets

| Secret | Purpose |
|--------|---------|
| registry_host | Container registry URL (Gitea + Caddy, host:port) |
| registry_user | Registry username (`azaion`) |
| registry_token | Gitea `ci-push` PAT (`write:package`) |
