Files
devops-infra-helm-charts-gcp/docs/global/SANCTITY_RULES.md
T
2026-08-26 03:39:42 +05:30

123 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SANCTITY_RULES.md
> Non-negotiable rules for the `devops-infra-helm-charts` repo.
> Read alongside [AGENT_BOUNDARIES.md](AGENT_BOUNDARIES.md) (per-operation Layer map) and [coding-guidelines/helm-values.md](coding-guidelines/helm-values.md) (style).
These are the rules whose violation is a process incident, not a clever shortcut. Each one is the result of a real failure mode (or proximity to one).
---
## R1 — `main` is production
Argo CD on every cluster reconciles from `main`. There is no staging branch. A merge is a deploy event.
- **No experimentation on `main`.** Always work on a feature/fix branch and open a PR.
- **No force-push to `main`** (enforced at GitHub org level).
- **No "I'll just amend that" after merge.** A new PR is the only path forward.
## R2 — Sister repo is the routing layer; this repo is the values layer
`devops-infra-helm-charts` holds *what gets installed and with what values*. `github.com/Meesho/devops-infra-argo-config` holds *where it gets routed* (the Argo `Application` / `ApplicationSet` manifests).
- **A new chart in `helm-templates/` does nothing** until an `Application` referencing it lands in the sister repo.
- **A new cluster directory in `helm-overrides/` does nothing** until an `ApplicationSet` (or per-cluster Application set) covers it.
- **Pair the two-repo change.** Cite the sister-repo PR in the description here, and vice versa.
## R3 — Production traffic surfaces are off-limits
Agent-initiated requests to `int.meesho.int`, `prd.meesho.int`, `int.mrouter.int`, `prd.mrouter.int`, and workload `*.meeshogcp.in` services are forbidden. Any accidental call can affect live traffic or data.
- **Never `curl`, `WebFetch`, query, or otherwise probe** these endpoints.
- The pre-commit hook telemetry endpoints (`observe.meeshogcp.in/api/webhook`, `cursor-server.meeshogcp.in/api/v1/...`) are *automated hook infrastructure*, not agent-initiated traffic. They are not a precedent for agent calls.
## R4 — Pre-commit hooks must pass
`pre-commit-scripts/runner.sh` invokes TruffleHog (verified-secret scan with webhook telemetry). CAC and Yaak hooks exist but are no-ops here (their gating paths — `configs/` and `api-collections/` — don't exist in this repo). TruffleHog is the last-line secret scan.
- **Never bypass** with `--no-verify`, `git commit -n`, or by removing the hook.
- **Never weaken a hook to "just get this through"** — fix the upstream cause.
- A verified TruffleHog hit means a secret is staged. Real secrets belong in `external-secrets` (per-cluster), backed by GCP Secret Manager / Vault — not in `custom-values.yaml`.
## R5 — Per-cluster scheduling is bespoke; never copy across clusters
Each cluster has its own node-pool topology. Some clusters use GKE Autopilot's `cloud.google.com/compute-class:` keys (`k8s-central-prd-ase1`, `k8s-dsgpu-prd-ase1`, `k8s-shared-int-ase1`); standard clusters use `dedicated:` keys. Per-Contour-instance, per-cluster mappings are recorded in [contour-nodeselector-tolerations-summary.md](../../contour-nodeselector-tolerations-summary.md).
- **Never copy `nodeSelector` / `tolerations` / `computeClass` blocks between clusters** without rewriting them from scratch against the destination cluster's topology.
- **Always read the matrix** before editing any Contour values; cross-reference sibling cluster files for non-Contour scheduling.
- Wrong values strand pods on wrong nodes or leave them `Pending` indefinitely.
## R6 — Surgical edits only
The repo has ~30 cluster directories × dozens of apps each. The whole point of per-cluster overrides is divergence — accumulated, deliberate, often for tiered traffic or specialised hardware.
- **Never "normalise" values across clusters in the same PR as a feature change.** Cross-cluster clean-ups are their own PRs with their own scope and CMRs.
- **Never auto-update labels, image tags, or comments** on apps you weren't asked to touch.
- **One change-type per PR.** Reviewer cognition matters; rollback granularity matters.
## R7 — `helm-templates/<chart>/` is mostly upstream
Most charts here are vanilla upstream pulled via `helm pull`. The local `Chart.yaml` is often a thin wrapper that declares the upstream chart as a dependency. Editing a `templates/*.yaml` or the chart's own `values.yaml` silently forks the chart, and the fork is clobbered on the next upstream sync.
- **Never edit `helm-templates/<chart>/templates/` or `values.yaml` casually.** If a fork is intentional, follow [fork-upstream-chart](../platform/procedures/fork-upstream-chart.md) and document the reason in the chart's `README.md`.
- **Never bump `Chart.yaml` `dependencies[].version`** without (a) reading the upstream changelog, (b) running `helm dependency update` to refresh `Chart.lock`, and (c) calling out the bump in the PR description.
## R8 — Versioned chart siblings stay live during migrations
`<chart>``<chart>-green` (blue-green), `<chart>``<chart>-vX.Y.Z` (pinned upgrade target), `<chart>``<chart>-latest` (work-in-progress), `<chart>``<chart>-old` (retired but still referenced). Both directories may be referenced by Argo Applications during the migration window.
- **Never delete a versioned sibling** without confirming zero references in `github.com/Meesho/devops-infra-argo-config`.
- **Never "consolidate" siblings** into one chart in a maintenance PR. The split is intentional ([ADR-A2](../../wiki/analyses/ADR-A2-blue-green-sibling-pattern.md)).
## R9 — `fullnameOverride` is load-bearing
Helm's `fullnameOverride` controls the name of every released Service, Deployment, StatefulSet, ConfigMap, Secret, and PVC. Service DNS, PVC binding, ConfigMap references in other apps, and Argo Application names downstream all depend on it being stable.
- **Never change `fullnameOverride`** in any `custom-values.yaml`.
- A release-name migration is its own headline-of-the-PR change with platform-team approval, a documented before/after map, and an explicit reason.
## R10 — `manifests/` is cluster-wide singletons
`manifests/storageclass/*.yaml` is repo-global; a wrong StorageClass affects every PVC on every cluster that consumes it. `manifests/priorityclass/<cluster>/*.yaml` is per-cluster but cluster-wide; a wrong PriorityClass changes scheduling priority for every pod that references it.
- **Never edit `manifests/storageclass/`** or `manifests/priorityclass/<cluster>/` without platform-team review.
- **Never delete a StorageClass referenced by an existing PVC** — Kubernetes will not remove the StorageClass while bindings remain, but new PVCs will fail to provision.
## R11 — Image tags go through Meesho's Artifact Registry mirror
Production overrides pin images to `asia-southeast1-docker.pkg.dev/meesho-devops-admin-0622/admin/sre/<image>`, not upstream Docker Hub or Quay. The mirror exists for supply-chain control and rate-limit isolation.
- **Never introduce a Docker Hub / Quay / GCR / ECR upstream tag** in a production override.
- **Never use `:latest` or unpinned tags** in production overrides; an Argo CD reconcile is not the same as a controlled rollout.
## R12 — `repository.yaml` is automation-owned
Generated by `registry-bootstrap`. Hand edits will be silently overwritten on the next bootstrap run.
- **Never hand-edit `repository.yaml`.** If owner data is wrong, fix it in the upstream registry that feeds registry-bootstrap.
## R13 — Branch protection trumps everything
Direct push to `main` is blocked at the GitHub org level. PRs go through code review.
- **Never propose workflows that bypass branch protection.** If a hotfix is genuinely urgent, the path is "open a PR with a `hotfix/*` branch and request emergency review," not "force-push to main."
## R14 — Pre-existing schema/label drift is not yours to fix
Some clusters have inconsistencies in label values, indentation, key ordering, or comment style — accumulated technical-debt items. Some apps lack values keys their newer siblings have. Some clusters use long BU names (`supply`) while others use short (`supl`).
- **Never normalise label or BU values in unrelated PRs.** Cross-cutting clean-ups are their own PRs with their own scope and CMRs.
- **Never reformat a YAML file in passing.** Diffs full of indentation churn drown out the real change.
---
## What "non-negotiable" means
Each rule above has a documented reason and is the result of a real failure mode (or proximity to one). If you find yourself wanting to break a rule, the path is:
1. Write up the case in a doc (or PR description) explaining what would change and why.
2. Loop in the platform team for review.
3. If the rule should change, change *the rule first* in this file (with a PR to update it), then act.
4. If the rule should not change, find another way.
A merge that violates a rule here is a process incident, not a clever shortcut.