Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c271270d4 |
@@ -24,7 +24,7 @@ jobs:
|
||||
echo "GPU_TYPE=${GPU_TYPE:-}"
|
||||
echo "TASK_TYPE=${TASK_TYPE:-}"
|
||||
if [ -z "${FRAMEWORK:-}" ] || [ "${FRAMEWORK}" = "vllm_fix_tokenizer" ]; then
|
||||
echo "FRAMEWORK 无效。本仓使用 vllm_0_17_0_corex_4_4_0。"
|
||||
echo "FRAMEWORK 无效。本仓使用 vllm_bi150_r2r4。"
|
||||
exit 1
|
||||
fi
|
||||
if [ "${GPU_TYPE:-}" != "Iluvatar_bi-150" ]; then
|
||||
@@ -32,8 +32,52 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
IMAGE_NAME="$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]' | tr '_' '-')"
|
||||
IMAGE_TAG="${{ gitea.ref_name }}"
|
||||
echo "FRAMEWORK=${FRAMEWORK}" >> "$GITEA_ENV"
|
||||
echo "GPU_TYPE=${GPU_TYPE}" >> "$GITEA_ENV"
|
||||
echo "TASK_TYPE=${TASK_TYPE:-}" >> "$GITEA_ENV"
|
||||
echo "IMAGE_NAME=${IMAGE_NAME}" >> "$GITEA_ENV"
|
||||
echo "IMAGE_TAG=${{ gitea.ref_name }}" >> "$GITEA_ENV"
|
||||
echo "IMAGE_TAG=${IMAGE_TAG}" >> "$GITEA_ENV"
|
||||
if [ -n "${DOCKER_REGISTRY:-}" ] && [ -n "${DOCKER_USERNAME:-}" ]; then
|
||||
echo "IMAGE=${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${IMAGE_TAG}" >> "$GITEA_ENV"
|
||||
fi
|
||||
|
||||
# FIXED_TOKEN 由 Runner 注入,不写进仓库,也不打印。
|
||||
- name: Validate Image Verify Metadata
|
||||
run: |
|
||||
if [ -z "${FIXED_TOKEN:-}" ]; then
|
||||
echo "FIXED_TOKEN is not configured on runner"
|
||||
exit 1
|
||||
fi
|
||||
if ! response="$(curl --silent --show-error --location --get \
|
||||
'https://modelhub.org.cn/adminApi/image-verify/validate' \
|
||||
--header "Xc-Token: ${FIXED_TOKEN}" \
|
||||
--data-urlencode "gpuType=${GPU_TYPE:-}" \
|
||||
--data-urlencode "taskType=${TASK_TYPE:-}")"; then
|
||||
echo "调用 image-verify validate 失败"
|
||||
exit 1
|
||||
fi
|
||||
VALIDATE_RESPONSE="$response" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
raw = os.environ.get("VALIDATE_RESPONSE", "")
|
||||
try:
|
||||
body = json.loads(raw)
|
||||
except json.JSONDecodeError:
|
||||
print("image-verify validate 返回的不是合法 JSON")
|
||||
print(raw)
|
||||
sys.exit(1)
|
||||
|
||||
if body.get("code") == 0 and body.get("data") is True:
|
||||
print("image-verify 元数据校验通过")
|
||||
sys.exit(0)
|
||||
|
||||
print(f"image-verify 元数据校验失败: {body.get('message') or '未知错误'}")
|
||||
print(raw)
|
||||
sys.exit(1)
|
||||
PY
|
||||
|
||||
- name: Build image
|
||||
run: |
|
||||
@@ -45,12 +89,40 @@ jobs:
|
||||
run: |
|
||||
if [ -z "${DOCKER_REGISTRY:-}" ] || [ -z "${DOCKER_USERNAME:-}" ] || [ -z "${DOCKER_PASSWORD:-}" ]; then
|
||||
echo "未配置 DOCKER_REGISTRY、DOCKER_USERNAME 或 DOCKER_PASSWORD。"
|
||||
echo "本次为 build-only,不登录仓库,不推送镜像。"
|
||||
echo "本次为 build-only,不登录仓库,不推送镜像,随后也不注册 image-verify。"
|
||||
echo "PUSHED=0" >> "$GITEA_ENV"
|
||||
exit 0
|
||||
fi
|
||||
remote="${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
echo "推送目标: ${remote}"
|
||||
echo "推送目标: ${IMAGE}"
|
||||
echo "$DOCKER_PASSWORD" | docker login "$DOCKER_REGISTRY" -u "$DOCKER_USERNAME" --password-stdin
|
||||
docker tag "${IMAGE_NAME}:${IMAGE_TAG}" "$remote"
|
||||
docker push "$remote"
|
||||
echo "推送完成: ${remote}"
|
||||
docker tag "${IMAGE_NAME}:${IMAGE_TAG}" "$IMAGE"
|
||||
docker push "$IMAGE"
|
||||
echo "PUSHED=1" >> "$GITEA_ENV"
|
||||
echo "推送完成: ${IMAGE}"
|
||||
|
||||
# 只有真的推成功才注册,build-only 没有可用的 imageUrl。
|
||||
- name: Notify Image Verify
|
||||
run: |
|
||||
if [ "${PUSHED:-0}" != "1" ]; then
|
||||
echo "镜像未推送,跳过 image-verify 注册。"
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "${FIXED_TOKEN:-}" ]; then
|
||||
echo "FIXED_TOKEN is not configured on runner"
|
||||
exit 1
|
||||
fi
|
||||
echo "注册 image-verify: ${IMAGE}"
|
||||
curl --silent --show-error --fail-with-body --location --request POST \
|
||||
'https://modelhub.org.cn//adminApi/image-verify' \
|
||||
--header "Xc-Token: ${FIXED_TOKEN}" \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw "{
|
||||
\"framework\": \"${FRAMEWORK}\",
|
||||
\"gpuType\": \"${GPU_TYPE}\",
|
||||
\"imageUrl\": \"${IMAGE}\",
|
||||
\"taskType\": \"${TASK_TYPE}\",
|
||||
\"createBy\": \"${{ gitea.actor }}\",
|
||||
\"repoUrl\": \"${{ gitea.server_url }}/${{ gitea.repository }}\",
|
||||
\"tag\": \"${{ gitea.ref_name }}\"
|
||||
}"
|
||||
echo "image-verify 注册请求已完成。适配下拉是否出现本引擎由人核对。"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
GPU_TYPE=Iluvatar_bi-150
|
||||
FRAMEWORK=vllm_0_17_0_corex_4_4_0
|
||||
FRAMEWORK=vllm_bi150_r2r4
|
||||
TASK_TYPE=text-generation
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
ARG BASE_IMAGE=registry.iluvatar.com.cn:10443/customer/sz/vllm0.17.0-4.4.0-x86:v4.1
|
||||
FROM ${BASE_IMAGE}
|
||||
|
||||
ENV FRAMEWORK=vllm_0_17_0_corex_4_4_0 \
|
||||
ENV FRAMEWORK=vllm_bi150_r2r4 \
|
||||
GPU_TYPE=Iluvatar_bi-150 \
|
||||
TASK_TYPE=text-generation \
|
||||
MODEL_DIR=/model \
|
||||
|
||||
24
README.md
24
README.md
@@ -10,7 +10,7 @@
|
||||
|
||||
- Track B(竞赛)为 **NO-GO**。没有 `contest/`,没有竞赛构建。
|
||||
- 没有 ZIP 打包,没有上传驱动的 Makefile 目标。
|
||||
- `FRAMEWORK` 使用 `vllm_0_17_0_corex_4_4_0`,不使用 `vllm_fix_tokenizer`。
|
||||
- `FRAMEWORK` 使用 `vllm_bi150_r2r4`,不使用 `vllm_fix_tokenizer`。
|
||||
- tokenizer 修补(I5)未开启。现有 bi150 引擎已覆盖 tokenizer;本仓补的是 chat_template(R2)和 architecture 白名单(R4)。
|
||||
|
||||
## 基线镜像
|
||||
@@ -40,21 +40,37 @@ make dry-run
|
||||
|
||||
`make dry-run` 只打印启动计划与模板预览,不启动 vLLM,不访问平台。
|
||||
|
||||
## 改 FRAMEWORK
|
||||
## FRAMEWORK
|
||||
|
||||
默认值写在 [task_info.env.example](task_info.env.example)。镜像内和 CI 使用同一组值:
|
||||
|
||||
- `GPU_TYPE=Iluvatar_bi-150`
|
||||
- `FRAMEWORK=vllm_0_17_0_corex_4_4_0`
|
||||
- `FRAMEWORK=vllm_bi150_r2r4`
|
||||
- `TASK_TYPE=text-generation`
|
||||
|
||||
### 为什么不用 `vllm_0_17_0_corex_4_4_0`
|
||||
|
||||
适配页按 FRAMEWORK 聚合。该名字已被 **i-liangzhuobang** 占用展示,本仓 v0.1.0 用它注册时,引擎下拉里看到的是对方的开发者身份。`vllm_bi150_r2r4` 是本仓独有的名字,用来让适配页正确归属。
|
||||
|
||||
若平台给出新的 FRAMEWORK 名,同时改这三处,并让 `make test` 保持通过:
|
||||
|
||||
- `task_info.env.example`
|
||||
- `.gitea/workflows/task_info.env`
|
||||
- `Dockerfile` 的 `ENV`
|
||||
|
||||
不要改回 `vllm_fix_tokenizer`。
|
||||
不要改回 `vllm_fix_tokenizer`,也不要改回撞名的旧值。
|
||||
|
||||
## CI 与 image-verify
|
||||
|
||||
`v*` 标签触发 [.gitea/workflows/build.yml](.gitea/workflows/build.yml):
|
||||
|
||||
```text
|
||||
Clone → Load task info → Validate Image Verify Metadata → Build image → Push → Notify Image Verify
|
||||
```
|
||||
|
||||
Validate 在构建前校验 `gpuType` 与 `taskType`;Notify 只在镜像真的推送成功后注册 `imageUrl`。两步都要 Runner 注入 `FIXED_TOKEN`,仓库里不存任何 Token。
|
||||
|
||||
CI 只调用 `adminApi/image-verify` 和它的 `validate`。不代领、也不代提交适配任务。
|
||||
|
||||
## 建仓与选用
|
||||
|
||||
|
||||
@@ -2,13 +2,33 @@
|
||||
|
||||
时区:**Asia/Shanghai**。本模板由人工填写。仓库不自动采集审核状态。
|
||||
|
||||
- 镜像 tag:待填写
|
||||
- CI 地址:待填写
|
||||
## 镜像
|
||||
|
||||
- 镜像 tag:待填写(例:v0.1.1)
|
||||
- 完整 imageUrl:待填写(例:harbor.4pd.io/modelhubxc/vc-nosugar/modelhub-engine-bi150-compat:v0.1.1)
|
||||
- 镜像 digest:待填写
|
||||
- CI 地址:待填写(例:https://dev.modelhub.org.cn/VC_noSugar/modelhub-engine-bi150-compat/actions/runs/N)
|
||||
|
||||
## image-verify
|
||||
|
||||
- FRAMEWORK 展示名:vllm_bi150_r2r4
|
||||
- Validate 通过时间(Asia/Shanghai):待填写
|
||||
- Notify HTTP 结果:待填写
|
||||
- createBy / 适配 UI 开发者:应为 VC_noSugar(或页面等价展示)
|
||||
- 适配下拉是否可见 vllm_bi150_r2r4:待填写
|
||||
- 抽检模型(只看下拉可见,不提交任务):Qwen/Qwen2.5-0.5B-Instruct
|
||||
|
||||
## 平台
|
||||
|
||||
- 平台状态:未推送
|
||||
- 审核:未开始
|
||||
- 审核通过时间(Asia/Shanghai):待填写
|
||||
- 首次被适配任务选用的任务 ID:待填写
|
||||
- 选用时间(Asia/Shanghai):待填写
|
||||
- 平台状态:未推送
|
||||
- 积分:待平台核实
|
||||
|
||||
## 说明
|
||||
|
||||
v0.1.0 用的是撞名的 `vllm_0_17_0_corex_4_4_0`,适配页把它聚合到了别人名下,且流水线没有 image-verify 注册。可见性要看含 Validate + Notify 的新 Tag。
|
||||
|
||||
无卡本地测试只说明 R2/R4 修补逻辑能跑,不说明天垓 150 上的吞吐。
|
||||
|
||||
@@ -2,13 +2,24 @@
|
||||
|
||||
Track B 不在本仓实现,状态保持 NO-GO。
|
||||
|
||||
## 首版(v0.1.0)
|
||||
|
||||
- [x] I0 仓骨架 + README + 非目标声明
|
||||
- [x] I1 Dockerfile + task_info.env.example
|
||||
- [x] I2 wrapper + dry-run
|
||||
- [x] I3 R2 chat_template 修补
|
||||
- [x] I4 R4 architecture 白名单
|
||||
- [ ] I5 tokenizer 修补(未开启;等 R2/R4 确认盖不住目标模型族再做)
|
||||
- [x] I6 CI build(Tag 触发;无凭据时 build-only;不提交平台任务)
|
||||
- [x] I6 CI build(Tag 触发;无凭据时 build-only)
|
||||
- [x] I7 人工 runbook + evidence 模板
|
||||
|
||||
本地 `make test` 已覆盖 I3/I4 与 dry-run。镜像是否能在 Runner 上拉到基线 tag,要等第一次 `v*` 流水线。
|
||||
## image-verify 注册(待发 v0.1.1)
|
||||
|
||||
- [x] I8 FRAMEWORK 改为 `vllm_bi150_r2r4`,全仓同步,避开与 i-liangzhuobang 撞名
|
||||
- [x] I9 CI 在 build 前 Validate Image Verify Metadata,缺 `FIXED_TOKEN` 失败且不打印 Token
|
||||
- [x] I10 CI 在推送成功后 Notify Image Verify,body 含 framework/gpuType/imageUrl/taskType/createBy/repoUrl/tag
|
||||
- [x] I11 单测契约翻转:要求 CI 含 image-verify,仍禁 ZIP/contest/代提交,仍拒 `vllm_fix_tokenizer`
|
||||
- [x] I12 runbook + evidence 写明注册步骤与下拉归属核对
|
||||
- [ ] I13 发版:推 main + tag v0.1.1;Actions 出现 Validate + Notify;人工抽检下拉
|
||||
|
||||
本地 `make test` 20 项覆盖 I3/I4、dry-run 与 CI 契约。镜像能否拉到基线 tag、适配下拉是否归属 `VC_noSugar`,都要等 v0.1.1 流水线和人工核对。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 建仓、打 Tag、选用引擎(人工)
|
||||
|
||||
本仓没有自动提交命令。CI 只构建镜像;仓库凭据齐全时才推送。CI 不调用 modelhub.org.cn,不代领适配任务。
|
||||
本仓没有自动提交命令。CI 构建镜像、在凭据齐全时推送,并把镜像注册到 `image-verify`。注册只是让适配页能看到这个引擎,不等于代领或代提交适配任务。
|
||||
|
||||
积分:待平台核实。
|
||||
|
||||
@@ -23,17 +23,24 @@ git push origin v0.1.0
|
||||
|
||||
## 3. 看 CI
|
||||
|
||||
流水线顺序:`Clone → Load task info → Validate Image Verify Metadata → Build image → Push → Notify Image Verify`。
|
||||
|
||||
1. 打开该 Tag 的 Actions / 流水线。
|
||||
2. `Load task info` 应打印 `FRAMEWORK=vllm_0_17_0_corex_4_4_0` 和 `GPU_TYPE=Iluvatar_bi-150`。
|
||||
3. `Build image` 执行 `docker build`。基线镜像拉取失败时,日志会停在构建步骤;无卡不能代替真机验证。
|
||||
4. 若 Runner 没有 `DOCKER_REGISTRY`、`DOCKER_USERNAME`、`DOCKER_PASSWORD`,流水线打印 build-only 并成功结束,不推送。
|
||||
5. 三份凭据都由 Runner 环境提供,不写进仓库。有凭据时才会 `docker login` 并推送。
|
||||
2. `Load task info` 应打印 `FRAMEWORK=vllm_bi150_r2r4` 和 `GPU_TYPE=Iluvatar_bi-150`。
|
||||
3. `Validate Image Verify Metadata` 在构建前 GET `adminApi/image-verify/validate`,校验 `gpuType` 与 `taskType`。缺 `FIXED_TOKEN` 这步直接失败。
|
||||
4. `Build image` 执行 `docker build`。基线镜像拉取失败时,日志会停在构建步骤;无卡不能代替真机验证。
|
||||
5. `Push` 需要 `DOCKER_REGISTRY`、`DOCKER_USERNAME`、`DOCKER_PASSWORD`。缺任意一项就打印 build-only 并成功结束,不推送。
|
||||
6. `Notify Image Verify` 只在推送成功后 POST `adminApi/image-verify`,把 `framework`、`gpuType`、`imageUrl`、`taskType`、`createBy`、`repoUrl`、`tag` 注册上去。build-only 时跳过,因为没有真实 `imageUrl`。
|
||||
7. `FIXED_TOKEN` 与 Harbor 密码都由 Runner 注入,不写进仓库,也不在日志里打印。打新 Tag 前先确认旧 Harbor 密码已轮换。
|
||||
|
||||
旧 Tag 不会自动补注册。`v0.1.0` 没有 Notify 步骤,必须打新 Tag 重跑。
|
||||
|
||||
## 4. 在模盒选用引擎
|
||||
|
||||
1. 用浏览器登录模盒。
|
||||
2. 等镜像审核通过。审核状态由人在页面上确认。
|
||||
3. 在适配任务里选用该引擎。本仓不代为创建或提交任务。
|
||||
4. 把审核通过时间、镜像 tag、以及首次被选用的适配任务 ID 写入 `docs/evidence.md`。积分栏保持「待平台核实」。
|
||||
2. 在适配任务的引擎下拉里确认能看到 `vllm_bi150_r2r4`,且开发者 / `createBy` 是 `VC_noSugar`(或页面等价展示)。如果看到的是别人的名字,说明 FRAMEWORK 又撞名了。
|
||||
3. 等镜像审核通过。审核状态由人在页面上确认。
|
||||
4. 在适配任务里选用该引擎。本仓不代为创建或提交任务。可用 `Qwen/Qwen2.5-0.5B-Instruct`(`Qwen2ForCausalLM`,在 R4 白名单内)只做下拉可见性抽检。
|
||||
5. 把审核通过时间、镜像 tag、`imageUrl`、以及首次被选用的适配任务 ID 写入 `docs/evidence.md`。积分栏保持「待平台核实」。
|
||||
|
||||
字段以登录后的控制台为准。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
【引擎 bi150-compat】2026-10-13
|
||||
- 本周:I0–I4、I6、I7 完成;I5 未开启。阻塞:尚未推送 Gitea,也还没有真机流水线。
|
||||
- 镜像 tag:未构建。默认基线 registry.iluvatar.com.cn:10443/customer/sz/vllm0.17.0-4.4.0-x86:v4.1(公开仓反推)
|
||||
- 本地 test:见 make test
|
||||
- 平台:未推送
|
||||
【引擎 bi150-compat · image-verify】2026-10-13
|
||||
- 本周:I8–I12 补注册 CI;FRAMEWORK 改为 vllm_bi150_r2r4(避开与 i-liangzhuobang 撞名)
|
||||
- 镜像:v0.1.0 已推;待发 v0.1.1(含 validate + notify)
|
||||
- 本地 test:make test 20 项通过
|
||||
- 平台:Harbor 有镜像但适配下拉尚无本仓身份;根因缺 image-verify 注册
|
||||
- 积分:待核实
|
||||
- 下周:人工建仓、打 v* Tag、看 CI;审核通过或被选用后再填 docs/evidence.md
|
||||
- 下周:打 v0.1.1 → 确认下拉可见 vllm_bi150_r2r4 且归属 VC_noSugar → 证据写入 docs/evidence.md(不代提交适配)
|
||||
|
||||
@@ -12,6 +12,7 @@ import sys
|
||||
from pathlib import Path
|
||||
|
||||
FORBIDDEN_FRAMEWORK = "vllm_fix_tokenizer"
|
||||
DEFAULT_FRAMEWORK = "vllm_bi150_r2r4"
|
||||
TOKENIZER_PATCH_KEY = "modelhub_tokenizer_patch"
|
||||
|
||||
|
||||
@@ -26,7 +27,7 @@ def engine_root() -> Path:
|
||||
def assert_framework(framework: str) -> None:
|
||||
if not framework or framework == FORBIDDEN_FRAMEWORK:
|
||||
raise PatchError(
|
||||
"FRAMEWORK 必须是 vllm_0_17_0_corex_4_4_0,"
|
||||
f"FRAMEWORK 必须是 {DEFAULT_FRAMEWORK},"
|
||||
"不能使用 vllm_fix_tokenizer"
|
||||
)
|
||||
|
||||
@@ -157,7 +158,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
root = engine_root()
|
||||
parser = argparse.ArgumentParser(description="应用 R2/R4 模型目录修补")
|
||||
parser.add_argument("--model-dir", required=True, type=Path)
|
||||
parser.add_argument("--framework", default="vllm_0_17_0_corex_4_4_0")
|
||||
parser.add_argument("--framework", default=DEFAULT_FRAMEWORK)
|
||||
parser.add_argument("--unknown-policy", default="fail", choices=("fail", "skip"))
|
||||
parser.add_argument("--force-chat-template", action="store_true")
|
||||
parser.add_argument("--tokenizer-patch", action="store_true")
|
||||
|
||||
@@ -61,7 +61,7 @@ APPLY_TOKENIZER_PATCH="${APPLY_TOKENIZER_PATCH:-0}"
|
||||
FORCE_CHAT_TEMPLATE="${FORCE_CHAT_TEMPLATE:-0}"
|
||||
|
||||
if [[ -z "$FRAMEWORK" || "$FRAMEWORK" == "vllm_fix_tokenizer" ]]; then
|
||||
echo "拒绝 FRAMEWORK=${FRAMEWORK:-空}。本仓使用 vllm_0_17_0_corex_4_4_0。" >&2
|
||||
echo "拒绝 FRAMEWORK=${FRAMEWORK:-空}。本仓使用 vllm_bi150_r2r4。" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$GPU_TYPE" ]]; then
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# 本地与镜像内的默认任务信息。平台若给出不同 FRAMEWORK,只改这一处,并保持 Dockerfile 的 ENV 与 CI 文件一致。
|
||||
# FRAMEWORK 必须是本仓独有的名字,否则适配页会把镜像聚合到同名的别人名下。
|
||||
GPU_TYPE=Iluvatar_bi-150
|
||||
FRAMEWORK=vllm_0_17_0_corex_4_4_0
|
||||
FRAMEWORK=vllm_bi150_r2r4
|
||||
TASK_TYPE=text-generation
|
||||
MODEL_DIR=/model
|
||||
SERVED_MODEL_NAME=llm
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FRAMEWORK = "vllm_bi150_r2r4"
|
||||
RETIRED_FRAMEWORK = "vllm_0_17_0_corex_4_4_0"
|
||||
|
||||
|
||||
class EngineContractTest(unittest.TestCase):
|
||||
@@ -11,11 +14,11 @@ class EngineContractTest(unittest.TestCase):
|
||||
example = (ROOT / "task_info.env.example").read_text(encoding="utf-8")
|
||||
workflow_env = (ROOT / ".gitea/workflows/task_info.env").read_text(encoding="utf-8")
|
||||
dockerfile = (ROOT / "Dockerfile").read_text(encoding="utf-8")
|
||||
self.assertIn("FRAMEWORK=vllm_0_17_0_corex_4_4_0", example)
|
||||
self.assertIn(f"FRAMEWORK={FRAMEWORK}", example)
|
||||
self.assertIn("GPU_TYPE=Iluvatar_bi-150", example)
|
||||
self.assertIn("FRAMEWORK=vllm_0_17_0_corex_4_4_0", workflow_env)
|
||||
self.assertIn(f"FRAMEWORK={FRAMEWORK}", workflow_env)
|
||||
self.assertIn("GPU_TYPE=Iluvatar_bi-150", workflow_env)
|
||||
self.assertIn("FRAMEWORK=vllm_0_17_0_corex_4_4_0", dockerfile)
|
||||
self.assertIn(f"FRAMEWORK={FRAMEWORK}", dockerfile)
|
||||
self.assertIn("GPU_TYPE=Iluvatar_bi-150", dockerfile)
|
||||
self.assertIn(
|
||||
"registry.iluvatar.com.cn:10443/customer/sz/vllm0.17.0-4.4.0-x86:v4.1",
|
||||
@@ -24,13 +27,83 @@ class EngineContractTest(unittest.TestCase):
|
||||
self.assertNotIn("FRAMEWORK=vllm_fix_tokenizer", example)
|
||||
self.assertNotIn("FRAMEWORK=vllm_fix_tokenizer", workflow_env)
|
||||
self.assertNotIn("FRAMEWORK=vllm_fix_tokenizer", dockerfile)
|
||||
self.assertNotIn(RETIRED_FRAMEWORK, example)
|
||||
self.assertNotIn(RETIRED_FRAMEWORK, workflow_env)
|
||||
self.assertNotIn(RETIRED_FRAMEWORK, dockerfile)
|
||||
|
||||
def test_ci_does_not_submit_platform_task(self) -> None:
|
||||
def test_ci_registers_image_verify(self) -> None:
|
||||
workflow = (ROOT / ".gitea/workflows/build.yml").read_text(encoding="utf-8")
|
||||
self.assertNotIn("adminApi", workflow)
|
||||
self.assertNotIn("modelhub.org.cn", workflow)
|
||||
self.assertIn("Validate Image Verify Metadata", workflow)
|
||||
self.assertIn("https://modelhub.org.cn/adminApi/image-verify/validate", workflow)
|
||||
self.assertIn("Notify Image Verify", workflow)
|
||||
self.assertIn("https://modelhub.org.cn//adminApi/image-verify", workflow)
|
||||
self.assertIn("Xc-Token: ${FIXED_TOKEN}", workflow)
|
||||
self.assertIn("FIXED_TOKEN is not configured on runner", workflow)
|
||||
for field in ("framework", "gpuType", "imageUrl", "taskType", "createBy", "repoUrl", "tag"):
|
||||
self.assertIn(f'\\"{field}\\"', workflow)
|
||||
self.assertIn("build-only", workflow)
|
||||
self.assertIn('tags:', workflow)
|
||||
self.assertIn("tags:", workflow)
|
||||
self.assertIn(f"本仓使用 {FRAMEWORK}", workflow)
|
||||
self.assertNotIn(RETIRED_FRAMEWORK, workflow)
|
||||
|
||||
def test_ci_notifies_only_after_push(self) -> None:
|
||||
workflow = (ROOT / ".gitea/workflows/build.yml").read_text(encoding="utf-8")
|
||||
self.assertIn('PUSHED=1', workflow)
|
||||
self.assertIn('if [ "${PUSHED:-0}" != "1" ]; then', workflow)
|
||||
notify_at = workflow.index("Notify Image Verify")
|
||||
push_at = workflow.index("Push when registry credentials exist")
|
||||
validate_at = workflow.index("Validate Image Verify Metadata")
|
||||
build_at = workflow.index("Build image")
|
||||
self.assertLess(validate_at, build_at)
|
||||
self.assertLess(build_at, push_at)
|
||||
self.assertLess(push_at, notify_at)
|
||||
|
||||
def test_ci_does_not_submit_adaptation_task(self) -> None:
|
||||
workflow = (ROOT / ".gitea/workflows/build.yml").read_text(encoding="utf-8")
|
||||
allowed = {
|
||||
"https://modelhub.org.cn/adminApi/image-verify/validate",
|
||||
"https://modelhub.org.cn//adminApi/image-verify",
|
||||
}
|
||||
for url in re.findall(r"https?://[^\s'\"]+", workflow):
|
||||
if "modelhub.org.cn" not in url:
|
||||
continue
|
||||
self.assertIn(url, allowed, f"CI 只允许调用 image-verify,发现 {url}")
|
||||
|
||||
def test_no_secret_literals_in_repo(self) -> None:
|
||||
tracked = subprocess.run(
|
||||
["git", "ls-files"],
|
||||
cwd=ROOT,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=True,
|
||||
).stdout.split()
|
||||
pattern = re.compile(r"(FIXED_TOKEN|DOCKER_PASSWORD)\s*=\s*\S")
|
||||
for name in tracked:
|
||||
path = ROOT / name
|
||||
if not path.is_file():
|
||||
continue
|
||||
try:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
for line in text.splitlines():
|
||||
self.assertIsNone(pattern.search(line), f"{name} 可能写入了明文密钥: {line}")
|
||||
|
||||
def test_ci_does_not_log_secrets(self) -> None:
|
||||
workflow = (ROOT / ".gitea/workflows/build.yml").read_text(encoding="utf-8")
|
||||
for line in workflow.splitlines():
|
||||
stripped = line.strip()
|
||||
if "FIXED_TOKEN" in stripped:
|
||||
self.assertFalse(
|
||||
stripped.startswith("echo") and "${FIXED_TOKEN" in stripped,
|
||||
f"不要把 FIXED_TOKEN 打进日志: {stripped}",
|
||||
)
|
||||
if stripped.startswith("echo") and "$DOCKER_PASSWORD" in stripped:
|
||||
self.assertIn(
|
||||
"docker login",
|
||||
stripped,
|
||||
f"DOCKER_PASSWORD 只能管道给 docker login: {stripped}",
|
||||
)
|
||||
|
||||
def test_no_zip_or_contest_targets(self) -> None:
|
||||
makefile = (ROOT / "Makefile").read_text(encoding="utf-8")
|
||||
@@ -53,11 +126,12 @@ class EngineContractTest(unittest.TestCase):
|
||||
check=False,
|
||||
)
|
||||
self.assertEqual(completed.returncode, 0, completed.stderr)
|
||||
self.assertIn("FRAMEWORK=vllm_0_17_0_corex_4_4_0", completed.stdout)
|
||||
self.assertIn(f"FRAMEWORK={FRAMEWORK}", completed.stdout)
|
||||
self.assertIn("GPU_TYPE=Iluvatar_bi-150", completed.stdout)
|
||||
self.assertIn("python3 -m vllm.entrypoints.openai.api_server", completed.stdout)
|
||||
self.assertIn("dry-run: 不启动进程,不访问平台", completed.stdout)
|
||||
self.assertNotIn("modelhub.org.cn", completed.stdout)
|
||||
self.assertNotIn(RETIRED_FRAMEWORK, completed.stdout)
|
||||
self.assertIn("<|user|>", completed.stdout)
|
||||
|
||||
def test_dry_run_rejects_forbidden_framework(self) -> None:
|
||||
@@ -73,6 +147,7 @@ class EngineContractTest(unittest.TestCase):
|
||||
)
|
||||
self.assertNotEqual(completed.returncode, 0)
|
||||
self.assertIn("vllm_fix_tokenizer", completed.stderr)
|
||||
self.assertIn(FRAMEWORK, completed.stderr)
|
||||
|
||||
def test_tokenizer_patch_stays_off(self) -> None:
|
||||
import shutil
|
||||
@@ -80,6 +155,7 @@ class EngineContractTest(unittest.TestCase):
|
||||
|
||||
import apply_patches
|
||||
|
||||
self.assertEqual(apply_patches.DEFAULT_FRAMEWORK, FRAMEWORK)
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
model = Path(tmp) / "model"
|
||||
shutil.copytree(ROOT / "tests" / "fixtures" / "fake-model", model)
|
||||
|
||||
Reference in New Issue
Block a user