sync-ci-to-staging
npx skills add https://github.com/oldwinter/skills --skill sync-ci-to-staging
Agent 安装分布
Skill 文档
Sync CI to Staging Skill
æ¤ skill æä¾å° Kubernetes kustomization é ç½®ä» CI ç¯å¢åæ¥å° Staging ç¯å¢ç工使µï¼ç¨äº simplex-gitops ä»åºã
â ï¸ å ³é®ï¼Staging ç¯å¢é¨ç½²çç¥
Staging ç¯å¢å¯ä»¥èªå¨åæ¥ï¼ä½éè¦è°¨æ æä½ã
工使µç¨ï¼
- â æ´æ° kustomization.yamlï¼å¯èªå¨åï¼
- â æäº¤å¹¶æ¨éå° GitLabï¼å¯èªå¨åï¼
- âï¸ ArgoCD åæ¥å° staging é群 – å¯ä»¥èªå¨ï¼ä½å»ºè®®ç¡®è®¤
æ¨éåæ´åï¼åç¥ç¨æ·ï¼
- åæ´å·²æ¨éå°ä»åº
- Staging ArgoCD åºç¨ä¼èªå¨æ£æµåæ´å¹¶åæ¥ï¼å¦æé ç½®äºèªå¨åæ¥ï¼
- 妿æªé ç½®èªå¨åæ¥ï¼ç¨æ·éè¦æå¨è§¦å忥
# æ¥çå¾
忥çåæ´ï¼å®å
¨ï¼åªè¯»ï¼
argocd app get simplex-aws-staging
argocd app diff simplex-aws-staging
# æå¨åæ¥ï¼å¦æéè¦ï¼
argocd app sync simplex-aws-staging
ç¯å¢å·®å¼ç½åå
以ä¸é 置项å¨åç¯å¢é´é¢æä¸åï¼åæ¥æ¶åºè·³è¿ï¼ä¸éè¦å ³æ³¨ï¼
| ç½åå项 | åå |
|---|---|
database.default.link |
åç¯å¢ç¬ç« RDS å®ä¾ |
redis.default.address |
åç¯å¢ç¬ç« MemoryDB |
mongodb.default.uri |
åç¯å¢ç¬ç« DocumentDB |
rabbitmq.default.url |
åç¯å¢ç¬ç« MQ broker |
stripe.publishableKey / secretKey / webhookSecret |
CI ç¨ test keysï¼Staging ç¨ live keys |
payment.*.stripePriceId |
ä¸å Stripe è´¦æ·ç Price ID |
campaign.sendEmails.redirectEnabled |
CI=trueï¼å®å ¨æ¨¡å¼ï¼ï¼Staging=false |
kubernetes/scripts/compare-configs.pyå·²å ç½®æ¤ç½ååï¼diff æ¶èªå¨æ 记为 “expected”ã
æä»¶ä½ç½®
kubernetes/overlays/aws-ci/kustomization.yaml # CI é
ç½®
kubernetes/overlays/aws-staging/kustomization.yaml # Staging é
ç½®
kubernetes/overlays/aws-ci/configs/ # CI æå¡é
ç½®æä»¶
kubernetes/overlays/aws-staging/configs/ # Staging æå¡é
ç½®æä»¶
å¿«éå½ä»¤
æ¥ç YAML é 置差å¼ï¼æ¨èï¼æ¯æç½ååï¼
# å¨ kubernetes/ ç®å½ä¸è¿è¡
cd kubernetes
# å¯¹æ¯ simplex-api é
ç½®ï¼é»è®¤ï¼åªæ¾ç¤ºå·®å¼ï¼
make config-diff
# å¯¹æ¯æå®æå¡
make config-diff SVC=simplex-gateway
make config-diff SVC=simplex-router-backend
# æ¾ç¤ºç½åå项详æ
python3 scripts/compare-configs.py --diff-only --show-expected
# JSON æ ¼å¼è¾åºï¼éåèæ¬å¤çï¼
python3 scripts/compare-configs.py --json --diff-only
# ååºææå¯å¯¹æ¯çæå¡
make list-services
æ¥çéåå·®å¼
# 使ç¨åæ¥èæ¬
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --diff
# æä½¿ç¨ make ç®æ ï¼å¦æå¨ kubernetes/ ç®å½ï¼
make compare-ci-staging-images
æ¥çé 置差å¼ï¼patches/ç®å½çº§å«ï¼
# æ¯è¾ææé
ç½®ï¼ConfigMaps, Secrets çï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py
# 详ç»å·®å¼ï¼å
嫿件å
容忴ï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py --detailed
# åªæ¾ç¤ºå®å
¨å¯åæ¥çé
ç½®ï¼æé¤ secrets, ingressï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py --detailed --safe-only
# æ¯è¾ç¹å®æä»¶
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py --file anotherme-agent-env-configmap.yaml --detailed
忥éå
# 忥ç¹å®æå¡
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --images front,anotherme-agent
# 忥ææéåï¼å
dry-runï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --all --dry-run
# 忥ææéåï¼åºç¨åæ´ï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --all
忥工使µ
æ¥éª¤ 0ï¼å®¡æ¥ææå·®å¼ï¼æ¨èï¼
å¨åæ¥ä»»ä½å 容ä¹åï¼å ¨é¢äºè§£ææå·®å¼ï¼
# æ¯è¾éå
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --diff
# æ¯è¾é
ç½®ï¼ä»
å®å
¨å¯å®¡æ¥çï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py --detailed --safe-only
è¿å°æ¾ç¤ºï¼
- ð éåæ ç¾å·®å¼ï¼æå¡çæ¬ä¸å
- ð ConfigMap å·®å¼ï¼é ç½®åæ´ï¼å å«è¯¦ç»å·®å¼ï¼
- ð ç¯å¢ç¹å®é ç½®ï¼ä¸åºåæ¥çå 容
- â æ°èµæºï¼CI 䏿°å¢ä½ staging 䏿²¡æçé ç½®
æ¥éª¤ 1ï¼æ¯è¾ç¯å¢
è¿è¡ diff å½ä»¤æ¥ç CI å Staging ä¹é´çå·®å¼ï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --diff
è¿å°æ¾ç¤ºï¼
- ð æ ç¾ä¸åï¼çæ¬ä¸åçæå¡
- â æ ç¾ç¸åï¼å·²åæ¥çæå¡
- â ï¸ ä» CIï¼åªå¨ CI ä¸çæå¡
- â ï¸ ä» STAGINGï¼åªå¨ Staging ä¸çæå¡
æ¥éª¤ 2ï¼å®¡æ¥å¹¶éæ©æå¡
å³å®æ¨å¹¿åªäºæå¡ãå¸¸è§æ¨¡å¼ï¼
# æ¨å¹¿å个å
³é®æå¡
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --images front --dry-run
# æ¨å¹¿å端æå¡
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --images front,front-homepage --dry-run
# æ¨å¹¿ææ AI æå¡
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --images anotherme-agent,anotherme-api,anotherme-search,anotherme-worker --dry-run
# æ¨å¹¿ææå
容
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --all --dry-run
æ¥éª¤ 3ï¼åºç¨åæ´
å®¡æ¥ dry-run è¾åºåï¼åºç¨åæ´ï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --images <services>
æ¥éª¤ 4ï¼æäº¤å¹¶æ¨é
cd /path/to/simplex-gitops
git add kubernetes/overlays/aws-staging/kustomization.yaml
git commit -m "chore: ä» CI æ¨å¹¿ <services> å° staging"
git push
éè¦ï¼æ¨éå ArgoCD 伿£æµåæ´ã
æ¥éª¤ 5ï¼Staging 忥ï¼èªå¨ææå¨ï¼
æ¨é宿åï¼staging ç¯å¢ç忥åå³äº ArgoCD é ç½®ï¼
妿é ç½®äºèªå¨åæ¥ï¼
# æ¥çåæ¥ç¶æ
argocd app get simplex-aws-staging
argocd app wait simplex-aws-staging --health
妿éè¦æå¨åæ¥ï¼
# æ¥çå¾
忥çåæ´
argocd app get simplex-aws-staging
argocd app diff simplex-aws-staging
# æå¨è§¦å忥
argocd app sync simplex-aws-staging
æéè¿ ArgoCD Web UI æå¨ç¹å» Sync æé®ï¼
- URL: http://192.168.10.117:31006
- æ¾å°
simplex-aws-stagingåºç¨ - ç¹å» “SYNC” æé®
å¯è½éè¦åæ¥çé ç½®é¨å
该 skill ç°å¨æä¾ä¸¤ä¸ªäºè¡¥çå·¥å ·ï¼
sync_images.py– å¤çéåæ ç¾åæ¥ï¼ä¸»è¦ç¨ä¾ï¼compare_configs.py– è¯å«é 置差å¼ï¼æ°åè½ï¼
èªå¨é ç½®å·®å¼æ£æµ
compare_configs.py èæ¬èªå¨è¯å«ä»¥ä¸å
容çå·®å¼ï¼
1. patches/ ä¸ç ConfigMaps å Secrets
èæ¬å°æ¯ä¸ªæä»¶å类为ï¼
| ç±»å« | ç¤ºä¾ | åæ¥å»ºè®® |
|---|---|---|
| â å®å ¨å¯å®¡æ¥ | *-env-configmap.yaml |
ä»ç»å®¡æ¥ï¼å¯è½éè¦éæ©æ§åæ¥ |
| ð Secrets | *-secrets.yaml |
æ°¸ä¸åæ¥ – ç¯å¢ç¹å® |
| ð Ingress | ingress.yaml |
æ°¸ä¸åæ¥ – ååä¸å |
| âï¸ åºç¡è®¾æ½ | gateway-cm0-*, router-cm0-*, api-cm0-* |
é常æ¯ç¯å¢ç¹å®ç |
ä½¿ç¨æ¹æ³ï¼
# æ¾ç¤ºææé
置差å¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py
# æ¾ç¤ºè¯¦ç»å·®å¼ï¼å
嫿件å
容忴ï¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py --detailed
# åªæ¾ç¤ºå®å
¨å¯å®¡æ¥çé
ç½®
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py --detailed --safe-only
# æ¯è¾ç¹å®æä»¶
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py --file anotherme-agent-env-configmap.yaml --detailed
è¾åºå æ¬ï¼
- ð æå·®å¼çæä»¶ï¼æå®å ¨æ§åç±»ï¼
- â CI 䏿°å¢çæä»¶
- â CI ä¸å é¤çæä»¶
- â ç¸åçæä»¶
- ð 详ç»çåæ´åæï¼æ·»å /å é¤/ä¿®æ¹çé®ï¼
- ð¡ åæ¥å»ºè®®
2. kustomization.yaml ä¸çæ°èµæº
èæ¬è¿æ¯è¾ resources: å patches: é¨åï¼
- â CI 䏿°å¢çèµæº
- â CI ä¸å é¤çèµæº
- ð å ±åçèµæº
常è§é 置差å¼
åºäºåæï¼å ¸åå·®å¼å æ¬ï¼
| é ç½®æä»¶ | 常è§å·®å¼ | åæ¥ï¼ |
|---|---|---|
anotherme-agent-env-configmap.yaml |
MQ_HOST, REDIS_URL, API keys | â ï¸ éæ©æ§ |
anotherme-search-env-configmap.yaml |
LLM presets, RABBITMQ_URL, API keys | â ï¸ éæ©æ§ |
frontend-env.yaml |
API_URL, APP_ENV | â æ°¸ä¸ï¼ç¯å¢ç¹å®ï¼ |
simplex-cron-env-configmap.yaml |
RABBITMQ_URL | â ï¸ éæ©æ§ |
anotherme-agent-secrets.yaml |
ææ secret å¼ | â æ°¸ä¸ |
ingress.yaml |
主æºå, TLS é ç½® | â æ°¸ä¸ |
*-cm0-configmap.yaml |
åºç¡è®¾æ½è®¾ç½® | â éå¸¸ä¸ |
æå¨åæ¥ ConfigMapsï¼å¿ è¦æ¶ï¼
对äºè¯å«ä¸ºå®å ¨å¯å®¡æ¥çé ç½®ï¼å¯ä»¥å¨ä»ç»å®¡æ¥åæå¨åæ¥ï¼
# 1. å
æ¥ç详ç»å·®å¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py \
--file anotherme-agent-env-configmap.yaml --detailed
# 2. æå¨å®¡æ¥åºåæ¥åªäºé®
# æäºé®å¦ REDIS_URL, MQ_HOST æ¯ç¯å¢ç¹å®ç
# å
¶ä»å¦åè½æ å¿æ LLM presets å¯è½éè¦åæ¥
# 3. 妿éè¦ï¼æå¨ç¼è¾ staging æä»¶
vim kubernetes/overlays/aws-staging/patches/anotherme-agent-env-configmap.yaml
# 4. æäº¤å¹¶æ¨é
git add kubernetes/overlays/aws-staging/patches/
git commit -m "chore: ä» CI 忥ç¹å®é
ç½®é®"
git push
æ§æå¨æ¨¡å¼ï¼ä»ç¶ææï¼
éåæ ç¾ï¼ä¸»è¦åæ¥ç®æ ï¼
ä½äº images: é¨åãè¿æ¯ sync_images.py èæ¬èªå¨å¤ççå
容ã
ConfigMap Patchesï¼éè¦æå¨å®¡æ¥ï¼
patches/ ç®å½ä¸çæä»¶å¯è½å
å«ç¯å¢ç¹å®çå¼ï¼
| Patch æä»¶ | ç¨é | 忥èè |
|---|---|---|
api-cm0-configmap.yaml |
API é ç½® | é常æ¯ç¯å¢ç¹å®çï¼ä¸åæ¥ |
gateway-cm0-configmap.yaml |
Gateway é ç½® | é常æ¯ç¯å¢ç¹å®ç |
anotherme-agent-env-configmap.yaml |
Agent é ç½® | å¯è½éè¦éæ©æ§åæ¥ |
anotherme-agent-secrets.yaml |
Agent secrets | æ°¸ä¸åæ¥ï¼ç¯å¢ç¹å® |
anotherme-search-env-configmap.yaml |
Search é ç½® | å¯è½éè¦éæ©æ§åæ¥ |
simplex-cron-env-configmap.yaml |
Cron é ç½® | é常æ¯ç¯å¢ç¹å®ç |
simplex-router-cm0-configmap.yaml |
Router é ç½® | é常æ¯ç¯å¢ç¹å®ç |
frontend-env.yaml |
å端ç¯å¢åé | é常æ¯ç¯å¢ç¹å®ç |
ingress.yaml |
Ingress è§å | æ°¸ä¸åæ¥ï¼ååä¸å |
坿¬æ°
CI é常è¿è¡æ´å°ç坿¬ãStaging ä½¿ç¨ base é»è®¤å¼ææ´é«å¼ãè¿æ¯ææçï¼ä¸åºåæ¥ã
èç¹æ± åé
- CI:
karpenter.sh/nodepool: ci/singleton-ci - Staging:
karpenter.sh/nodepool: staging/singleton-staging
è¿äºæ¯ç¯å¢ç¹å®çï¼ä¸åºåæ¥ã
åå¨ç±»
两个ç¯å¢ä½¿ç¨ç¸ä¼¼ç模å¼ï¼ä½å¯è½æä¸åçåå¨ç±»åç§°ãé常ä¸éè¦åæ¥ã
é«å¯ç¨è®¾ç½®
Staging å¯è½æé¢å¤ç HA é ç½®ï¼
- è·¨ AZ åå¸ç
topologySpreadConstraints - ä¼é
å
³éç
terminationGracePeriodSeconds: 60
è¿äºæ¯ staging ç¹å®çä¼åï¼ä¸åºåæ¥å° CIã
æå¨åæ¥æ¨¡å¼
对äºèªå¨åæ¥èæ¬æªå¤ççé ç½®ï¼
忥ç¹å® ConfigMap Patch
# 1. ä½¿ç¨æ°ç compare_configs.py æ¥ç详ç»å·®å¼
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py \
--file anotherme-agent-env-configmap.yaml --detailed
# 2. ä»ç»å®¡æ¥å·®å¼
# è¯å«åªäºé®æ¯ï¼
# - ç¯å¢ç¹å®çï¼REDIS_URL, MQ_HOST, DATABASE_URLï¼
# - åè½æ å¿æä¸å¡é»è¾ï¼LLM_PRESET, åè½å¼å
³ï¼
# - API keysï¼ç¯å¢é´å¯è½ä¸åï¼
# 3. 妿åéï¼æå¨åæ¥
# é项 Aï¼å¤å¶æ´ä¸ªæä»¶ï¼å¾å°åéï¼
cp kubernetes/overlays/aws-ci/patches/anotherme-agent-env-configmap.yaml \
kubernetes/overlays/aws-staging/patches/anotherme-agent-env-configmap.yaml
# é项 Bï¼æå¨ç¼è¾ç¹å®é®ï¼æ¨èï¼
vim kubernetes/overlays/aws-staging/patches/anotherme-agent-env-configmap.yaml
# åªæ´æ°éè¦åæ¥çé®ï¼ä¾å¦ LLM_PRESETï¼
# ä¿æç¯å¢ç¹å®çå¼ä¸å
# 4. éªè¯åæ´
git diff kubernetes/overlays/aws-staging/patches/anotherme-agent-env-configmap.yaml
忥æ°èµæº
妿 CI æ staging éè¦çæ°èµæºï¼PVãPVCãConfigMaps çï¼ï¼
# 1. æ£æ¥æ°èµæº
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/compare_configs.py
# æ¥æ¾ "NEW IN CI" é¨å
# 2. å°èµæºæä»¶å¤å¶å° aws-staging
cp kubernetes/overlays/aws-ci/patches/new-config.yaml \
kubernetes/overlays/aws-staging/patches/
# 3. æ·»å å° aws-staging kustomization.yaml patches é¨å
vim kubernetes/overlays/aws-staging/kustomization.yaml
# 4. è°æ´ç¯å¢ç¹å®çå¼
vim kubernetes/overlays/aws-staging/patches/new-config.yaml
# æ´æ°å½åç©ºé´æ ç¾ãURLãAPI 端ç¹ç
# 5. éªè¯æ¸
å
kubectl kustomize kubernetes/overlays/aws-staging > /tmp/staging-check.yaml
# å®¡æ¥ /tmp/staging-check.yaml çæ£ç¡®æ§
忥åéªè¯
æ£æ¥ ArgoCD ç¶æï¼åªè¯»ï¼å®å ¨ï¼
# æ¥çåºç¨ç¶æåå¾
忥忴
argocd app get simplex-aws-staging
argocd app diff simplex-aws-staging
æå¨åæ¥ï¼ç¨æ·å¿ é¡»æç¡®è¯·æ±ï¼
# â ï¸ ä»
å¨ç¨æ·æç¡®è¦æ±æ¶æ§è¡
argocd app sync simplex-aws-staging
æ£æ¥é¨ç½²ççæ¬
# Staging namespace
k2 get pods -n staging -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
# CI namespace
k1 get pods -n ci -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'
éªè¯æ¸ å
kubectl kustomize kubernetes/overlays/aws-staging > /tmp/staging-manifests.yaml
kubectl kustomize kubernetes/overlays/aws-ci > /tmp/ci-manifests.yaml
diff /tmp/ci-manifests.yaml /tmp/staging-manifests.yaml
æ éæé¤
èæ¬æªæ¾å°ä»åº
ç¡®ä¿ä½ å¨ simplex-gitops ç®å½ä¸ææç¡®è®¾ç½®è·¯å¾ï¼
cd /path/to/simplex-gitops
python3 ~/.cursor/skills/sync-ci-to-staging/scripts/sync_images.py --diff
CI 䏿ªæ¾å°éå
æå¡å¯è½ä½¿ç¨ä¸åçéååç§°æ ¼å¼ï¼Aliyun vs ECRï¼ãæ£æ¥ kustomization æä»¶ä¸çä¸¤ç§æ ¼å¼ã
ArgoCD æªåæ¥
# æ¥çåºç¨ç¶æï¼åªè¯»ï¼
argocd app get simplex-aws-staging --show-operation
# å·æ°åºç¨æ£æµææ°åæ´ï¼åªè¯»ï¼å®å
¨ï¼
argocd app refresh simplex-aws-staging
# â ï¸ æå¨åæ¥ - ä»
å¨ç¨æ·æç¡®è¦æ±æ¶æ§è¡
argocd app sync simplex-aws-staging
æå¡ç±»å«åè
| ç±»å« | æå¡ |
|---|---|
| AI æ ¸å¿ | anotherme-agent, anotherme-api, anotherme-search, anotherme-worker |
| å端 | front, front-homepage |
| å端 | simplex-cron, simplex-gateway-api, simplex-gateway-worker |
| æ°æ® | data-search-api, crawler |
| åºç¡è®¾æ½ | litellm, node-server, simplex-router, simplex-router-backend, simplex-router-fronted |