Skip to content

Commit

Permalink
feat: 插件测试中使用 uv 来控制 Python 版本并与本体共享依赖 (#320)
Browse files Browse the repository at this point in the history
* build: nonetest 现在与 noneflow 共享依赖

* feat: 使用 uv 来安装对应版本的 Python

* test: 修复测试

* docs: 添加更新日志

* ci: 删除独立的 workflow

* build: 升级 uv 版本和调整 poetry 安装顺序

* fix: 修复获取的 Python 版本不是测试环境中的问题

* refactor: 用直接导入代替环境变量并使用 httpx

* refactor: 使用 jinja 来渲染加载测试脚本并调整运行方法

* fix: 将工作目录设置为 /app

* refactor: 稍微调整一下环境变量传入的顺序

* refactor: 不提供默认 Python 版本

* test: 修复网页请求没 mock 的问题

* refactor: 并发读取 Python 版本

* refactor: 调整 DockerTestResult 的默认值
  • Loading branch information
he0119 authored Dec 11, 2024
1 parent 614ef9b commit 262b559
Show file tree
Hide file tree
Showing 20 changed files with 443 additions and 263 deletions.
54 changes: 0 additions & 54 deletions .github/workflows/docker-test.yml

This file was deleted.

41 changes: 39 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:
with:
token: ${{ secrets.CODECOV_TOKEN }}

docker:
name: Docker
noneflow-docker:
name: NoneFlow Docker
runs-on: ubuntu-latest
needs: test
steps:
Expand Down Expand Up @@ -70,3 +70,40 @@ jobs:
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}

nonetest-docker:
name: NoneTest Docker
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Docker
uses: docker/setup-buildx-action@v3

- name: Login to Github Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Generate Tags
uses: docker/metadata-action@v5
id: metadata
with:
images: ghcr.io/nonebot/nonetest
tags: |
type=semver,pattern={{version}}
type=ref,event=branch
- name: Build and Publish
uses: docker/build-push-action@v6
with:
context: .
file: ./src/providers/docker_test/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/lang/zh-CN/

## [Unreleased]

### Added

- 插件测试中使用 uv 来控制 Python 版本并与本体共享依赖

## [4.1.4] - 2024-12-08

### Fixed
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ show-bump = "bump-my-version show-bump"
snapshot-create = "pytest --inline-snapshot=create"
snapshot-fix = "pytest --inline-snapshot=fix"
store-test = "python -m src.providers.store_test"
docker-test = "python -m src.providers.docker_test"

[tool.pyright]
pythonVersion = "3.12"
Expand Down
1 change: 1 addition & 0 deletions src/plugins/github/plugins/publish/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ async def resolve_conflict_pull_requests(
# 如果信息验证失败,则跳过更新
if not result.valid:
logger.error("信息验证失败,已跳过")
logger.error(f"验证结果: {result}")
continue

# 每次切换前都要确保回到主分支
Expand Down
2 changes: 1 addition & 1 deletion src/providers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@
# 商店测试镜像
# https://github.com/orgs/nonebot/packages/container/package/nonetest
DOCKER_IMAGES_VERSION = os.environ.get("DOCKER_IMAGES_VERSION") or "latest"
DOCKER_IMAGES = f"ghcr.io/nonebot/nonetest:{{}}-{DOCKER_IMAGES_VERSION}"
DOCKER_IMAGES = f"ghcr.io/nonebot/nonetest:{DOCKER_IMAGES_VERSION}"
21 changes: 13 additions & 8 deletions src/providers/docker_test/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
ARG PYTHON_VERSION=3.12
FROM python:3.12.4
COPY --from=ghcr.io/astral-sh/uv:0.5.6 /uv /bin/uv

FROM python:${PYTHON_VERSION}
WORKDIR /app

WORKDIR /tmp
# 设置时区
ENV TZ=Asia/Shanghai

# OpenCV 所需的依赖
RUN apt-get update \
Expand All @@ -11,11 +13,14 @@ RUN apt-get update \
&& apt-get purge -y --auto-remove \
&& rm -rf /var/lib/apt/lists/*

# 测试插件依赖 Poetry
RUN curl -sSL https://install.python-poetry.org | python3 -

# 插件测试需要 Poetry
ENV PATH="${PATH}:/root/.local/bin"
RUN uv tool install poetry

# Python 依赖
COPY pyproject.toml uv.lock /app/
RUN uv sync --project /app/ --no-dev --frozen --compile-bytecode

COPY ./plugin_test.py /tmp/plugin_test.py
COPY src /app/src/

CMD ["python", "plugin_test.py"]
CMD ["uv", "run", "--project", "/app/", "--no-dev", "-m", "src.providers.docker_test"]
21 changes: 10 additions & 11 deletions src/providers/docker_test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from typing import TypedDict

import docker
from pydantic import BaseModel, Field, SkipValidation, field_validator
from pydantic import BaseModel, SkipValidation, field_validator

from src.providers.constants import DOCKER_IMAGES, REGISTRY_PLUGINS_URL
from src.providers.constants import DOCKER_IMAGES


class Metadata(TypedDict):
Expand All @@ -24,19 +24,19 @@ class DockerTestResult(BaseModel):
""" 是否运行测试 """
load: bool
""" 是否加载成功 """
output: str
""" 测试输出 """
version: str | None = None
""" 测试版本 """
config: str = ""
""" 测试配置 """
test_env: str = Field(default="unknown")
test_env: str = ""
"""测试环境
python==3.12 nonebot2==2.4.0 pydantic==2.10.0
"""
metadata: SkipValidation[Metadata] | None
metadata: SkipValidation[Metadata] | None = None
""" 插件元数据 """
output: str
""" 测试输出 """

@field_validator("config", mode="before")
@classmethod
Expand All @@ -59,20 +59,20 @@ async def run(self, version: str) -> DockerTestResult:
Returns:
DockerTestResult: 测试结果
"""
image_name = DOCKER_IMAGES.format(version)
# 连接 Docker 环境
client = docker.DockerClient(base_url="unix://var/run/docker.sock")

try:
# 运行 Docker 容器,捕获输出。 容器内运行的代码拥有超时设限,此处无需设置超时
output = client.containers.run(
image_name,
DOCKER_IMAGES,
environment={
# 运行测试的 Python 版本
"PYTHON_VERSION": version,
# 插件信息
"PROJECT_LINK": self.project_link,
"MODULE_NAME": self.module_name,
"PLUGIN_CONFIG": self.config,
# 插件测试需要用到的插件列表来验证插件依赖是否正确加载
"PLUGINS_URL": REGISTRY_PLUGINS_URL,
},
detach=False,
remove=True,
Expand All @@ -83,6 +83,5 @@ async def run(self, version: str) -> DockerTestResult:
"run": False,
"load": False,
"output": str(e),
"metadata": None,
}
return DockerTestResult(**data)
27 changes: 27 additions & 0 deletions src/providers/docker_test/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import asyncio
import os

from .plugin_test import PluginTest


def main():
"""根据传入的环境变量进行测试
PYTHON_VERSION 为运行测试的 Python 版本
PROJECT_LINK 为插件的项目名
MODULE_NAME 为插件的模块名
PLUGIN_CONFIG 为该插件的配置
"""
python_version = os.environ.get("PYTHON_VERSION", "")

project_link = os.environ.get("PROJECT_LINK", "")
module_name = os.environ.get("MODULE_NAME", "")
plugin_config = os.environ.get("PLUGIN_CONFIG", None)

plugin = PluginTest(python_version, project_link, module_name, plugin_config)

asyncio.run(plugin.run())


if __name__ == "__main__":
main()
Loading

0 comments on commit 262b559

Please sign in to comment.