mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-31 20:34:48 +08:00
ci: gate v3 release on version value changes (#7052)
Co-authored-by: DDSRem <1448139087@qq.com>
This commit is contained in:
42
.github/workflows/build-v3.yml
vendored
42
.github/workflows/build-v3.yml
vendored
@@ -12,7 +12,49 @@ permissions:
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
release-gate:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
publish: ${{ steps.detect.outputs.publish }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Detect version change
|
||||
id: detect
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
BEFORE_SHA: ${{ github.event.before }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "$EVENT_NAME" = workflow_dispatch ]; then
|
||||
echo "publish=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
versions() {
|
||||
sed -nE "s/^(APP_VERSION|FRONTEND_VERSION)[[:space:]]*=[[:space:]]*'([^']+)'[[:space:]]*$/\1=\2/p" | sort
|
||||
}
|
||||
previous=$(git show "$BEFORE_SHA:version.py" | versions)
|
||||
current=$(versions < version.py)
|
||||
for value in APP_VERSION FRONTEND_VERSION; do
|
||||
if ! printf '%s\n' "$previous" | grep -q "^${value}=" ||
|
||||
! printf '%s\n' "$current" | grep -q "^${value}="; then
|
||||
echo "版本声明缺失: $value" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if [ "$previous" = "$current" ]; then
|
||||
echo "publish=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "publish=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
Docker-build:
|
||||
needs: release-gate
|
||||
if: needs.release-gate.outputs.publish == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
name: Build Docker Image
|
||||
steps:
|
||||
|
||||
@@ -215,6 +215,8 @@ uvx --from pip-audit pip-audit \
|
||||
Docker 镜像直接基于官方基础镜像构建,只安装应用运行所需的系统依赖;不运行镜像漏洞扫描,
|
||||
也不为扫描结果刷新系统包、删除基础镜像自带工具或维护漏洞忽略清单。正式版和 Beta 均直接构建
|
||||
并发布标准版与 free-threaded 版的双架构镜像。应用锁定依赖仍按上述流程审计。
|
||||
`v3` 分支自动发布仅在 `version.py` 的 `APP_VERSION` 或 `FRONTEND_VERSION` 值发生变化时运行;
|
||||
只修改该文件的说明文字不会重建正式镜像。维护者仍可通过手动触发正式发布工作流重建当前版本。
|
||||
|
||||
### 6. Contributor 提交准备
|
||||
|
||||
|
||||
@@ -403,6 +403,52 @@ def test_publish_refreshes_base_and_preserves_build_cache() -> None:
|
||||
assert "scope=moviepilot-v3-standard-docker," in publish["cache-to"]
|
||||
|
||||
|
||||
def test_release_gate_only_publishes_changed_versions(tmp_path: Path) -> None:
|
||||
"""
|
||||
自动发布只接受版本值变化,手动重建保留入口。
|
||||
"""
|
||||
workflow = _load_workflow()
|
||||
gate = workflow["jobs"]["release-gate"]
|
||||
build = workflow["jobs"]["Docker-build"]
|
||||
assert build["needs"] == "release-gate"
|
||||
assert build["if"] == "needs.release-gate.outputs.publish == 'true'"
|
||||
|
||||
repo = tmp_path / "repo"
|
||||
repo.mkdir()
|
||||
subprocess.run(["git", "init", "-q", str(repo)], check=True)
|
||||
version_file = repo / "version.py"
|
||||
version_file.write_text(
|
||||
"APP_VERSION = 'v3.1.6'\nFRONTEND_VERSION = 'v3.1.6'\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
subprocess.run(["git", "-C", str(repo), "add", "version.py"], check=True)
|
||||
subprocess.run(
|
||||
["git", "-C", str(repo), "-c", "user.name=Test", "-c", "user.email=test@example.com",
|
||||
"commit", "-qm", "base"],
|
||||
check=True,
|
||||
)
|
||||
before_sha = subprocess.check_output(
|
||||
["git", "-C", str(repo), "rev-parse", "HEAD"], text=True
|
||||
).strip()
|
||||
command = next(step for step in gate["steps"] if step.get("id") == "detect")["run"]
|
||||
output_file = tmp_path / "output"
|
||||
|
||||
def detect(event_name: str, content: str) -> str:
|
||||
version_file.write_text(content, encoding="utf-8")
|
||||
output_file.write_text("", encoding="utf-8")
|
||||
subprocess.run(
|
||||
["bash", "-e", "-c", command], cwd=repo, check=True,
|
||||
env={**os.environ, "EVENT_NAME": event_name, "BEFORE_SHA": before_sha,
|
||||
"GITHUB_OUTPUT": str(output_file)},
|
||||
)
|
||||
return output_file.read_text(encoding="utf-8").strip()
|
||||
|
||||
assert detect("push", "\"\"\"说明文字\"\"\"\nAPP_VERSION = 'v3.1.6'\nFRONTEND_VERSION = 'v3.1.6'\n") == "publish=false"
|
||||
assert detect("push", "APP_VERSION = 'v3.1.7'\nFRONTEND_VERSION = 'v3.1.6'\n") == "publish=true"
|
||||
assert detect("push", "APP_VERSION = 'v3.1.6'\nFRONTEND_VERSION = 'v3.1.7'\n") == "publish=true"
|
||||
assert detect("workflow_dispatch", "APP_VERSION = 'v3.1.6'\nFRONTEND_VERSION = 'v3.1.6'\n") == "publish=true"
|
||||
|
||||
|
||||
def test_release_publishes_free_threaded_image_with_separate_metadata_and_cache() -> None:
|
||||
"""
|
||||
free-threaded 发布必须使用 v3t 命名、参数和独立缓存。
|
||||
|
||||
Reference in New Issue
Block a user