CI/CD 与容器部署说明
发布边界
根仓由同一次 Buildx 多架构构建同时发布到 Docker Hub 和阿里云 ACR 个人版。两个仓库使用相同的镜像标签与内容摘要——这依赖 .github/actions/publish-image 用单次构建携带双仓标签,而不是分别构建;代价是发布镜像不生成 OCI provenance/SBOM 附件,因为 ACR 个人版不接受该类附件。Docker Hub 作为默认公共仓库,ACR 作为中国大陆网络环境下的拉取副本。镜像仓库为:
- Docker Hub:
docker.io/llmxpm/web-presentation、docker.io/llmxpm/web-runtime-vue、docker.io/llmxpm/web-presentation-renderer(Renderer 尚未发布,见下) - 阿里云 ACR:
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation、${ACR_REGISTRY}/${ACR_NAMESPACE}/web-runtime-vue、${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation-renderer(Renderer 尚未发布)
关于 Renderer / 自构建 Runtime 镜像的现状(必须如实理解):web-presentation-renderer 与仓库自构建 web-runtime-vue 的推送 job 尚未执行过,两个 registry 中当前不可拉取对应镜像;它们的首次推送预计发生在下一次 Release。在首次真实 Release 验证之前,不要按「已存在可拉取的 renderer 镜像」编写部署步骤或回滚组合。
runtime/ 已 vendored 进本仓,Runtime 独立镜像由本仓 Release 使用 runtime/Dockerfile 构建推送,不再依赖外部 web-runtime-vue 子模块 SHA 镜像。本仓镜像变体:
常规平台镜像:由
deploy/docker/Dockerfile.platform构建,包含 Backend 代码、Editor 静态资源、Nginx 配置和 Backend 运行所需的 Runtime Kit manifest。SQLite 轻量单容器镜像:由
deploy/docker/Dockerfile.lite构建,额外内置 Runtime Vite server 运行依赖,面向 SQLite + memory runtime 轻量部署。该变体直接打包当前仓库原生runtime/源码。已发布的sqlite-lite(旧架构)自带浏览器,截图在容器内完成;当前 HEAD 开发中的 lite 渲染能力形态与是否再内置浏览器,以镜像专项计划为准,发布前不要假设 HEAD 与已发布镜像同构。独立 Runtime 运行时镜像:由
runtime/Dockerfile构建(构建上下文为仓库根,以共享 pnpm workspace 锁文件),提供独立 Vite server 以承载生产编排中的预览、诊断与构建接口。自构建 Runtime 镜像尚未随 Release 推送过,待下一次 Release 首次发布。独立 Renderer 镜像:由
renderer/Dockerfile在根构建上下文中构建,包含wp_renderer与 Python Playwright Chromium。尚未发布;待下一次 Release 首次推送。
GitHub Actions
质量门禁入口
- 三条流水线共用
.github/workflows/reusable-quality.yml,测试命令统一走根目录package.json的test:*脚本;workflow 级permissions收敛为contents: read,每个 job 都带timeout-minutes。 platform-test.yml的首个 jobtest-scope执行.github/scripts/resolve-test-scope.sh,由脚本按事件与git diff产出full_tests、run_runtime、e2e_scope、image_matrix四个 output。YAML 内不维护第二份路径清单,也不再使用dorny/paths-filter:该 action 在 push 与 schedule 事件没有 diff base 时恒为真,会让每次 main push 都白跑一遍 Runtime 门禁。- 分级规则:
pull_request与mainpush 以变更文件为输入。只改docs/、README/AGENTS/DESIGN/LICENSE.md、.gitignore、.gitattributes时只跑快速门禁;其它任何改动进入全量门禁(Backend integration、Runtime 门禁、E2E smoke)。- 镜像 smoke 只重建受影响变体:平台镜像构建输入(
deploy/、backend/、editor/、scripts/、Dockerfile*、根 workspace 锁文件、runtime/package.json、Runtime Kit manifest)命中则重建平台 + lite;runtime/命中重建 Runtime 镜像与 lite;renderer/、packages/、uv.lock命中重建 Renderer 镜像。全部 leg 定义在脚本的FULL_MATRIX,由tests/contracts/repository/deployment.test.ts校验四类交付 Dockerfile 都在其中。 - 解析不到 diff base(浅克隆、force push、
github.event.before不可达)时脚本保守升级为全量,绝不静默降级。 schedule(每周一)与workflow_dispatch且full_tests=true是全量入口:始终跑完整门禁,E2E 使用test:e2e:all,镜像 smoke 覆盖四个变体的多架构构建。cli-contract依赖同级web-presentation-cli仓库,仅在定时与手动触发。
- 并发分组:
schedule使用独立 group 且cancel-in-progress=false,避免定时全量被随后的 main push 中途杀掉;其余事件按 PR 号或 ref 分组并自动取消。 - E2E 在 CI 下允许一次重试(
tests/config/playwright.config.ts的retries: process.env.CI ? 1 : 0):单条用例的定位抖动应在 job 内自愈,不能放大成整套门禁重跑;本地保持0以暴露真实不稳定。
Release 流水线
platform-release.yml不再重复执行整套质量门禁。verify-main-gate通过gh api repos/.../actions/runs?head_sha=<发布提交>检查该提交是否已有通过的platform-test运行;没有则拒绝发布。因此合入 main 的那次 push 必须跑绿,且 release tag 指向的提交要与该运行同 SHA。确需紧急补发时,需通过 GitHub Actions 页面使用workflow_dispatch手动触发并勾选allow_unverified(GitHub Release UI 发布无法传入跳过参数),此时写入::warning::留痕。release-meta在构建前一次性校验vars.DOCKER_USERNAME、secrets.DOCKER_PASSWORD、vars.ACR_REGISTRY、vars.ACR_NAMESPACE、vars.ACR_USERNAME、secrets.ACR_PASSWORD是否缺失(只做非空判断,不输出值),避免缺配置直到 docker login 阶段才报出难以定位的错误。- 推送由
.github/actions/publish-imagecomposite action 完成:先复用.github/actions/check-image验证镜像实际启动,再用一次docker/build-push-action多架构构建同时携带 Docker Hub 与 ACR 两组标签。代价是关闭 OCI provenance/SBOM 附件(ACR 个人版不接受该附件),换取双仓镜像内容与摘要一致。 - Docker Hub 配置:
vars.DOCKER_USERNAMEsecrets.DOCKER_PASSWORD
- 阿里云 ACR 配置:
vars.ACR_REGISTRY:个人版实例访问域名,例如crpi-xxxx.cn-hangzhou.personal.cr.aliyuncs.com,不要填写https://。vars.ACR_NAMESPACE:阿里云 ACR 命名空间。vars.ACR_USERNAME:ACR 访问凭证中的登录名。secrets.ACR_PASSWORD:ACR 访问凭证密码,不是阿里云控制台登录密码。
稳定 Release 的目标推送清单如下。其中 web-presentation-renderer 与 web-runtime-vue(自构建)两类镜像尚未发布;下列 renderer / runtime 行描述的是「待下一次 Release 首次推送」的计划,不是当前已可拉取的标签:
docker.io/llmxpm/web-presentation-renderer:<release_tag>
docker.io/llmxpm/web-presentation-renderer:latest
docker.io/llmxpm/web-presentation-renderer:sha-<commit_sha>
docker.io/llmxpm/web-runtime-vue:<release_tag>
docker.io/llmxpm/web-runtime-vue:latest
docker.io/llmxpm/web-runtime-vue:sha-<commit_sha>
docker.io/llmxpm/web-presentation:<release_tag>
docker.io/llmxpm/web-presentation:latest
docker.io/llmxpm/web-presentation:sqlite-lite-<release_tag>
docker.io/llmxpm/web-presentation:sqlite-lite
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation-renderer:<release_tag>
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation-renderer:latest
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation-renderer:sha-<commit_sha>
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-runtime-vue:<release_tag>
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-runtime-vue:latest
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-runtime-vue:sha-<commit_sha>
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation:<release_tag>
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation:latest
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation:sqlite-lite-<release_tag>
${ACR_REGISTRY}/${ACR_NAMESPACE}/web-presentation:sqlite-litePre-release 只推送固定版本标签,不移动 latest 与 sqlite-lite。
生产 Compose
部署模板、环境变量、启动命令和进程形态详见 生产部署指南 和 Compose 部署说明。
关键访问关系
- 浏览器访问简化版的
platform:80,或 production env 版的gateway:80。 - 平台 Nginx 代理
/api、/public、/build-artifacts、/preview到backend:8000;旧/media及其子路径直接返回 404。 - 平台 Nginx 代理
/runtime/到runtime:7373,并保留/runtime/前缀。 - Backend 通过
RUNTIME_BASE_URL=http://runtime:7373访问 Runtime 内网服务。 - Runtime 通过
RUNTIME_BACKEND_API_BASE_URL=http://backend:8000回源 Backend 内部接口。 - Runtime 通过
RUNTIME_PREVIEW_JWKS_URL=http://backend:8000/.well-known/jwks.json校验 Backend 签发的预览与构建令牌。