with one click
umac-ai-deploy-prod
UMAC AI 生產部署 SOP — backend + frontend + CDK + ECS 全流程
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
UMAC AI 生產部署 SOP — backend + frontend + CDK + ECS 全流程
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Dev-agent / checker-agent collaboration loop driven by downstream project docs/STATE.md. Dev agent implements and records work items; an independent checker agent verifies each item with real lint/typecheck/test/build evidence and writes findings back; loop continues until all items are VERIFIED or escalation limits are hit.
Synchronizes review feedback, QA findings, user corrections, and code-review suggestions into durable project docs before Build, merge, or ship.
Intake workflow for existing projects before continuing development. Analyze current source state, derive a truthful docs baseline, identify QA/regression gaps, and create a safe continuation plan.
防止修復過的 bug 重新出現(regression)。 規則:每個修過的 bug 必須留下「regression test」+「root cause note」+「為何會發生」分析, 確保日後 refactor / 改需求時唔會重新踩坑。 David 在 2026-06-06 kanban task 明確指出「舊的 bug 又出現」嘅困擾。
定時壓縮長時間任務的 context,避免 token 爆炸。寫入 context-summary.md 保留決策和當前狀態,丢棄細節。
Task Orchestration Subagent — Coordinates all subagents, manages task board, handles parallel/sequential execution, tracks dependencies and failures. The conductor of the development orchestra.
| name | umac-ai-deploy-prod |
| description | UMAC AI 生產部署 SOP — backend + frontend + CDK + ECS 全流程 |
⚠️ DEPRECATED 2026-06-19 —
umac-ai-clusterECS cluster、SES verified identities、Route53 hosted zone、S3 bucket 全部不存在(0 個)。DNS 解析去 Hetzner + hosting reseller,項目已搬離 AWS。Recipe 過時,等 David 確認 hosting 位置 + supply access 再 update。
UMAC AI 項目(澳門大學 AI 大賽活動網站)的生產環境部署 SOP。
ap-east-1us-east-1https://api.board-ai.sitehttps://board-ai.siteumac-ai-clusterumac-ai-backend, umac-ai-frontendcd ~/projects/umac_ai
git add -A && git commit -m "description"
git push origin main
# 先確認有哪些 pending migrations
aws ecs run-task \
--cluster umac-ai-cluster \
--task-definition UMacAiEcsStackBackendTaskDefEF56D88D \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-01255018d4a3a1b1f,subnet-0c5ce99b7d83c693b],securityGroups=[sg-01d213a5c6e416f40]}" \
--overrides '{"containerOverrides":[{"name":"umac-ai-backend","command":["sh","-c","cd /app && ./node_modules/.bin/prisma migrate deploy --schema prisma/schema.prisma"],"environment":[{"name":"DATABASE_URL","value":"postgresql://umacai:PASSWORD@umacaidatabasestack-ummaaidbinstancecd68fce1-pxp9c9hn2dv6.cd8ge4mwq7jq.ap-east-1.rds.amazonaws.com:5432/umac_ai"}]}]}' \
--region ap-east-1
# 等待約 45 秒後 describe-tasks 確認 ExitCode: 0
注意:npx prisma 在 Fargate 內會失敗(ExitCode: 127),必須用 ./node_modules/.bin/prisma 並先 cd /app。
cd ~/projects/umac_ai/backend
sudo docker build --no-cache -t umac-ai-backend .
sudo docker tag umac-ai-backend:latest 631807311787.dkr.ecr.ap-east-1.amazonaws.com/umac-ai-backend:latest
aws ecr get-login-password --region ap-east-1 | sudo docker login --username AWS --password-stdin 631807311787.dkr.ecr.ap-east-1.amazonaws.com
sudo docker push 631807311787.dkr.ecr.ap-east-1.amazonaws.com/umac-ai-backend:latest
cd ~/projects/umac_ai/frontend
# .env.production 已有 VITE_API_BASE_URL=https://api.board-ai.site/api
sudo docker build -t umac-ai-frontend .
sudo docker tag umac-ai-frontend:latest 631807311787.dkr.ecr.ap-east-1.amazonaws.com/umac-ai-frontend:latest
sudo docker push 631807311787.dkr.ecr.ap-east-1.amazonaws.com/umac-ai-frontend:latest
cd ~/projects/umac_ai/infra
npx cdk deploy UMacAiEcsStack --region ap-east-1 --require-approval never
# CDK deploy 會 timeout(300s),但 CloudFormation 會繼續在後台執行
# 確認:aws cloudformation describe-stacks --stack-name UMacAiEcsStack --region ap-east-1
cd ~/projects/umac_ai
git add -A && git commit -m "description" && git push origin main
# CodeBuild 會自動:
# 1. Build backend Docker image + push to ECR
# 2. Build frontend + sync to S3 + CloudFront invalidation
# 3. 如果 infra/ 有變更 → CDK deploy
# 4. Prisma migrate + seed
# 5. ECS service update(拉新 image)
手動觸發 CodeBuild(如需立即部署):
aws codebuild start-build --project-name umac-ai-deploy --region ap-east-1 --query 'build.id' --output text
# 查狀態:
aws codebuild batch-get-builds --ids umac-ai-deploy:<build-id> --region ap-east-1 --query 'builds[0].[status,currentPhase]' --output text
CodeBuild 包含完整的檢測邏輯:
git diff 檢測哪些模組有變更# Backend
aws ecs update-service --cluster umac-ai-cluster --service umac-ai-backend --force-new-deployment --region ap-east-1
# Frontend
aws ecs update-service --cluster umac-ai-cluster --service umac-ai-frontend --force-new-deployment --region ap-east-1
# 前端靜態資源需同步到 S3,ECS frontend 容器更新的只是 container 本身
cd ~/projects/umac_ai/frontend
npm run build
aws s3 sync dist/ s3://umac-ai-frontend-631807311787-ap-east-1/ --region ap-east-1
aws cloudfront create-invalidation --distribution-id E2KORZ2WAC4CZS --paths "/*"
前端有 UI 改動時,否則用戶看到的是 CloudFront 緩存的舊版。
# Basic health
curl -s https://api.board-ai.site/health
# 測試登入
curl -s -X POST "https://api.board-ai.site/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"admin@umac.ai","password":"AdminPass123"}'
# 測試 presign 上傳(需要新 token)
LOGIN_RESP=$(curl -s -X POST "https://api.board-ai.site/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"admin@umac.ai","password":"AdminPass123"}')
TOKEN=$(echo $LOGIN_RESP | python3 -c "import sys,json; print(json.load(sys.stdin).get('token',''))")
curl -s -X POST "https://api.board-ai.site/api/upload/presign" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"filename":"test.pdf","contentType":"application/pdf","size":1234}'
# CloudFront 測試(等同瀏覽器訪問)
curl -s -I "https://d25s1d60o4mvcq.cloudfront.net/api/courses"
CDK 只負責更新 AWS infrastructure(建立 S3 bucket、更新 task definition env、加 IAM policy)。CDK 不會 build 或 push Docker image。
每次代碼變更後,必須手動:
如果忘記這步,ECS 會繼續跑舊 image。
cd ~/projects/umac_ai/backend
bun --env-file=.env src/index.ts
.env 必須包含:
SES_REGION=us-east-1
SES_FROM_EMAIL=noreply@board-ai.site
JWT_SECRET=...
DATABASE_URL=...
email From 為 noreply@board-ai.site,envelope sender 預設是 010001...@amazonses.com,導致 DMARC FAIL。
解決:在 Route53 加 DKIM CNAME 記錄 + DMARC TXT 記錄。
umac-ai-cluster ECS cluster、SES verified identities、Route53 hosted zone、S3 bucket 全部不存在(0 個)。api.board-ai.site DNS 解析去 Hetzner 95.41.26.30 + hosting reseller (16.163.242.148 AMAZO-4 block),項目已搬離 AWS。Recipe 過時 — AWS infra 0/6 services 全部 missing,等 David 確認 hosting 位置 + supply access 再 update。
情境: 用戶投訴功能唔 work,你以為係 code bug,先查 AWS 卻發現成個 project 已搬走 — code bug 唔存在, infra drift 嘅 root cause 喺別處。
6 個 5-second probes(全部唔需要 project source code access,只需要 AWS credentials 同 dig):
# 1. DNS 指去邊
dig api.<project>.site +short # 預期 AWS 內: ELB/CloudFront IP
# 實際 Hetzner/DO/Linode = infra 已搬走
# 2. ECS cluster 仲在唔在
aws ecs list-clusters --region ap-east-1 # 預期有 project-cluster, 0 = gone
# 3. SES verified identities
aws sesv2 list-email-identities --region us-east-1
# 預期有 project-domain.com 或 no-reply@...
# 0 = SES 沙盒空, 邊個 email 都 send 唔出
# 4. SES Production Access
aws sesv2 get-account --region us-east-1 --query 'ProductionAccessEnabled,SendQuota' --output text
# false + Max24HourSend: 200 = 沙盒 mode
# 5. Route53 hosted zones
aws route53 list-hosted-zones --query 'HostedZones[?Name==`<project>.site.`].Id' --output text
# 0 = DNS 都唔喺 AWS
# 6. S3 buckets
aws s3api list-buckets --query 'Buckets[?contains(Name, `<project>`)].Name' --output text
# 0 = frontend hosting 都唔喺 AWS
Decision matrix:
| 6 probes 結果 | 結論 | Action |
|---|---|---|
| 全部預期值 | infra 仲喺 AWS | 查 code bug / env 變更 / recent deploy |
| 1-2 missing | partial drift | 逐個 probe, fix 缺失嗰個 (e.g. verify SES identity 走咗就 re-verify) |
| 3+ missing | infra 已搬走 | STOP。搵實際 hosting (SSH / control panel / GitHub repo)。悶頭做 AWS recipe 係 waste token |
Lesson codification: 任何「用戶投訴功能壞咗」嘅 task,第一步唔係睇 code,係跑呢 6 probes 10 秒。If 3+ missing → project 唔再你以為嘅 hosting,investigation 路徑完全唔同。
desired=2 但 running=0?先查 ECS stopped tasks + CloudWatch logs。曾發生 root cause:backend Dockerfile 用 bun build --target=node --format=cjs,但 runtime 是 CMD ["bun", "dist/index.js"],導致 Elysia/Bun app 啟動後 crash:
TypeError: Bun.serve() needs either routes object or fetch handler
修復:Dockerfile 必須用 Bun target:
RUN bun build src/index.ts --target=bun --outfile=dist/index.js
CMD ["bun", "dist/index.js"]
驗證:
cd ~/projects/umac_ai/backend
bun build src/index.ts --target=bun --outfile=dist/index.js
PORT=3999 timeout 5s bun dist/index.js
# 看到 startup log 並保持運行直到 timeout,不能出現 Bun.serve TypeError
修好後 rebuild/push backend image + force ECS deploy,確認:
aws ecs describe-services --cluster umac-ai-cluster --services umac-ai-backend --region ap-east-1 \
--query 'services[0].{desired:desiredCount,running:runningCount,pending:pendingCount,deployments:deployments[*].rolloutState}'
curl -fsS https://api.board-ai.site/health
先分辨是 API 掛了還是密碼錯:
curl -fsS https://api.board-ai.site/health — 如果 503,先修 backend。admin@umac.ai / AdminPass123;admin123 會回 Invalid email or password。根因:CloudFront origin 使用 ALB DNS name(如 UMacAi-UmmaA-...elb.amazonaws.com),但 ALB ACM 證書是 api.board-ai.site,TLS CN 不匹配導致 CloudFront 無法完成 TLS 握手。
修復(CDK 或 AWS CLI):
api.board-ai.sitehttps-only 改為 match-viewerAWS CLI 直接修復(立即生效):
# 取得目前 config
aws cloudfront get-distribution --id E2KORZ2WAC4CZS --region ap-east-1 > /tmp/cf-config.json
# 修改 Origin items[0].DomainName = "api.board-ai.site"
# 修改 Origin items[0].CustomOriginConfig.OriginProtocolPolicy = "match-viewer"
aws cloudfront update-distribution --id E2KORZ2WAC4CZS --distribution-config file:///tmp/cf-config.json
CDK 修復(同步到代碼):
// infra/lib/frontend.ts
const albDomain = 'api.board-ai.site'; // 不要用 ALB DNS name
// origin: { domainName: albDomain, originProtocolPolicy: 'match-viewer' }
測試 API 時一定要用「立即取得的新 token」,不要重複使用舊 token。
# 正確方式:登入後立即用同一個 shell session 測試
LOGIN_RESP=$(curl -s -X POST "https://api.board-ai.site/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"admin@umac.ai","password":"AdminPass123"}')
TOKEN=$(echo $LOGIN_RESP | python3 -c "import sys,json; print(json.load(sys.stdin).get('token',''))")
curl -s -X POST "https://api.board-ai.site/api/upload/presign" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"filename":"test.pdf","contentType":"application/pdf","size":1234}'
檢查是否忘記 force new deployment。CDK deploy 只更新 task definition,現有 ECS tasks 不會自動重啟。
檢查 DKIM 是否 Pending → 需要在 Route53 加 DKIM CNAME 記錄。
正常,CloudFormation 在後台繼續執行。等 2-3 分鐘後確認 UPDATE_COMPLETE。
~/projects/umac_ai/backend/~/projects/umac_ai/frontend/~/projects/umac_ai/infra/631807311787.dkr.ecr.ap-east-1.amazonaws.com/umac-ai-backend 和 .../umac-ai-frontend