88 lines
5.3 KiB
Markdown
88 lines
5.3 KiB
Markdown
<!-- m-wiki: type=top-level slug=deploy-flow topic=null base-sha=5399a5ddc36b generated-at=2026-05-21 sources=[code:src/com/meesho/stages/deployArgoCD.groovy, code:src/com/meesho/stages/deployRingmaster.groovy, code:src/com/meesho/stages/notify.groovy, code:src/com/meesho/stages/helmGenerator.groovy] -->
|
|
|
|
> Generated 2026-05-21 at base-sha 5399a5ddc36b. Type: top-level. 4 sources.
|
|
|
|
# Deploy flow
|
|
|
|
The deploy phase is owned by [`deployArgoCD.groovy`](../../../src/com/meesho/stages/deployArgoCD.groovy) (the ArgoCD ceremony) and [`deployRingmaster.groovy`](../../../src/com/meesho/stages/deployRingmaster.groovy) (the callback to the higher-level deploy controllers). Two things to never mess with: the four-step order, and the canary gate.
|
|
|
|
## The four-step ArgoCD ceremony — load-bearing
|
|
|
|
`deployArgoCD.run()` ([lines 73-107](../../../src/com/meesho/stages/deployArgoCD.groovy)) calls these in strict order:
|
|
|
|
```
|
|
1. update_argo_repo (line 91) pushes the ArgoApplication YAML into devops-argo-config
|
|
so the app-of-apps registry sees the new app.
|
|
2. refresh_app_of_apps (line 94) argocd app sync ${appofapps} — materialises the new
|
|
Application object before the per-service sync needs it.
|
|
3. update_helm_repo (line 97) computes xms/xmx, renders values.yaml, pushes into
|
|
devops-helm-charts.
|
|
4. refresh_and_sync (line 100) argocd app sync ${app_name} --hard-refresh — the
|
|
actual service rollout. Uses --http-retry-max 3
|
|
--retry-backoff-duration 1m (lines 506, 526).
|
|
```
|
|
|
|
Steps 2 and 4 are **not interchangeable**. On first-deploy of a brand-new service, the Application object doesn't exist yet — step 2 creates it (as a downstream effect of the app-of-apps sync), step 4 reads it. Swap the order and step 4 fails on a missing Application. See [`docs/tribal-knowledge.md`](../../tribal-knowledge.md) §10 for the post-incident note.
|
|
|
|
## JVM memory auto-calculation
|
|
|
|
`update_helm_repo` ([lines 220-255](../../../src/com/meesho/stages/deployArgoCD.groovy)) derives JVM memory flags from the pod's `memory_limit`:
|
|
|
|
```groovy
|
|
memory_value = memory_limit * 0.5
|
|
xms = "${memory_value}M"
|
|
xmx = "${memory_value}M"
|
|
```
|
|
|
|
Both flags are set equal, derived from `memory_limit` (not `memory_request`), with no 0.75 multiplier and no 64m rounding. The historical claim "`xmx = memory_request * 0.75, xms = xmx * 0.5`" was wrong and has been reconciled out of [`docs/tribal-knowledge.md`](../../tribal-knowledge.md).
|
|
|
|
**Do not hard-code `-Xmx` in `JAVA_OPTS`** — the auto-computed value will collide with it, and the last value seen by the JVM wins depending on arg order. There is no `jvm_memory_override` flag (that referenced flag does not exist in code).
|
|
|
|
## Canary enforcement — sp0 / up0 in prd
|
|
|
|
[`deployArgoCD.groovy:408-430`](../../../src/com/meesho/stages/deployArgoCD.groovy):
|
|
|
|
```
|
|
enforceCanary = (priority_v2 ∈ {sp0, up0})
|
|
∧ (envrn == 'prd')
|
|
∧ ¬(service is canary | cron | worker | scheduler | consumer | node | headless)
|
|
```
|
|
|
|
When `enforceCanary` is true, the deploy hard-errors unless the Helm values declare:
|
|
|
|
- `canary.enabled = true`
|
|
- `canary.skipAnalysis = false`
|
|
- `canary.enableManualPromotion = true`
|
|
|
|
There is **no whitelist** and **no bypass flag**. A service that needs to skip canary on a high-priority prd path has to either (a) be classified out of `sp0/up0`, or (b) match one of the exempted service types listed above.
|
|
|
|
## Ringmaster vs Turbo-Turtle routing
|
|
|
|
[`deployRingmaster.groovy:55-89`](../../../src/com/meesho/stages/deployRingmaster.groovy):
|
|
|
|
```groovy
|
|
def build_user = currentBuild.rawBuild.getCause(Cause.UserIdCause).getUserId()
|
|
if (build_user == "ringmaster-bot") {
|
|
callApi(url, header, jsonData) // → ringmaster endpoint
|
|
} else {
|
|
// → http://turbo-turtle.meeshogcp.in (line 71)
|
|
// http://turbo-turtle.admin.meeshogcp.in (line 74)
|
|
sh "curl -s -X POST -H '$newCICD_Header' -w '\\n%{response_code}' $newCICD_URL -d '$newCICD_JSON'"
|
|
}
|
|
```
|
|
|
|
The string `"ringmaster-bot"` is a **load-bearing constant**. Renaming the bot user silently routes every Ringmaster callback to Turbo-Turtle, which rejects them.
|
|
|
|
The JSON payload is passed **inline** via `-d '$newCICD_JSON'` ([line 80](../../../src/com/meesho/stages/deployRingmaster.groovy)). Earlier documentation claimed a temp-file + `curl -d @<file>` pattern with `finally`-block cleanup — that pattern does **not** exist in the current code and was reconciled out of `docs/tribal-knowledge.md`.
|
|
|
|
## Deployment-tracker callback (notify.groovy)
|
|
|
|
[`notify.groovy:108-152`](../../../src/com/meesho/stages/notify.groovy) POSTs to one of:
|
|
|
|
- `http://deployment-tracker.meeshoint.in/api/1.0/deployment-tracker/jenkins/create` (AWS)
|
|
- `http://deployment-tracker.prd.meesho.int/api/1.0/deployment-tracker/jenkins/create` (GCP)
|
|
|
|
Only triggered on branches `main` / `master` / `gcp-main` / `gcp-master` ([line 34](../../../src/com/meesho/stages/notify.groovy)). Payload includes repository, team, link, job_name, tag, status, commit_id, error_msg. No retry — a single failed POST means the dashboard miscounts that deploy.
|
|
|
|
See also: [05-cross-cutting](05-cross-cutting.md), [concepts/whitelists](concepts/whitelists.md), [`docs/tribal-knowledge.md`](../../tribal-knowledge.md).
|