mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-08 17:08:35 +08:00
fix(ci): gate pylint on changed files
This commit is contained in:
@@ -23,7 +23,9 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up uv
|
- name: Set up uv
|
||||||
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
||||||
@@ -49,29 +51,48 @@ jobs:
|
|||||||
echo "❌ 未找到 .pylintrc 配置文件"
|
echo "❌ 未找到 .pylintrc 配置文件"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Run pylint
|
- name: Collect changed Python files
|
||||||
|
id: changed
|
||||||
|
env:
|
||||||
|
EVENT_NAME: ${{ github.event_name }}
|
||||||
|
BASE_REF: ${{ github.base_ref }}
|
||||||
|
BEFORE_SHA: ${{ github.event.before }}
|
||||||
|
CURRENT_SHA: ${{ github.sha }}
|
||||||
run: |
|
run: |
|
||||||
# 运行pylint,检查主要的Python文件
|
if [[ "$EVENT_NAME" == "pull_request" ]]; then
|
||||||
echo "🚀 运行 Pylint 错误检查..."
|
git diff --name-only --diff-filter=ACMRT \
|
||||||
|
"origin/$BASE_REF...HEAD" -- '*.py' > changed-python-files.txt
|
||||||
|
elif [[ "$EVENT_NAME" == "push" ]] \
|
||||||
|
&& [[ -n "$BEFORE_SHA" ]] \
|
||||||
|
&& [[ ! "$BEFORE_SHA" =~ ^0+$ ]] \
|
||||||
|
&& git cat-file -e "$BEFORE_SHA^{commit}"; then
|
||||||
|
git diff --name-only --diff-filter=ACMRT \
|
||||||
|
"$BEFORE_SHA" "$CURRENT_SHA" -- '*.py' > changed-python-files.txt
|
||||||
|
else
|
||||||
|
git diff-tree --no-commit-id --name-only --diff-filter=ACMRT \
|
||||||
|
-r HEAD -- '*.py' > changed-python-files.txt
|
||||||
|
fi
|
||||||
|
sort -u -o changed-python-files.txt changed-python-files.txt
|
||||||
|
if [[ -s changed-python-files.txt ]]; then
|
||||||
|
echo "has_files=true" >> "$GITHUB_OUTPUT"
|
||||||
|
sed -n '1,200p' changed-python-files.txt
|
||||||
|
else
|
||||||
|
echo "has_files=false" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "本次没有改动 Python 文件"
|
||||||
|
fi
|
||||||
|
|
||||||
# 检查主要目录 - 只关注错误,如果有错误则退出
|
- name: Run pylint on changed Python files
|
||||||
echo "📂 检查 app/ 目录..."
|
if: steps.changed.outputs.has_files == 'true'
|
||||||
uv run --locked --no-sync pylint app/ --output-format=colorized --reports=yes --score=yes
|
run: |
|
||||||
|
xargs uv run --locked --no-sync pylint \
|
||||||
|
--output-format=colorized --reports=yes --score=yes \
|
||||||
|
< changed-python-files.txt
|
||||||
|
|
||||||
# 检查根目录的Python文件
|
- name: Generate full advisory report
|
||||||
echo "📂 检查根目录 Python 文件..."
|
if: always()
|
||||||
for file in $(find . -name "*.py" -not -path "./.*" -not -path "./.venv/*" -not -path "./build/*" -not -path "./dist/*" -not -path "./tests/*" -not -path "./docs/*" -not -path "./__pycache__/*" -maxdepth 1); do
|
run: |
|
||||||
echo "检查文件: $file"
|
uv run --locked --no-sync pylint app/ \
|
||||||
uv run --locked --no-sync pylint "$file" --output-format=colorized || exit 1
|
--output-format=json > pylint-report.json || true
|
||||||
done
|
|
||||||
|
|
||||||
# 生成详细报告
|
|
||||||
echo "📊 生成 Pylint 详细报告..."
|
|
||||||
uv run --locked --no-sync pylint app/ --output-format=json > pylint-report.json || true
|
|
||||||
|
|
||||||
# 显示评分(仅供参考)
|
|
||||||
echo "📈 Pylint 评分(仅供参考):"
|
|
||||||
uv run --locked --no-sync pylint app/ --score=yes --reports=no | tail -2 || true
|
|
||||||
|
|
||||||
- name: Upload pylint report
|
- name: Upload pylint report
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -83,5 +104,5 @@ jobs:
|
|||||||
- name: Summary
|
- name: Summary
|
||||||
run: |
|
run: |
|
||||||
echo "🎉 Pylint 检查完成!"
|
echo "🎉 Pylint 检查完成!"
|
||||||
echo "✅ 没有发现语法错误或严重问题"
|
echo "✅ 改动 Python 文件没有新增语法错误或严重问题"
|
||||||
echo "📊 详细报告已保存为构建工件"
|
echo "📊 全仓建议性报告已保存为构建工件"
|
||||||
|
|||||||
+1
-1
@@ -147,7 +147,7 @@ def test_recognize_prefers_explicit_identity(sample_meta, monkeypatch):
|
|||||||
|
|
||||||
- **门禁**:`.github/workflows/test.yml` 在指向 `v3` 的 `pull_request` / `push` 及手动触发时,从 `uv.lock` 同步环境。独立 `architecture` job 先运行宿主依赖、运行契约和基线 CLI 快速门禁;全量测试再通过 `tests/run.py --shard N/TOTAL` 稳定分到 4 个 pytest job。每个分片都有独立进程和临时 `CONFIG_DIR`,不共用 SQLite 或进程级状态。
|
- **门禁**:`.github/workflows/test.yml` 在指向 `v3` 的 `pull_request` / `push` 及手动触发时,从 `uv.lock` 同步环境。独立 `architecture` job 先运行宿主依赖、运行契约和基线 CLI 快速门禁;全量测试再通过 `tests/run.py --shard N/TOTAL` 稳定分到 4 个 pytest job。每个分片都有独立进程和临时 `CONFIG_DIR`,不共用 SQLite 或进程级状态。
|
||||||
- **跨仓观察**:`.github/workflows/architecture-observe.yml` 每周或手工检出官方插件仓最新 `main`,使用 `--check-plugins` 比较公开导入、Hook 和动态 API 契约。它只上传 `official-plugin-architecture-report.json`,不会自动刷新 fixture;语义变化必须人工审查后显式执行 `--write-plugins`。
|
- **跨仓观察**:`.github/workflows/architecture-observe.yml` 每周或手工检出官方插件仓最新 `main`,使用 `--check-plugins` 比较公开导入、Hook 和动态 API 契约。它只上传 `official-plugin-architecture-report.json`,不会自动刷新 fixture;语义变化必须人工审查后显式执行 `--write-plugins`。
|
||||||
- **静态检查**:`.github/workflows/pylint.yml` 对指向 `v3` 的 PR、推送和手工触发运行现有严重错误门禁,不再仅依赖维护者手工执行。
|
- **静态检查**:`.github/workflows/pylint.yml` 对指向 `v3` 的 PR、推送和手工触发运行 Pylint。PR/推送改动到的 Python 文件是硬门禁;`app/` 全量扫描保留为建议性 JSON 构建工件,存量告警不会掩盖或阻塞本次增量治理。
|
||||||
- **PR**:产品代码、测试基础设施、依赖或运行行为发生变化时,运行 `uv run --locked --no-sync python tests/run.py`,默认以 4 个独立 pytest 进程完成全量;需要断点、输出顺序或测试污染诊断时使用 `--serial`。确认本次改动涉及的路径通过且 socket 探针零真实出站。若存在无关失败,必须在当前 `upstream/v3` 基线上独立复现并在 PR 中如实说明;不得静默扩大当前 PR 去修复基线问题。纯文档变更按实际内容执行文本、结构和 diff 检查,CI 仍会运行全量门禁。
|
- **PR**:产品代码、测试基础设施、依赖或运行行为发生变化时,运行 `uv run --locked --no-sync python tests/run.py`,默认以 4 个独立 pytest 进程完成全量;需要断点、输出顺序或测试污染诊断时使用 `--serial`。确认本次改动涉及的路径通过且 socket 探针零真实出站。若存在无关失败,必须在当前 `upstream/v3` 基线上独立复现并在 PR 中如实说明;不得静默扩大当前 PR 去修复基线问题。纯文档变更按实际内容执行文本、结构和 diff 检查,CI 仍会运行全量门禁。
|
||||||
- 覆盖率不参与常规 PR / push 的合并门禁;需要覆盖率制品时手动触发 `Unit Tests` workflow,独立的 `Coverage Report` job 会通过 `tests/run.py --serial` 跑串行全量并上传 JSON / XML 报告。
|
- 覆盖率不参与常规 PR / push 的合并门禁;需要覆盖率制品时手动触发 `Unit Tests` workflow,独立的 `Coverage Report` job 会通过 `tests/run.py --serial` 跑串行全量并上传 JSON / XML 报告。
|
||||||
- 复现 CI 使用 `uv sync --locked`;主程序运行依赖位于 `[project].dependencies`,pytest 与覆盖率工具位于默认 `dev` 依赖组。
|
- 复现 CI 使用 `uv sync --locked`;主程序运行依赖位于 `[project].dependencies`,pytest 与覆盖率工具位于默认 `dev` 依赖组。
|
||||||
|
|||||||
@@ -53,8 +53,20 @@ def test_official_plugin_observation_is_scheduled_and_never_writes_fixture():
|
|||||||
|
|
||||||
|
|
||||||
def test_pylint_workflow_runs_for_v3_pull_requests_and_pushes():
|
def test_pylint_workflow_runs_for_v3_pull_requests_and_pushes():
|
||||||
"""严重 Python 静态错误检查不能继续只依赖手工触发。"""
|
"""改动文件应硬门禁,而全仓存量问题只能生成建议性报告。"""
|
||||||
workflow = _load_workflow("pylint.yml")
|
workflow = _load_workflow("pylint.yml")
|
||||||
|
commands = _step_commands(workflow, "pylint")
|
||||||
|
|
||||||
assert workflow["on"]["pull_request"]["branches"] == ["v3"]
|
assert workflow["on"]["pull_request"]["branches"] == ["v3"]
|
||||||
assert workflow["on"]["push"]["branches"] == ["v3"]
|
assert workflow["on"]["push"]["branches"] == ["v3"]
|
||||||
|
assert "changed-python-files.txt" in commands
|
||||||
|
assert "xargs uv run --locked --no-sync pylint" in commands
|
||||||
|
assert "pylint app/" in commands
|
||||||
|
assert "--output-format=json > pylint-report.json || true" in commands
|
||||||
|
|
||||||
|
full_report_step = next(
|
||||||
|
step
|
||||||
|
for step in workflow["jobs"]["pylint"]["steps"]
|
||||||
|
if step.get("name") == "Generate full advisory report"
|
||||||
|
)
|
||||||
|
assert "|| true" in full_report_step["run"]
|
||||||
|
|||||||
Reference in New Issue
Block a user