119 lines
4.7 KiB
Markdown
119 lines
4.7 KiB
Markdown
# Sanctity Rules — `devops-infra-argo-config`
|
|
|
|
> Non-negotiable rules for this repository. Violations are hard stops — not warnings, not suggestions.
|
|
>
|
|
> **Audience:** Every agent and human who opens a PR against this repo.
|
|
>
|
|
> **Enforcement:** Pre-commit hooks (TruffleHog, CAC validate, Yaak) + branch protection on `main`. A merge to `main` **immediately deploys** — infra apps are auto-sync.
|
|
|
|
---
|
|
|
|
## R1: `main` is production
|
|
|
|
A merge to `main` triggers immediate ArgoCD auto-sync across all managed clusters. There is no staging gate between merge and deploy.
|
|
|
|
- No experiments on `main`.
|
|
- No force-pushes to `main`.
|
|
- Every PR must pass pre-commit hooks and receive platform-team review before merge.
|
|
|
|
---
|
|
|
|
## R2: The incubator ↔ values ↔ generic-chart contract is sacred
|
|
|
|
Each cluster is bootstrapped by exactly three things working together:
|
|
|
|
1. **Incubator file** (`incubator/<env>/<cluster>.yaml`) — parent ArgoCD Application that points at the generic chart + the cluster's values file.
|
|
2. **Values file** (`values/<env>/<cluster>-values.yaml`) — defines `clusterSpec`, `teamSpec`, `argocdSpec`, and the `appSpec[]` list.
|
|
3. **Generic chart** (`generic-argo-apps-chart/`) — renders one child ArgoCD Application per `appSpec` entry.
|
|
|
|
Breaking any leg of this triangle breaks the cluster's tooling. The naming conventions in CLAUDE.md are load-bearing — they are identifiers, not cosmetic.
|
|
|
|
---
|
|
|
|
## R3: `appSpec` entries must reference existing chart and values in `devops-infra-helm-charts`
|
|
|
|
Every `appSpec[].chartDir` must correspond to a directory under `devops-infra-helm-charts/helm-templates/`. Every `appSpec[].valuesDir` must correspond to a directory under `devops-infra-helm-charts/helm-overrides/<cluster>/`. If either doesn't exist, the ArgoCD Application will fail to render.
|
|
|
|
**Verify before adding:**
|
|
```bash
|
|
# chartDir exists?
|
|
ls devops-infra-helm-charts/helm-templates/<chartDir>/
|
|
|
|
# valuesDir exists?
|
|
ls devops-infra-helm-charts/helm-overrides/<cluster>/<valuesDir>/custom-values.yaml
|
|
```
|
|
|
|
---
|
|
|
|
## R4: Child Application names are auto-generated — do not invent names
|
|
|
|
The generic chart template generates Application names as:
|
|
|
|
```
|
|
<appSpec.name>-<mungedCluster>-<env>
|
|
```
|
|
|
|
Where cluster munging strips: `k8s-`, `prd-`, `int-`, `dev-`, `-ase1`; maps `-ase1c` to `-c`.
|
|
|
|
Example: `keda` on `k8s-central-prd-ase1` becomes `keda-central-prd`.
|
|
|
|
Only use `nameOverride` when:
|
|
- The auto-generated name would exceed 253 characters (Kubernetes limit).
|
|
- There is a genuine name collision between two appSpec entries.
|
|
|
|
---
|
|
|
|
## R5: `repository.yaml` is automation-owned
|
|
|
|
Owned by `registry-bootstrap`. Direct edits will be overwritten. To change ownership metadata, go to the upstream automation.
|
|
|
|
---
|
|
|
|
## R6: Secrets stay out of git
|
|
|
|
No credentials, tokens, API keys, or passwords in any YAML file. The TruffleHog pre-commit hook will block the commit. If a secret is accidentally committed, it must be force-purged from history — this requires platform-team involvement.
|
|
|
|
---
|
|
|
|
## R7: `nameOverride` is exceptional, not routine
|
|
|
|
Most PRs should not include `nameOverride`. When reviewing, flag any `nameOverride` that lacks a comment explaining why the auto-generated name was insufficient.
|
|
|
|
---
|
|
|
|
## R8: One incubator file per cluster, one values file per cluster
|
|
|
|
The 1:1 mapping between incubator files and values files is structural. Do not create multiple incubator files for the same cluster or share a values file across clusters.
|
|
|
|
---
|
|
|
|
## R9: Cluster folder/file names are routing keys
|
|
|
|
The cluster name in the values file (`clusterSpec.destination.name`) must match the incubator file name and the `helm-overrides/` folder name in the sister repo. These names are used by ArgoCD for cluster routing — a mismatch means tools deploy to the wrong cluster or fail silently.
|
|
|
|
---
|
|
|
|
## R10: Pre-commit hooks must pass
|
|
|
|
Run `pre-commit run --all-files` before pushing. Never use `--no-verify` to skip hooks. If a hook fails, fix the root cause.
|
|
|
|
The hooks are: TruffleHog (secrets scan), CAC validate (config validation), Yaak (additional linting).
|
|
|
|
---
|
|
|
|
## R11: Branch protection trumps everything
|
|
|
|
All changes go via PR with required review. Direct pushes to `main` are blocked at the GitHub org level. No exceptions for "quick fixes" — the blast radius of a bad merge is immediate cluster-wide impact.
|
|
|
|
---
|
|
|
|
## R12: AppProject wildcards are dangerous
|
|
|
|
The `sre` and `sec` projects currently allow `*` for source repos and destinations. Widening or modifying AppProject scope requires auditing every Application that references the project. A misconfigured project could allow unauthorized deployments.
|
|
|
|
---
|
|
|
|
## How to cite these rules
|
|
|
|
In PR reviews or agent halt messages, cite as: *"Blocked by R3 (SANCTITY_RULES.md) — chartDir must exist in devops-infra-helm-charts before adding appSpec."*
|