@decocms/start 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/skills/deco-api-call-dedup/SKILL.md +443 -0
- package/.cursor/skills/deco-apps-architecture/SKILL.md +255 -0
- package/.cursor/skills/deco-apps-architecture/app-pattern.md +288 -0
- package/.cursor/skills/deco-apps-architecture/commerce-types.md +239 -0
- package/.cursor/skills/deco-apps-architecture/new-app-guide.md +268 -0
- package/.cursor/skills/deco-apps-architecture/scripts-codegen.md +148 -0
- package/.cursor/skills/deco-apps-architecture/shared-utils.md +181 -0
- package/.cursor/skills/deco-apps-architecture/vtex-deep-structure.md +253 -0
- package/.cursor/skills/deco-apps-architecture/website-app.md +169 -0
- package/.cursor/skills/deco-apps-vtex-porting/SKILL.md +189 -0
- package/.cursor/skills/deco-apps-vtex-porting/adaptation-patterns.md +335 -0
- package/.cursor/skills/deco-apps-vtex-porting/commerce-porting.md +155 -0
- package/.cursor/skills/deco-apps-vtex-porting/cookie-auth-patterns.md +148 -0
- package/.cursor/skills/deco-apps-vtex-porting/structure-map.md +234 -0
- package/.cursor/skills/deco-apps-vtex-porting/transform-mapping.md +99 -0
- package/.cursor/skills/deco-apps-vtex-porting/website-porting.md +194 -0
- package/.cursor/skills/deco-apps-vtex-review/SKILL.md +234 -0
- package/.cursor/skills/deco-async-rendering-architecture/SKILL.md +270 -0
- package/.cursor/skills/deco-async-rendering-site-guide/SKILL.md +417 -0
- package/.cursor/skills/deco-cms-layout-caching/SKILL.md +293 -0
- package/.cursor/skills/deco-cms-route-config/SKILL.md +388 -0
- package/.cursor/skills/deco-core-architecture/SKILL.md +185 -0
- package/.cursor/skills/deco-core-architecture/blocks.md +196 -0
- package/.cursor/skills/deco-core-architecture/deco-vs-deco-start.md +191 -0
- package/.cursor/skills/deco-core-architecture/engine.md +220 -0
- package/.cursor/skills/deco-core-architecture/hooks-components.md +157 -0
- package/.cursor/skills/deco-core-architecture/plugins-clients.md +136 -0
- package/.cursor/skills/deco-core-architecture/runtime.md +116 -0
- package/.cursor/skills/deco-core-architecture/site-usage.md +165 -0
- package/.cursor/skills/deco-e2e-testing/SKILL.md +372 -0
- package/.cursor/skills/deco-e2e-testing/discovery.md +337 -0
- package/.cursor/skills/deco-e2e-testing/scripts/scaffold.sh +81 -0
- package/.cursor/skills/deco-e2e-testing/selectors.md +175 -0
- package/.cursor/skills/deco-e2e-testing/templates/package.json +18 -0
- package/.cursor/skills/deco-e2e-testing/templates/playwright.config.ts +65 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/baseline.ts +279 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/run-e2e.ts +194 -0
- package/.cursor/skills/deco-e2e-testing/templates/specs/ecommerce-flow.spec.ts +612 -0
- package/.cursor/skills/deco-e2e-testing/templates/tsconfig.json +12 -0
- package/.cursor/skills/deco-e2e-testing/templates/utils/metrics-collector.ts +918 -0
- package/.cursor/skills/deco-e2e-testing/troubleshooting.md +602 -0
- package/.cursor/skills/deco-edge-caching/SKILL.md +316 -0
- package/.cursor/skills/deco-full-analysis/SKILL.md +898 -0
- package/.cursor/skills/deco-full-analysis/checklists/asset-optimization.md +251 -0
- package/.cursor/skills/deco-full-analysis/checklists/bug-fix.md +189 -0
- package/.cursor/skills/deco-full-analysis/checklists/cache-strategy.md +144 -0
- package/.cursor/skills/deco-full-analysis/checklists/dependency-update.md +150 -0
- package/.cursor/skills/deco-full-analysis/checklists/hydration-fix.md +191 -0
- package/.cursor/skills/deco-full-analysis/checklists/image-optimization.md +180 -0
- package/.cursor/skills/deco-full-analysis/checklists/loader-optimization.md +165 -0
- package/.cursor/skills/deco-full-analysis/checklists/seo-fix.md +183 -0
- package/.cursor/skills/deco-full-analysis/checklists/site-cleanup.md +281 -0
- package/.cursor/skills/deco-full-analysis/discovery.md +548 -0
- package/.cursor/skills/deco-incident-debugging/SKILL.md +378 -0
- package/.cursor/skills/deco-incident-debugging/headless-mode.md +510 -0
- package/.cursor/skills/deco-incident-debugging/learnings-index.md +227 -0
- package/.cursor/skills/deco-incident-debugging/triage-workflow.md +312 -0
- package/.cursor/skills/deco-islands-migration/SKILL.md +251 -0
- package/.cursor/skills/deco-loader-n-plus-1-detector/SKILL.md +275 -0
- package/.cursor/skills/deco-performance-audit/SKILL.md +530 -0
- package/.cursor/skills/deco-performance-audit/tools-reference.md +428 -0
- package/.cursor/skills/deco-performance-audit/workflow.md +457 -0
- package/.cursor/skills/deco-server-functions-invoke/SKILL.md +92 -0
- package/.cursor/skills/deco-server-functions-invoke/architecture.md +166 -0
- package/.cursor/skills/deco-server-functions-invoke/generator.md +122 -0
- package/.cursor/skills/deco-server-functions-invoke/problem.md +98 -0
- package/.cursor/skills/deco-server-functions-invoke/troubleshooting.md +110 -0
- package/.cursor/skills/deco-site-deployment/SKILL.md +396 -0
- package/.cursor/skills/deco-site-memory-debugging/SKILL.md +121 -0
- package/.cursor/skills/deco-site-memory-debugging/cdp-connection.md +222 -0
- package/.cursor/skills/deco-site-memory-debugging/memory-analysis.md +362 -0
- package/.cursor/skills/deco-site-patterns/SKILL.md +124 -0
- package/.cursor/skills/deco-site-patterns/app-composition.md +337 -0
- package/.cursor/skills/deco-site-patterns/client-patterns.md +341 -0
- package/.cursor/skills/deco-site-patterns/cms-wiring.md +230 -0
- package/.cursor/skills/deco-site-patterns/section-patterns.md +340 -0
- package/.cursor/skills/deco-site-scaling-tuning/SKILL.md +240 -0
- package/.cursor/skills/deco-site-scaling-tuning/analysis-scripts.md +267 -0
- package/.cursor/skills/deco-start-architecture/SKILL.md +218 -0
- package/.cursor/skills/deco-start-architecture/admin-protocol.md +156 -0
- package/.cursor/skills/deco-start-architecture/cms-resolution.md +201 -0
- package/.cursor/skills/deco-start-architecture/code-quality.md +158 -0
- package/.cursor/skills/deco-start-architecture/gap-analysis.md +129 -0
- package/.cursor/skills/deco-start-architecture/sdk-utilities.md +197 -0
- package/.cursor/skills/deco-start-architecture/worker-entry-caching.md +154 -0
- package/.cursor/skills/deco-startup-analysis/SKILL.md +248 -0
- package/.cursor/skills/deco-storefront-test-checklist/SKILL.md +369 -0
- package/.cursor/skills/deco-tanstack-hydration-fixes/SKILL.md +468 -0
- package/.cursor/skills/deco-tanstack-navigation/SKILL.md +681 -0
- package/.cursor/skills/deco-tanstack-search/SKILL.md +411 -0
- package/.cursor/skills/deco-tanstack-storefront-patterns/SKILL.md +1013 -0
- package/.cursor/skills/deco-to-tanstack-migration/SKILL.md +518 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/codemod-commands.md +174 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/commerce/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/deco-framework/README.md +128 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/gotchas.md +719 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/imports/README.md +70 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/platform-hooks/README.md +154 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/signals/README.md +220 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/vite-config/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/package-json.md +55 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/root-route.md +110 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/router.md +96 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/setup-ts.md +167 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/vite-config.md +122 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/worker-entry.md +67 -0
- package/.cursor/skills/deco-typescript-fixes/SKILL.md +178 -0
- package/.cursor/skills/deco-typescript-fixes/common-fixes.md +330 -0
- package/.cursor/skills/deco-typescript-fixes/strategy.md +148 -0
- package/.cursor/skills/deco-variant-selection-perf/SKILL.md +272 -0
- package/.cursor/skills/deco-vtex-fetch-cache/SKILL.md +225 -0
- package/.cursor/skills/find-skills/SKILL.md +133 -0
- package/.cursor/skills/incident-report/SKILL.md +179 -0
- package/.cursor/skills/incident-report/references/5-whys.md +75 -0
- package/.cursor/skills/incident-report/templates/client-report.md +187 -0
- package/.cursor/skills/incident-report/templates/internal-report.md +206 -0
- package/.cursor/skills/template-skill/SKILL.md +38 -0
- package/.github/workflows/release.yml +32 -0
- package/.releaserc.json +25 -0
- package/CLAUDE.md +135 -0
- package/GAP_ANALYSIS.md +224 -0
- package/GAP_ANALYSIS_V2.md +1013 -0
- package/biome.json +39 -0
- package/knip.json +5 -0
- package/package.json +87 -0
- package/scripts/generate-blocks.ts +69 -0
- package/scripts/generate-invoke.ts +378 -0
- package/scripts/generate-schema.ts +657 -0
- package/src/admin/cors.ts +29 -0
- package/src/admin/decofile.ts +72 -0
- package/src/admin/index.ts +24 -0
- package/src/admin/invoke.ts +163 -0
- package/src/admin/liveControls.ts +29 -0
- package/src/admin/meta.ts +70 -0
- package/src/admin/render.ts +205 -0
- package/src/admin/schema.ts +686 -0
- package/src/admin/setup.ts +44 -0
- package/src/cms/index.ts +59 -0
- package/src/cms/loader.ts +180 -0
- package/src/cms/registry.ts +162 -0
- package/src/cms/resolve.ts +1005 -0
- package/src/cms/sectionLoaders.ts +294 -0
- package/src/hooks/DecoPageRenderer.tsx +444 -0
- package/src/hooks/LazySection.tsx +109 -0
- package/src/hooks/LiveControls.tsx +108 -0
- package/src/hooks/SectionErrorFallback.tsx +85 -0
- package/src/hooks/index.ts +8 -0
- package/src/index.ts +5 -0
- package/src/matchers/builtins.ts +184 -0
- package/src/matchers/posthog.ts +154 -0
- package/src/middleware/decoState.ts +55 -0
- package/src/middleware/healthMetrics.ts +131 -0
- package/src/middleware/index.ts +80 -0
- package/src/middleware/liveness.ts +21 -0
- package/src/middleware/observability.ts +205 -0
- package/src/routes/adminRoutes.ts +83 -0
- package/src/routes/cmsRoute.ts +302 -0
- package/src/routes/components.tsx +34 -0
- package/src/routes/index.ts +15 -0
- package/src/sdk/analytics.ts +72 -0
- package/src/sdk/cacheHeaders.ts +268 -0
- package/src/sdk/cachedLoader.ts +206 -0
- package/src/sdk/clx.ts +3 -0
- package/src/sdk/cookie.ts +39 -0
- package/src/sdk/createInvoke.ts +57 -0
- package/src/sdk/csp.ts +59 -0
- package/src/sdk/env.ts +27 -0
- package/src/sdk/index.ts +63 -0
- package/src/sdk/instrumentedFetch.ts +137 -0
- package/src/sdk/invoke.ts +133 -0
- package/src/sdk/mergeCacheControl.ts +150 -0
- package/src/sdk/redirects.ts +217 -0
- package/src/sdk/requestContext.ts +184 -0
- package/src/sdk/serverTimings.ts +68 -0
- package/src/sdk/signal.ts +41 -0
- package/src/sdk/sitemap.ts +143 -0
- package/src/sdk/urlUtils.ts +117 -0
- package/src/sdk/useDevice.ts +82 -0
- package/src/sdk/useId.ts +7 -0
- package/src/sdk/useScript.ts +101 -0
- package/src/sdk/workerEntry.ts +703 -0
- package/src/sdk/wrapCaughtErrors.ts +107 -0
- package/src/types/index.ts +39 -0
- package/src/types/widgets.ts +13 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deco-site-deployment
|
|
3
|
+
description: Manage Deco site configuration (env vars, scaling, resources) via the Kubernetes state secret and trigger redeployment. Handles multi-cloud deployment across AWS and GCP clusters.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deco Site Deployment
|
|
7
|
+
|
|
8
|
+
Manage a Deco site's configuration and trigger redeployment. Each site has a `state` secret in its Kubernetes namespace that controls env vars, scaling rules, resources, and more. Changing this secret and triggering a redeploy applies the new configuration.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
- Change environment variables for a site
|
|
13
|
+
- Adjust autoscaler settings (min/max scale, concurrency target)
|
|
14
|
+
- Modify resource requests/limits (CPU, memory)
|
|
15
|
+
- Trigger a redeployment of a site
|
|
16
|
+
- Debug what configuration a site is currently running with
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
- `kubectl` access to the target cluster
|
|
21
|
+
- `ADMIN_API_KEY` environment variable set (ask the user to set it if missing)
|
|
22
|
+
- `jq` and `base64` CLI tools
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
1. ASK USER → Which cluster to target? (ask every time)
|
|
28
|
+
2. READ STATE → kubectl get secret state -n sites-<sitename> → decode
|
|
29
|
+
3. MODIFY → Change the desired fields in the JSON
|
|
30
|
+
4. WRITE STATE → Encode and patch the secret on the TARGET cluster
|
|
31
|
+
5. REDEPLOY → POST to admin.deco.cx AND admin-gcp.deco.cx
|
|
32
|
+
6. VERIFY → Check pods are rolling out with new config
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Files in This Skill
|
|
36
|
+
|
|
37
|
+
| File | Purpose |
|
|
38
|
+
|------|---------|
|
|
39
|
+
| `SKILL.md` | Overview, SiteState schema, procedures |
|
|
40
|
+
|
|
41
|
+
## Important: Multi-Cloud Architecture
|
|
42
|
+
|
|
43
|
+
Deco runs on multiple clouds. **Always ask the user which cluster to target** before making changes.
|
|
44
|
+
|
|
45
|
+
**Known clusters:**
|
|
46
|
+
|
|
47
|
+
| Cloud | Context | Admin endpoint |
|
|
48
|
+
|-------|---------|---------------|
|
|
49
|
+
| AWS | `arn:aws:eks:sa-east-1:578348582779:cluster/eks-cluster-eksCluster-ea385ba` | `https://admin.deco.cx` |
|
|
50
|
+
| GCP | `gke_gke-cluster-453314_us-east1_sites` | `https://admin-gcp.deco.cx` |
|
|
51
|
+
|
|
52
|
+
**Workflow:**
|
|
53
|
+
|
|
54
|
+
1. **Ask the user** which cluster(s) to target
|
|
55
|
+
2. **Change the secret** on the target cluster(s) — switch kubectl context accordingly
|
|
56
|
+
3. **Trigger redeploy** on **both** admin endpoints (AWS and GCP) — the deployer on each cloud reads its own cluster's state secret and applies it:
|
|
57
|
+
- `https://admin.deco.cx` (reads from AWS cluster)
|
|
58
|
+
- `https://admin-gcp.deco.cx` (reads from GCP cluster)
|
|
59
|
+
|
|
60
|
+
If the change should apply to both clouds, you must patch the secret on **both** clusters before triggering redeploy.
|
|
61
|
+
|
|
62
|
+
## Important: ADMIN_API_KEY
|
|
63
|
+
|
|
64
|
+
The deploy endpoint requires authentication via `x-api-key` header. **Never hardcode the key.** Always read it from the `ADMIN_API_KEY` environment variable:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
if [ -z "$ADMIN_API_KEY" ]; then
|
|
68
|
+
echo "ERROR: Set the ADMIN_API_KEY environment variable first"
|
|
69
|
+
exit 1
|
|
70
|
+
fi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If the user hasn't set it, ask them to:
|
|
74
|
+
```
|
|
75
|
+
export ADMIN_API_KEY="<your-api-key>"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## SiteState Schema
|
|
79
|
+
|
|
80
|
+
The `state` secret contains a single key `state` with base64-encoded JSON matching the `SiteState` interface:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
interface SiteState {
|
|
84
|
+
// Source code reference
|
|
85
|
+
source?: {
|
|
86
|
+
type: "github";
|
|
87
|
+
repo: string;
|
|
88
|
+
owner: string;
|
|
89
|
+
commitSha: string;
|
|
90
|
+
};
|
|
91
|
+
deploymentId?: string;
|
|
92
|
+
|
|
93
|
+
// Environment variables
|
|
94
|
+
envVars?: Array<{ name: string; value: string }>;
|
|
95
|
+
|
|
96
|
+
// Autoscaling
|
|
97
|
+
scaling?: {
|
|
98
|
+
initialScale?: number;
|
|
99
|
+
minScale?: number;
|
|
100
|
+
maxScale?: number;
|
|
101
|
+
retentionPeriod?: string; // e.g. "20m"
|
|
102
|
+
metric?: ScaleMetric;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Resource requests and limits
|
|
106
|
+
resources?: {
|
|
107
|
+
requests?: { memory?: string; cpu?: string; "ephemeral-storage"?: string };
|
|
108
|
+
limits?: { memory?: string; cpu?: string; "ephemeral-storage"?: string };
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Caching
|
|
112
|
+
caching?: {
|
|
113
|
+
implementations?: Array<
|
|
114
|
+
| { type: "FILE_SYSTEM"; directory: string; maxSize: number; maxItems: number }
|
|
115
|
+
| { type: "CACHE_API" }
|
|
116
|
+
| { type: "REDIS"; url: string }
|
|
117
|
+
>;
|
|
118
|
+
loaderCacheStartThreshold?: number;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Domain bindings
|
|
122
|
+
domains?: Array<{ url: string; production?: boolean; validated?: boolean }>;
|
|
123
|
+
|
|
124
|
+
// Runtime
|
|
125
|
+
entrypoint?: string; // defaults to main.ts
|
|
126
|
+
runArgs?: string;
|
|
127
|
+
runnerImage?: string;
|
|
128
|
+
builderImage?: string;
|
|
129
|
+
|
|
130
|
+
// Advanced: volumes, node selection, tolerations, affinity
|
|
131
|
+
volumes?: k8s.V1Volume[];
|
|
132
|
+
volumeMounts?: k8s.V1VolumeMount[];
|
|
133
|
+
nodeSelector?: Record<string, string>;
|
|
134
|
+
tolerations?: k8s.V1Toleration[];
|
|
135
|
+
nodeAffinity?: k8s.V1NodeAffinity;
|
|
136
|
+
|
|
137
|
+
// Feature flags
|
|
138
|
+
features?: { usesDecofileHotSwap?: boolean };
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### ScaleMetric Types
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Concurrency-based (default, uses Knative KPA)
|
|
146
|
+
{ type: "concurrency"; target: number; targetUtilizationPercentage?: number }
|
|
147
|
+
|
|
148
|
+
// RPS-based (uses Knative KPA)
|
|
149
|
+
{ type: "rps"; target: number }
|
|
150
|
+
|
|
151
|
+
// CPU-based (uses Knative HPA)
|
|
152
|
+
// IMPORTANT: target is in millicores (e.g., 400 = 400m CPU)
|
|
153
|
+
{ type: "cpu"; target: number }
|
|
154
|
+
|
|
155
|
+
// Memory-based (uses Knative HPA)
|
|
156
|
+
// IMPORTANT: target is in megabytes (e.g., 512 = 512Mi)
|
|
157
|
+
{ type: "memory"; target: number }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### How Scaling Maps to Knative Annotations
|
|
161
|
+
|
|
162
|
+
| SiteState field | Knative annotation |
|
|
163
|
+
|-----------------|-------------------|
|
|
164
|
+
| `scaling.initialScale` | `autoscaling.knative.dev/initial-scale` |
|
|
165
|
+
| `scaling.minScale` | `autoscaling.knative.dev/min-scale` |
|
|
166
|
+
| `scaling.maxScale` | `autoscaling.knative.dev/max-scale` |
|
|
167
|
+
| `scaling.retentionPeriod` | `autoscaling.knative.dev/scale-to-zero-pod-retention-period` |
|
|
168
|
+
| `scaling.metric.type` | `autoscaling.knative.dev/metric` |
|
|
169
|
+
| `scaling.metric.target` | `autoscaling.knative.dev/target` |
|
|
170
|
+
| `scaling.metric.targetUtilizationPercentage` | `autoscaling.knative.dev/target-utilization-percentage` |
|
|
171
|
+
|
|
172
|
+
**Note:** `stable-window`, `scale-down-delay`, `max-scale-down-rate`, and `panic-threshold-percentage` are NOT in SiteState. These can only be set globally via the `config-autoscaler` ConfigMap in `knative-serving` namespace or per-revision by manually adding annotations after deployment.
|
|
173
|
+
|
|
174
|
+
## Procedures
|
|
175
|
+
|
|
176
|
+
### Procedure 1: Read Current State
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Ensure correct cluster context (ask user which cluster)
|
|
180
|
+
# AWS: kubectl config use-context arn:aws:eks:sa-east-1:578348582779:cluster/eks-cluster-eksCluster-ea385ba
|
|
181
|
+
# GCP: kubectl config use-context gke_gke-cluster-453314_us-east1_sites
|
|
182
|
+
kubectl config use-context <TARGET_CLUSTER_CONTEXT>
|
|
183
|
+
|
|
184
|
+
# Read and decode
|
|
185
|
+
kubectl get secret state -n sites-<SITENAME> -o json \
|
|
186
|
+
| jq -r '.data.state' | base64 -d | jq '.'
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Procedure 2: Modify State
|
|
190
|
+
|
|
191
|
+
Extract, modify, and write back:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
SITENAME="fila-store"
|
|
195
|
+
NS="sites-${SITENAME}"
|
|
196
|
+
|
|
197
|
+
# 1. Extract current state
|
|
198
|
+
STATE=$(kubectl get secret state -n $NS -o json | jq -r '.data.state' | base64 -d)
|
|
199
|
+
|
|
200
|
+
# 2. Modify with jq (examples below)
|
|
201
|
+
# ... see specific modification examples ...
|
|
202
|
+
|
|
203
|
+
# 3. Encode and patch
|
|
204
|
+
ENCODED=$(echo "$NEW_STATE" | base64)
|
|
205
|
+
kubectl patch secret state -n $NS --type='json' \
|
|
206
|
+
-p="[{\"op\":\"replace\",\"path\":\"/data/state\",\"value\":\"${ENCODED}\"}]"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Procedure 3: Trigger Redeploy
|
|
210
|
+
|
|
211
|
+
**Must deploy to BOTH clouds:**
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
if [ -z "$ADMIN_API_KEY" ]; then
|
|
215
|
+
echo "ERROR: Set ADMIN_API_KEY env var first"
|
|
216
|
+
exit 1
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
SITENAME="fila-store"
|
|
220
|
+
|
|
221
|
+
# Deploy to AWS
|
|
222
|
+
curl -s --location "https://admin.deco.cx/live/invoke/deco-sites/admin/actions/hosting/deploy.ts" \
|
|
223
|
+
--header "x-api-key: ${ADMIN_API_KEY}" \
|
|
224
|
+
--header "Content-Type: application/json" \
|
|
225
|
+
--data "{\"sitename\": \"${SITENAME}\"}"
|
|
226
|
+
|
|
227
|
+
# Deploy to GCP
|
|
228
|
+
curl -s --location "https://admin-gcp.deco.cx/live/invoke/deco-sites/admin/actions/hosting/deploy.ts" \
|
|
229
|
+
--header "x-api-key: ${ADMIN_API_KEY}" \
|
|
230
|
+
--header "Content-Type: application/json" \
|
|
231
|
+
--data "{\"sitename\": \"${SITENAME}\"}"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Procedure 4: Verify Deployment
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Watch pods rolling out
|
|
238
|
+
kubectl get pods -n sites-${SITENAME} -w
|
|
239
|
+
|
|
240
|
+
# Check the new revision
|
|
241
|
+
kubectl get rev -n sites-${SITENAME} --sort-by=.metadata.creationTimestamp | tail -3
|
|
242
|
+
|
|
243
|
+
# Verify annotations on new revision
|
|
244
|
+
kubectl get rev -n sites-${SITENAME} -o json | \
|
|
245
|
+
jq '.items[-1].metadata.annotations | with_entries(select(.key | startswith("autoscaling")))'
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Common Modification Examples
|
|
249
|
+
|
|
250
|
+
### Change Scaling Parameters
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Set target concurrency to 30, min 10, max 40
|
|
254
|
+
NEW_STATE=$(echo "$STATE" | jq '
|
|
255
|
+
.scaling.minScale = 10 |
|
|
256
|
+
.scaling.maxScale = 40 |
|
|
257
|
+
.scaling.initialScale = 10 |
|
|
258
|
+
.scaling.metric = {
|
|
259
|
+
"type": "concurrency",
|
|
260
|
+
"target": 30,
|
|
261
|
+
"targetUtilizationPercentage": 70
|
|
262
|
+
}
|
|
263
|
+
')
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Add/Change Environment Variable
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Set or update an env var (upsert pattern)
|
|
270
|
+
VARNAME="MY_VAR"
|
|
271
|
+
VARVALUE="my-value"
|
|
272
|
+
NEW_STATE=$(echo "$STATE" | jq --arg name "$VARNAME" --arg val "$VARVALUE" '
|
|
273
|
+
if (.envVars | map(.name) | index($name)) then
|
|
274
|
+
.envVars = [.envVars[] | if .name == $name then .value = $val else . end]
|
|
275
|
+
else
|
|
276
|
+
.envVars += [{"name": $name, "value": $val}]
|
|
277
|
+
end
|
|
278
|
+
')
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Remove Environment Variable
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
VARNAME="MY_VAR"
|
|
285
|
+
NEW_STATE=$(echo "$STATE" | jq --arg name "$VARNAME" '
|
|
286
|
+
.envVars = [.envVars[] | select(.name != $name)]
|
|
287
|
+
')
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Change Resource Requests/Limits
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
NEW_STATE=$(echo "$STATE" | jq '
|
|
294
|
+
.resources.requests.cpu = "1000m" |
|
|
295
|
+
.resources.requests.memory = "2Gi" |
|
|
296
|
+
.resources.limits.memory = "4Gi"
|
|
297
|
+
')
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Add V8 Flags via runArgs
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Reduce V8 max heap to force more frequent GC
|
|
304
|
+
NEW_STATE=$(echo "$STATE" | jq '
|
|
305
|
+
.runArgs = "--v8-flags=--max-old-space-size=512"
|
|
306
|
+
')
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Complete Example: Update Scaling on a Specific Cluster
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
#!/bin/bash
|
|
313
|
+
set -e
|
|
314
|
+
|
|
315
|
+
if [ -z "$ADMIN_API_KEY" ]; then
|
|
316
|
+
echo "ERROR: export ADMIN_API_KEY=<key> first"
|
|
317
|
+
exit 1
|
|
318
|
+
fi
|
|
319
|
+
|
|
320
|
+
SITENAME="fila-store"
|
|
321
|
+
NS="sites-${SITENAME}"
|
|
322
|
+
|
|
323
|
+
# Ask user which cluster to target, then set:
|
|
324
|
+
# AWS: CLUSTER="arn:aws:eks:sa-east-1:578348582779:cluster/eks-cluster-eksCluster-ea385ba"
|
|
325
|
+
# GCP: CLUSTER="gke_gke-cluster-453314_us-east1_sites"
|
|
326
|
+
CLUSTER="<TARGET_CLUSTER_CONTEXT>"
|
|
327
|
+
|
|
328
|
+
# Switch to target cluster
|
|
329
|
+
kubectl config use-context "$CLUSTER"
|
|
330
|
+
|
|
331
|
+
# Read current state
|
|
332
|
+
STATE=$(kubectl get secret state -n $NS -o json | jq -r '.data.state' | base64 -d)
|
|
333
|
+
echo "Current scaling:"
|
|
334
|
+
echo "$STATE" | jq '.scaling'
|
|
335
|
+
|
|
336
|
+
# Update scaling
|
|
337
|
+
NEW_STATE=$(echo "$STATE" | jq '
|
|
338
|
+
.scaling.minScale = 10 |
|
|
339
|
+
.scaling.maxScale = 40 |
|
|
340
|
+
.scaling.initialScale = 10 |
|
|
341
|
+
.scaling.metric = {
|
|
342
|
+
"type": "concurrency",
|
|
343
|
+
"target": 30,
|
|
344
|
+
"targetUtilizationPercentage": 70
|
|
345
|
+
}
|
|
346
|
+
')
|
|
347
|
+
echo "New scaling:"
|
|
348
|
+
echo "$NEW_STATE" | jq '.scaling'
|
|
349
|
+
|
|
350
|
+
# Apply to secret on target cluster
|
|
351
|
+
ENCODED=$(echo "$NEW_STATE" | base64)
|
|
352
|
+
kubectl patch secret state -n $NS --type='json' \
|
|
353
|
+
-p="[{\"op\":\"replace\",\"path\":\"/data/state\",\"value\":\"${ENCODED}\"}]"
|
|
354
|
+
echo "Secret updated on $CLUSTER"
|
|
355
|
+
|
|
356
|
+
# Redeploy BOTH clouds (each reads its own cluster's secret)
|
|
357
|
+
echo "Deploying to AWS..."
|
|
358
|
+
curl -sf --location "https://admin.deco.cx/live/invoke/deco-sites/admin/actions/hosting/deploy.ts" \
|
|
359
|
+
--header "x-api-key: ${ADMIN_API_KEY}" \
|
|
360
|
+
--header "Content-Type: application/json" \
|
|
361
|
+
--data "{\"sitename\": \"${SITENAME}\"}"
|
|
362
|
+
|
|
363
|
+
echo "Deploying to GCP..."
|
|
364
|
+
curl -sf --location "https://admin-gcp.deco.cx/live/invoke/deco-sites/admin/actions/hosting/deploy.ts" \
|
|
365
|
+
--header "x-api-key: ${ADMIN_API_KEY}" \
|
|
366
|
+
--header "Content-Type: application/json" \
|
|
367
|
+
--data "{\"sitename\": \"${SITENAME}\"}"
|
|
368
|
+
|
|
369
|
+
echo "Done. Watch rollout:"
|
|
370
|
+
echo " kubectl get pods -n $NS -w"
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Troubleshooting
|
|
374
|
+
|
|
375
|
+
### Deploy returns error
|
|
376
|
+
- Check `ADMIN_API_KEY` is set and valid
|
|
377
|
+
- Verify the sitename matches exactly (no `sites-` prefix)
|
|
378
|
+
- Check both admin endpoints are reachable
|
|
379
|
+
|
|
380
|
+
### Secret patch fails
|
|
381
|
+
- Ensure you're on the correct cluster context for the target cloud
|
|
382
|
+
- Ensure the base64 encoding is correct (no extra newlines)
|
|
383
|
+
- Verify the secret exists: `kubectl get secret state -n sites-<sitename>`
|
|
384
|
+
|
|
385
|
+
### New pods don't pick up changes
|
|
386
|
+
- The deploy creates a new Knative revision — old pods stay until traffic shifts
|
|
387
|
+
- Check for deployment errors: `kubectl get ksvc -n sites-<sitename> -o json | jq '.status.conditions'`
|
|
388
|
+
- Verify the state secret was actually updated: re-read and decode it
|
|
389
|
+
|
|
390
|
+
### Annotations not applied
|
|
391
|
+
- The deployer only supports fields in SiteState. For annotations like `stable-window` or `scale-down-delay`, you must set them globally in `config-autoscaler` configmap in `knative-serving` namespace, or manually patch the revision after deployment.
|
|
392
|
+
|
|
393
|
+
## Related Skills
|
|
394
|
+
|
|
395
|
+
- `deco-site-memory-debugging` — Debug memory issues on running pods
|
|
396
|
+
- `deco-incident-debugging` — Incident response and triage
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: deco-site-memory-debugging
|
|
3
|
+
description: Debug memory issues on Deno/Fresh sites running on Kubernetes/Knative. Connects to pods via Chrome DevTools Protocol (CDP) to analyze heap, ArrayBuffers, Response leaks, and native memory. Guides GC analysis and V8 heap tuning.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deco Site Memory Debugging
|
|
7
|
+
|
|
8
|
+
Debug memory issues on Deno sites running in Kubernetes pods using Chrome DevTools Protocol (CDP) over WebSocket.
|
|
9
|
+
|
|
10
|
+
## When to Use This Skill
|
|
11
|
+
|
|
12
|
+
- Pod memory usage is high or growing over time
|
|
13
|
+
- Kubernetes OOMKill events on site pods
|
|
14
|
+
- Need to identify what's consuming memory inside a Deno process
|
|
15
|
+
- Investigating Response/Request body leaks
|
|
16
|
+
- Need to determine if memory is a real leak vs lazy GC
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
1. IDENTIFY POD → kubectl get pods -n sites-<sitename>
|
|
22
|
+
2. PORT-FORWARD → kubectl port-forward <pod> 9229:9229
|
|
23
|
+
3. GET WS URL → curl http://127.0.0.1:9229/json/list
|
|
24
|
+
4. CONNECT CDP → WebSocket to the debuggerUrl
|
|
25
|
+
5. FORCE GC → HeapProfiler.collectGarbage
|
|
26
|
+
6. ANALYZE MEMORY → Deno.memoryUsage() + queryObjects + heap snapshot
|
|
27
|
+
7. DIAGNOSE → Is it a leak or lazy GC?
|
|
28
|
+
8. RECOMMEND → Tune --v8-flags=--max-old-space-size or fix leak
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Files in This Skill
|
|
32
|
+
|
|
33
|
+
| File | Purpose |
|
|
34
|
+
|------|---------|
|
|
35
|
+
| `SKILL.md` | This overview and quick reference |
|
|
36
|
+
| `cdp-connection.md` | How to connect to pods and common pitfalls |
|
|
37
|
+
| `memory-analysis.md` | Step-by-step memory analysis procedures |
|
|
38
|
+
|
|
39
|
+
## Key Concept: GC is Lazy
|
|
40
|
+
|
|
41
|
+
**V8's garbage collector is lazy by design.** It won't collect garbage until memory pressure forces it to. A pod showing 1.8 GB RSS might drop to 700 MB after a forced GC — meaning there was no leak, just uncollected garbage.
|
|
42
|
+
|
|
43
|
+
**Always force GC before concluding there's a leak:**
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
HeapProfiler.collectGarbage (via CDP)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then check `Deno.memoryUsage()` again. The difference between before-GC and after-GC tells you how much was reclaimable garbage vs actual retained memory.
|
|
50
|
+
|
|
51
|
+
### Recommendation: Reduce Max Heap Size
|
|
52
|
+
|
|
53
|
+
If post-GC memory is reasonable but pre-GC memory is causing OOMKills or high pod memory:
|
|
54
|
+
|
|
55
|
+
**Decrease the V8 max old space size** so GC runs more frequently:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
--v8-flags=--max-old-space-size=512
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This forces V8 to GC more aggressively instead of letting garbage accumulate. For most Deco sites this doesn't affect performance because the actual live heap is much smaller than the default limit. The GC runs are fast (milliseconds) and the trade-off is worth it to keep RSS predictable.
|
|
62
|
+
|
|
63
|
+
Example Deno flags:
|
|
64
|
+
```bash
|
|
65
|
+
deno run --v8-flags=--max-old-space-size=512 -A main.ts
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Memory Breakdown Model
|
|
69
|
+
|
|
70
|
+
RSS is composed of multiple layers. You must understand what each layer represents:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
RSS = V8 Heap + V8 External + Native (untracked)
|
|
74
|
+
|
|
75
|
+
V8 Heap → JavaScript objects, closures, strings, compiled code
|
|
76
|
+
V8 External → ArrayBuffers (including a ~304MB static V8/ICU data buffer)
|
|
77
|
+
Native → Deno Rust runtime, module graph, JIT code cache, mmap'd files, thread stacks
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use `Deno.memoryUsage()` to get the breakdown:
|
|
81
|
+
- `rss`: Total resident set size
|
|
82
|
+
- `heapUsed`: V8 JavaScript heap
|
|
83
|
+
- `heapTotal`: V8 heap capacity
|
|
84
|
+
- `external`: V8 external allocations (ArrayBuffers)
|
|
85
|
+
- `rss - heapUsed - external` = native/untracked memory
|
|
86
|
+
|
|
87
|
+
**The native gap is normal.** For a large Deno/Fresh app with thousands of modules, 500MB-1GB of native memory is expected (JIT compiled code, Rust allocator, module cache). This is NOT a leak.
|
|
88
|
+
|
|
89
|
+
## Common Memory Consumers
|
|
90
|
+
|
|
91
|
+
| What | Typical Size | Is It a Problem? |
|
|
92
|
+
|------|-------------|-----------------|
|
|
93
|
+
| Static V8/ICU ArrayBuffer | ~304 MB | No — built into V8, constant |
|
|
94
|
+
| Deno module cache on disk | ~100-200 MB | No — normal for large apps |
|
|
95
|
+
| V8 JIT compiled code | ~200-500 MB | No — proportional to loaded modules |
|
|
96
|
+
| Response bodies not consumed | Variable, grows | **YES — leak if bodyUsed=false** |
|
|
97
|
+
| OpenTelemetry export buffers | ~10-50 MB | Minor — accumulates slowly |
|
|
98
|
+
| Rendered HTML strings (SSR cache) | ~20-100 MB | Monitor — should be bounded |
|
|
99
|
+
| LRU cache metadata | Small (booleans) | No — only stores `true` with size tracking |
|
|
100
|
+
|
|
101
|
+
## Diagnostic Decision Tree
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Pod memory high?
|
|
105
|
+
├── Force GC → Memory drops significantly?
|
|
106
|
+
│ ├── YES → Not a leak. Recommend reducing --max-old-space-size
|
|
107
|
+
│ └── NO → Real retained memory. Continue investigation:
|
|
108
|
+
│ ├── Check Response objects (queryObjects Response.prototype)
|
|
109
|
+
│ │ └── bodyUsed=false count high? → Response body leak
|
|
110
|
+
│ ├── Check ArrayBuffers
|
|
111
|
+
│ │ └── Many large OTEL/JSON buffers? → Export/cache leak
|
|
112
|
+
│ ├── Check heap snapshot top consumers
|
|
113
|
+
│ │ └── Large HTML strings? → SSR cache unbounded
|
|
114
|
+
│ └── Large native gap (RSS - heap - external)?
|
|
115
|
+
│ └── Normal for large Deno apps (JIT + Rust runtime)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Related Skills
|
|
119
|
+
|
|
120
|
+
- `deco-incident-debugging` — For general incident response and triage
|
|
121
|
+
- `deco-performance-audit` — For deep performance analysis
|