fix(ci): pull API base image from Huawei SWR instead of DaoCloud
Staging publish failed resolving python:3.12-slim through m.daocloud.io; the web image already uses the reachable SWR docker.io/library path. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
FROM m.daocloud.io/docker.io/library/python:3.12-slim
|
||||
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/python:3.12-slim
|
||||
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PIP_NO_CACHE_DIR=1 \
|
||||
|
||||
@@ -5003,6 +5003,22 @@
|
||||
- 复发自:BUG-307(当时把分盘句和宫位表从正文挪到界面后,入口合同锁死了那句提示词)
|
||||
- 修复版本:379f0e6f
|
||||
|
||||
## BUG-333 | staging 发布 API 镜像时 DaoCloud TLS 握手超时
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-08-20
|
||||
- 最近更新:2026-08-20
|
||||
- 影响面:Gitea `backend-quality-gate` 的 `publish` job、`deploy/railway-api.Dockerfile`、`xiaoxin` runner 拉官方基础镜像
|
||||
- 用户现象:`validate` 通过后 `Build and publish exact-SHA ACR images` 在 API Dockerfile 第一行失败:`Head "https://m.daocloud.io/v2/docker.io/library/python/manifests/3.12-slim"` TLS handshake timeout。
|
||||
- 触发条件:向 `staging` 推送后 publish 构建 `deploy/railway-api.Dockerfile`。
|
||||
- 根因:API 基础镜像仍走 DaoCloud 代理。同一 runner 已验证可达华为 SWR / ECR / ACR;Web 镜像早已改用 `swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/node:22-alpine`,API 未跟上。
|
||||
- 修复:API `FROM` 改为与 Web 相同的华为 SWR `docker.io/library` 路径,指向 `python:3.12-slim`。不改运行时端口、pip/apt 镜像或 ACR 目标仓库。
|
||||
- 验证:`tests/test_railway_deployment.py`、`frontend/tests/staging-backend-workflows.test.ts`。远端 publish 由本提交后的 Gitea quality gate 验收。
|
||||
- 防复发:API/Web 官方基础镜像必须走华为 SWR `ddn-k8s/docker.io/library`,合同禁止 `daocloud`。不要为了重试再加一套 `for attempt in 1 2 3`,workflow 里该循环次数已被合同锁死为 5。
|
||||
- 相关记录:BUG-149、BUG-150、BUG-332
|
||||
- 复发自:无
|
||||
- 修复版本:待提交
|
||||
|
||||
## BUG-329 | 生时纠正 Agent 回答在结算后一次性出现,推理中无法停止
|
||||
|
||||
- 状态:resolved
|
||||
|
||||
@@ -105,6 +105,7 @@ const railwayWebDockerfile = new URL(
|
||||
const nextConfig = new URL("../next.config.ts", import.meta.url);
|
||||
const instrumentation = new URL("../src/instrumentation.ts", import.meta.url);
|
||||
const frontendPackage = new URL("../package.json", import.meta.url);
|
||||
const apiDockerfile = new URL("../../deploy/railway-api.Dockerfile", import.meta.url);
|
||||
|
||||
function read(url: URL): string {
|
||||
return readFileSync(url, "utf8");
|
||||
@@ -228,6 +229,15 @@ test("quality gate validates relevant changes once and publishes a digest manife
|
||||
assert.doesNotMatch(workflow, /(?:^|:)latest$/m);
|
||||
});
|
||||
|
||||
test("staging images pull official bases from Huawei SWR instead of DaoCloud", () => {
|
||||
const api = read(apiDockerfile);
|
||||
const web = read(railwayWebDockerfile);
|
||||
assert.match(api, /^FROM swr\.cn-north-4\.myhuaweicloud\.com\/ddn-k8s\/docker\.io\/library\/python:3\.12-slim$/m);
|
||||
assert.match(web, /^FROM swr\.cn-north-4\.myhuaweicloud\.com\/ddn-k8s\/docker\.io\/library\/node:22-alpine/m);
|
||||
assert.doesNotMatch(api, /daocloud/i);
|
||||
assert.doesNotMatch(web, /daocloud/i);
|
||||
});
|
||||
|
||||
test("Gitea quality gate validates before publishing an immutable ACR manifest", () => {
|
||||
const workflow = read(giteaQualityWorkflow);
|
||||
|
||||
@@ -237,6 +247,10 @@ test("Gitea quality gate validates before publishing an immutable ACR manifest",
|
||||
assert.equal((workflow.match(/runs-on: xiaoxin/g) ?? []).length, 2);
|
||||
assert.match(workflow, /validate:[\s\S]*?timeout-minutes: 45[\s\S]*?publish:[\s\S]*?timeout-minutes: 60/);
|
||||
assert.match(workflow, /GITEA_SHA: \$\{\{ gitea\.sha \}\}/);
|
||||
assert.match(
|
||||
workflow,
|
||||
/docker build -f deploy\/railway-api\.Dockerfile -t "\$IMAGE_REPOSITORY:api-\$GITEA_SHA"/,
|
||||
);
|
||||
assert.match(
|
||||
workflow,
|
||||
/docker build --build-arg NEXT_DEPLOYMENT_ID="\$GITEA_SHA" -f deploy\/railway-web\.Dockerfile/,
|
||||
|
||||
@@ -9,15 +9,18 @@ def test_railway_services_use_the_product_frontend_and_dynamic_ports() -> None:
|
||||
api = (ROOT / "deploy" / "railway-api.Dockerfile").read_text(encoding="utf-8")
|
||||
|
||||
assert "COPY frontend/package.json frontend/package-lock.json" in web
|
||||
assert "--hostname 0.0.0.0" in web and "${PORT:-3000}" in web
|
||||
assert "HOSTNAME=0.0.0.0" in web
|
||||
assert 'CMD ["node", "server.js"]' in web
|
||||
assert "next-env.d.ts" not in web
|
||||
|
||||
assert "FROM m.daocloud.io/docker.io/library/python:3.12-slim" in api
|
||||
assert "FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/python:3.12-slim" in api
|
||||
assert "daocloud" not in api.lower()
|
||||
assert "COPY SKILL.md mcp_server.py" in api
|
||||
assert "--host 0.0.0.0" in api and "${PORT:-5200}" in api
|
||||
assert "http.server" not in api
|
||||
|
||||
assert "FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/node:22-alpine" in web
|
||||
assert "daocloud" not in web.lower()
|
||||
|
||||
|
||||
def test_web_image_copies_postcss_config_before_building_frontend() -> None:
|
||||
|
||||
Reference in New Issue
Block a user