# auto-deploy

Go CLI and Terraform automation for provisioning and tearing down TiDB Cloud regions across AWS, Azure, and AliCloud. GitHub Actions workflows drive the full lifecycle; the `deploy-cli` binary is the runtime engine invoked by those workflows.

## Branch Protection

The `main` branch is protected. **All changes must go through a pull request** — direct pushes to `main` are rejected. Always create a feature branch and open a PR.

## Directory Structure

```
auto-deploy/
├── cmd/deploy-cli/        # CLI entry point (main.go + commands/)
├── internal/              # Business logic
│   ├── cloud-provider/    # AWS / Azure / AliCloud SDK wrappers
│   ├── argocd/            # ArgoCD interaction
│   ├── job/               # Job management
│   ├── meta/              # Region metadata reader (meta.go)
│   ├── types/ constants/ utils/
│   └── deploy-*.go / destroy-*.go / recreate-*.go / ...
├── etc/                   # Static assets: CRDs, deploy-job scripts, k8s-templates, images
├── meta/                  # Per-environment region YAML (dev/prod/staging/o11y-*)
├── accounts/              # Cloud account configs (alicloud/ aws/ azure/)
├── terraform/
│   ├── alicloud/          # premium/ region/ o11y-region/ ...
│   ├── aws/               # premium/ byoc/ region/ o11y-global/ account/ ...
│   ├── azure/             # premium/ region/ ...
│   └── modules/           # Shared modules (app/ argocd_cluster/ ack/ aks/ ...)
├── scripts/               # Shell/Python helpers (create/destroy/get-info for EKS/AKS/ACK, RDS init/destroy)
├── .github/
│   ├── actions/           # Reusable composite actions
│   ├── skills/            # Copilot agent skills
│   └── workflows/         # GitHub Actions workflow definitions
├── autopilot/             # AI agent for issue-driven deploy/destroy/diagnose
└── go.mod                 # Go 1.23.0 (toolchain 1.23.7)
```

## deploy-cli Commands

The `deploy-cli` binary is built from `cmd/deploy-cli/`. Commands map 1-to-1 with workflow operations:

| Command | Description |
|---|---|
| `deploy-aws-region` | Deploy standard Dedicated AWS region |
| `deploy-azure-region` | Deploy standard Azure region |
| `deploy-alicloud-region` | Deploy AliCloud region |
| `deploy-o11y-aws-region` | Deploy O11y-dedicated AWS region |
| `deploy-azure-o11y-region` | Deploy O11y-dedicated Azure region |
| `destroy-aws-region-k8s` | Tear down AWS region K8s resources |
| `destroy-azure-region` | Tear down Azure region |
| `destroy-o11y-aws-region-k8s` | Tear down O11y AWS region K8s resources |
| `destroy-o11y-azure-region` | Tear down O11y Azure region |
| `recreate-aws-region-k8s` | Recreate AWS region K8s resources |
| `recreate-azure-region` | Recreate Azure region |
| `register-default-sku` | Register default SKUs for a region |
| `update-region-info` | Update region metadata in the control plane |

## Building and Testing

```bash
go build ./cmd/deploy-cli/...   # build the binary
go test ./...                   # run tests (most packages have no tests)
```

Requires Go 1.23+. The binary is also built by the `.github/actions/build-cli` composite action inside workflows.

`internal/argocd` and `internal/global-client` tests require real cloud credentials and will fail without them.

## Local Development

`.env` contains dev API credentials (`GLOBAL_AUTH_KEY`, `DATA_SERVICE_PUBLIC_KEY`, `DATA_SERVICE_PRIVATE_KEY`). Source it before running the CLI locally:

```bash
source .env
```

AWS profiles are named by account ID (e.g., `385595570414`). Use `aws configure list-profiles` to see available profiles.

## GitHub Actions Workflows

All workflows are in `.github/workflows/`. Most are `workflow_dispatch` only. Key groupings:

| Group | Workflows |
|---|---|
| AWS region | `deploy-aws-region.yml`, `deploy-aws-nextgen-region.yml`, `deploy-aws-premium-region.yml`, `deploy-aws-byoc-region.yml` |
| AWS O11y | `deploy-o11y-aws-region.yml`, `destroy-o11y-aws-region-k8s.yml`, `deploy-o11y-aws-region-tf.yml` |
| Azure region | `deploy-azure-region.yml`, `deploy-azure-premium-region.yml`, `deploy-azure-byoc-region.yml`, `destroy-azure-region.yml` |
| AliCloud | `deploy-alicloud-premium-region.yml`, `deploy-alicloud-o11y-region.yml` |
| Initialization | `init-aws-region.yml`, `init-azure-region.yml`, `init-alicloud-region.yml` |
| Registration | `register-new-region.yml`, `register-cloud-provider.yml`, `register-default-skus.yml` |
| Maintenance | `update-region.yml`, `update-aws-region-roles.yml` |
| Testing | `weekly-test.yml` — dispatches deploy+destroy for each entry in `autopilot/test-configs.yaml` |
| Diagnostics | `auto-diagnose.yml` — AI-driven workflow failure diagnosis via the autopilot agent |

`deploy-aws-premium-region.yml`, `deploy-azure-premium-region.yml`, and `deploy-alicloud-premium-region.yml` auto-trigger the corresponding `init-*-region.yml` if the prerequisite Terraform state is missing.

## Extracting Workflow Inputs and Triggering Destroy

The GitHub API does not expose `inputs` on run objects — use the run logs instead.

```bash
# Step 1: get the run name to identify region/env
gh run view <run_id> --repo tidbcloud/auto-deploy --json workflowName,displayTitle

# Step 2: extract inputs from the "print inputs" step in the logs
gh run view <run_id> --repo tidbcloud/auto-deploy --log | grep -A 30 "print inputs"
```

**Premium workflows** (`deploy-aws-premium-region.yml`, `deploy-azure-premium-region.yml`, `deploy-alicloud-premium-region.yml`) handle both deploy and destroy in a single workflow via a `destroy` boolean input. There is no separate destroy workflow for premium tiers — re-trigger with the same parameters and `destroy=true`:

```bash
gh workflow run deploy-aws-premium-region.yml \
  --repo tidbcloud/auto-deploy \
  --field environment=<env> \
  --field region-name=<region-name> \
  --field aws-region=<aws-region> \
  --field aws-account=<aws-account> \
  --field dataplane-accounts=<dataplane-accounts> \
  --field "availability-zones=<az1,az2,az3>" \
  --field 'eks={}' \
  --field 'vpc={}' \
  --field preview=false \
  --field destroy=true
```

The Terraform-native O11y workflows (`deploy-alicloud-o11y-region.yml`, `deploy-o11y-aws-region-tf.yml`) follow the same single-workflow deploy/destroy pattern.

**Standard/non-premium workflows** have separate destroy workflows (e.g., `destroy-azure-region.yml`, `destroy-o11y-aws-region-k8s.yml`).

## Reusable Actions (`.github/actions/`)

| Action | Description |
|---|---|
| `setup-runtime` | Installs eksctl, aws-iam-authenticator, kubectl, Helm, jq, yq, gh CLI, and optional cloud CLIs |
| `build-cli` | Builds `deploy-cli` from source |
| `config-aws-credentials` | Configures AWS credentials via OIDC |
| `config-alicloud-credentials` | Configures AliCloud credentials via OIDC |
| `check-region-conflict` | Verifies no ArgoCD cluster secret already exists for the region |
| `check-terraform-state` | Checks whether a Terraform state file exists in S3 |
| `check-team-member` | Verifies the actor is a member of specified GitHub teams |
| `save-metrics` | Saves deploy metrics by creating and auto-merging a PR |

`gh` CLI is installed by `setup-runtime` via `sersoft-gmbh/setup-gh-cli-action@v2`. Workflows that do not use `setup-runtime` must install it separately.

## Terraform Layout

Terraform root modules follow `terraform/{cloud}/{tier}/`:

- `aws/premium/`, `aws/byoc/`, `aws/region/`, `aws/o11y-region/`, `aws/o11y-global/`, `aws/account/`
- `azure/premium/`, `azure/region/`
- `alicloud/premium/`, `alicloud/region/`, `alicloud/o11y-region/`

State files are stored in S3 with key pattern `{cloud}/{tier}/{env}-{region}.json`.

### terraform/modules/app

The shared `app` module encapsulates the pattern: trigger GitHub Actions workflow in `tidbcloud/app-delivery` → wait for k8s resources to be ready (`kubectl wait`). Key behaviors:

- `kubectl` stdout and stderr are **suppressed** — failures produce no visible error output beyond `exit status 1`.
- `kubectl wait --for=create` **fails immediately** (exit 1) if the target CRD does not exist yet. It does not retry.
- **`depends_on` is mandatory** when a service depends on another: e.g., `module.issuers` must declare `depends_on = [module.cert-manager]`; `module.upbound-aws-provider` must declare `depends_on = [module.upbound-crossplane]`. Without it, Terraform runs modules in parallel and kubectl fails silently on missing CRDs.
- Timeout is controlled by `var.timeout` (default 3600 s), passed as `JOB_TIMEOUT` env var to `app_ops.py`.

## meta/ and accounts/

`meta/` holds per-environment region YAML files (`dev.yaml`, `prod.yaml`, `staging.yaml`, `o11y-*.yaml`) read by `internal/meta/meta.go`. Each entry contains EKS cluster name, OIDC issuer, IAM roles, VPC/NAT config, add-on versions, and job options.

`accounts/` holds cloud account configs per environment for AWS, Azure, and AliCloud.

## autopilot

`autopilot/` is an AI agent (pydantic-ai) that handles GitHub-issue-driven deploy, destroy, and diagnosis operations. See [autopilot/AGENTS.md](autopilot/AGENTS.md) for full details.

## Related Documentation

- [Workflow reference](.github/workflows/AGENTS.md)
- [.github reference](.github/AGENTS.md)
- [terraform/aws/premium](terraform/aws/premium/AGENTS.md)
- [terraform/aws/o11y-region](terraform/aws/o11y-region/AGENTS.md)
- [terraform/aws/region](terraform/aws/region/AGENTS.md)
- [terraform/aws/byoc](terraform/aws/byoc/AGENTS.md)
- [terraform/aws/account](terraform/aws/account/AGENTS.md)
- [terraform/alicloud/premium](terraform/alicloud/premium/AGENTS.md)
- Skill: [logfire-query](.github/skills/logfire-query/SKILL.md)
- Skill: [private-repo-access](.github/skills/private-repo-access/SKILL.md)
- Skill: [whitelist-tenant](.github/skills/whitelist-tenant/SKILL.md)
- Skill: [building-pydantic-ai-agents](.github/skills/building-pydantic-ai-agents/SKILL.md)
