Skip to content

Deploy và cấu hình ​

Luật gốc ​

  • Cloudflare tự build từ GitHub. Mỗi app được nối thẳng vào repo conan-web bằng ứng dụng GitHub của Cloudflare: Workers Builds cho Worker, Pages Git cho Pages. Push lên main là Cloudflare build và deploy, khoá do Cloudflare tự cấp (quyết định 16.10.2026).
  • GitHub Actions không deploy gì cả, và không có CLOUDFLARE_API_TOKEN trong GitHub. Lý do: chủ repo không cầm khoá, và không có khoá rộng quyền nào nằm trong GitHub. ci.yml chỉ KIỂM (gác, build, test).
  • Không bao giờ deploy từ máy. Không wrangler deploy, không wrangler pages deploy, không áp migration D1 bằng tay. Phiên Claude Code chạy trên cloud cũng là "máy" theo nghĩa này.
  • Chỉ merge khi CI xanh.

Cấu hình build theo từng app ​

Bảng này chép nguyên từ CLAUDE.md của repo. Hai bản phải giống hệt nhau; đổi một bên thì đổi bên kia trong cùng PR.

AppLoạiThư mục gốcLệnh buildDeployWatch paths
api-cmsWorkers Builds, Worker api-cms-conan-schoolapi-cms.conan.schoolnpm run check && npm testnpx wrangler d1 migrations apply conan-cms --remote && npx wrangler deployapi-cms.conan.school/*, packages/cms-contract/*
cmsPages Git, cms-conan-schoolcms.conan.schoolnpm test && npm run buildđầu ra distcms.conan.school/*, packages/cms-contract/*, packages/design-system/*
cms-docsPages Git, cms-docs-conan-schoolcms-docs.conan.schoolnpm run buildđầu ra .vitepress/distcms-docs.conan.school/*
wwwPages Git, project mới tạo vào ngày cắtwww.conan.schoolnpm run typecheck && npm run buildđầu ra build/clientwww.conan.school/*, packages/* (trừ cms-contract)
cầu nối wwwWorkers Builds, Worker conan-www-stale-asset-bridge (đã có)www.conan.school/edge-hotfix(không)npx wrangler deploywww.conan.school/edge-hotfix/*
  • Lệnh build chạy test TRƯỚC. Một commit đỏ trên main không lên production, kể cả khi ci.yml chưa chạy xong. CI và bước build của Cloudflare chạy song song, không chờ nhau.
  • Cấu hình build (lệnh, thư mục gốc, watch paths) nằm ở dashboard Cloudflare, không nằm trong repo. Đổi ở dashboard mà không sửa bảng trên là bảng nói sai mà không ai biết.
  • www chưa deploy từ repo này. Tới ngày cắt nó vẫn deploy từ conanplatform. Xem Kế hoạch chuyển đổi.

Watch paths ​

cms và api-cms import gói hợp đồng dùng chung packages/cms-contract/ (ngoài thư mục gốc của app), và các site Tailwind đọc packages/design-system/. Watch paths của mỗi project phải gồm cả thư mục app lẫn các gói nó dùng, nếu không một PR chỉ sửa hợp đồng sẽ không dựng lại app nào, và production chạy hai nửa của một hợp đồng đã lệch nhau.

AppWatch paths cần có
api-cmsapi-cms.conan.school/*, packages/cms-contract/*
cmscms.conan.school/*, packages/cms-contract/*, packages/design-system/*
cms-docscms-docs.conan.school/*
wwwwww.conan.school/*, packages/* (trừ cms-contract)
cầu nối wwwwww.conan.school/edge-hotfix/*

ci.yml chỉ kiểm ​

.github/workflows/ci.yml chạy trên mọi PR và mọi push lên main, gồm hai job:

  • guards: npm run check:guards ở gốc repo. Xem Gác.
  • build: ma trận bốn app, mỗi app npm ci --legacy-peer-deps rồi chạy đúng lệnh build như ở Cloudflare (api-cms thêm npm run build, tức wrangler deploy --dry-run).

npm ci hỏng phải làm CI đỏ, không có đường rơi: CI xanh với phụ thuộc không ghim là một bài học cũ của conanplatform.

Migration D1 của conan-cms ​

  • File migration nằm ở api-cms.conan.school/migrations/, đặt tên 000N_*.sql.
  • database_id thật của D1 conan-cms nằm trong api-cms.conan.school/wrangler.toml. Id D1 không phải bí mật: không có khoá Cloudflare thì id không làm được gì.
  • Lệnh deploy của Workers Builds áp migration bằng wrangler d1 migrations apply conan-cms --remote, rồi mới wrangler deploy, nối bằng &&. Áp migration hỏng thì dừng, Worker cũ vẫn chạy với lược đồ cũ. Worker mới không bao giờ chạy trước lược đồ của nó.
  • conan-cms là DB mới, không có lịch sử lệch, nên dùng sổ d1_migrations có sẵn của wrangler. Khác với D1 của conanplatform, nơi phải áp từng file một và có sổ riêng.
  • Thêm migration = thêm file mới. Không bao giờ sửa file đã áp.
  • Thử ở máy: npm run migrate:local trong api-cms.conan.school/ (D1 cục bộ trong .wrangler/).

Bài học từ conanplatform: khi bước migration đỏ, API đứng yên ở bản cũ trong khi frontend vẫn ship, và nhìn từ ngoài không có gì đỏ. Sau mỗi PR có migration, mở lượt build của Worker api-cms-conan-school ở dashboard (Workers, Deployments) và xem bước deploy có xanh không.

Cài Cloudflare Access ​

Khi chưa làm bước này, mọi route /admin/* trả 503 access_not_configured, và người soạn thấy màn hình "Cloudflare Access chưa được cấu hình". Đó là đúng thiết kế.

  1. Vào Cloudflare Zero Trust, mục Access, Applications. Tạo một ứng dụng Self-hosted.

  2. Domain: cms.conan.school. Không đặt api-cms.conan.school sau Access: nhánh /public/* phải công khai cho www, còn nhánh /admin/* đã tự kiểm JWT.

  3. Thêm policy Allow, chọn danh sách email người soạn (hoặc một nhóm).

  4. Mở ứng dụng vừa tạo, chép Application Audience (AUD) Tag.

  5. Lấy team domain ở Settings của Zero Trust, dạng <team>.cloudflareaccess.com.

  6. Điền hai giá trị vào [vars] của api-cms.conan.school/wrangler.toml:

    toml
    [vars]
    CF_ACCESS_TEAM_DOMAIN = "<team>.cloudflareaccess.com"
    CF_ACCESS_AUD = "<AUD tag>"

    Không ghi https:// trước team domain. Nhiều AUD thì cách nhau bằng dấu phẩy. Hai giá trị này không phải bí mật, nên nằm trong wrangler.toml là được.

  7. Mở PR, chờ CI xanh, merge. Workers Builds dựng và deploy lại Worker với biến mới.

  8. Đăng nhập thử ở cms.conan.school. Gọi /api/admin/me phải trả email của bạn.

Thêm hay bớt người soạn chỉ cần sửa policy ở bước 3, không cần deploy lại.

Tên miền ​

Tên miềnGắn vàoCách gắn
api-cms.conan.schoolWorker api-cms-conan-schoolTự động: routes với custom_domain = true trong wrangler.toml, gắn mỗi lần deploy
cms.conan.schoolPages cms-conan-schoolTay, một lần, ở dashboard Pages, Custom domains
cms-docs.conan.schoolPages cms-docs-conan-schoolTay, một lần, như trên
www.conan.schoolWorker cầu nối conan-www-stale-asset-bridge, trỏ tới một Pages projectĐã có. Ngày cắt chỉ đổi project mà Worker trỏ tới, không đổi tên miền

Sau khi gắn, so trang ở tên miền với trang ở <project>.pages.dev: hai bản phải giống nhau. Lệch là tên miền đang trỏ vào một project khác.

Kiểm sau lượt deploy đầu ​

  • Mỗi project ở dashboard có lượt build xanh cho commit vừa merge, và lượt đó là production (nhánh main), không phải preview.
  • curl https://api-cms.conan.school/health trả {"ok":true}.
  • ci.yml cài phụ thuộc bằng npm ci --legacy-peer-deps, còn Cloudflare tự cài bằng lệnh của nó, không có cờ đó. Nếu bước cài ở Cloudflare đỏ vì xung đột peer dependency thì CI xanh không nói lên gì về production: sửa ngay chỗ xung đột, đừng để hai môi trường cài khác nhau.

Tài liệu nội bộ của Conan CMS.