mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-10-30 20:05:42 +08:00
build(docker): refresh system packages against a tracked baseline
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
committed by
InfinityPacer
parent
a76fc9f579
commit
cba9779a8a
25
.github/workflows/beta.yml
vendored
25
.github/workflows/beta.yml
vendored
@@ -106,6 +106,27 @@ jobs:
|
||||
echo "digest=sha256:$(sha256sum app/agent/llm/resources/models.json | awk '{print $1}')" >> "$GITHUB_OUTPUT"
|
||||
echo "Downloaded models.dev catalog ($(wc -c < app/agent/llm/resources/models.json) bytes)"
|
||||
|
||||
- name: Resolve System Refresh Key
|
||||
id: system_refresh
|
||||
run: |
|
||||
# 刷新键决定镜像末尾系统安全更新层何时重建:每 ISO 周最多一次,
|
||||
# docker/system-baseline 变化时立即重建。计算失败只降级为基线值,不阻断发布。
|
||||
baseline=$(tr -d '[:space:]' < docker/system-baseline 2>/dev/null || true)
|
||||
if ! [[ "$baseline" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
|
||||
echo "::warning::docker/system-baseline 缺失或格式无效,系统基线记为 unknown"
|
||||
baseline=unknown
|
||||
fi
|
||||
week=$(date -u +%G-W%V 2>/dev/null || true)
|
||||
if [[ "$week" =~ ^[0-9]{4}-W[0-9]{2}$ ]]; then
|
||||
key="${week}-${baseline}"
|
||||
else
|
||||
echo "::warning::无法计算 ISO 周,系统刷新键仅使用系统基线"
|
||||
key="${baseline}"
|
||||
fi
|
||||
echo "System refresh key: ${key}"
|
||||
echo "baseline=${baseline}" >> "$GITHUB_OUTPUT"
|
||||
echo "key=${key}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Docker Meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
@@ -162,8 +183,10 @@ jobs:
|
||||
MOVIEPILOT_PLUGINS_REF=${{ steps.payloads.outputs.plugins_revision }}
|
||||
MOVIEPILOT_RESOURCES_REF=${{ steps.payloads.outputs.resources_revision }}
|
||||
MOVIEPILOT_PYTHON_VARIANT=standard
|
||||
MOVIEPILOT_SYSTEM_REFRESH_ID=${{ steps.system_refresh.outputs.key }}
|
||||
labels: |
|
||||
${{ steps.meta.outputs.labels }}
|
||||
org.moviepilot.system-baseline=${{ steps.system_refresh.outputs.baseline }}
|
||||
org.opencontainers.image.revision=${{ env.SOURCE_COMMIT }}
|
||||
org.moviepilot.source-revision=${{ env.SOURCE_COMMIT }}
|
||||
org.moviepilot.frontend-version=${{ steps.release_version.outputs.frontend_version }}
|
||||
@@ -195,8 +218,10 @@ jobs:
|
||||
MOVIEPILOT_PLUGINS_REF=${{ steps.payloads.outputs.plugins_revision }}
|
||||
MOVIEPILOT_RESOURCES_REF=${{ steps.payloads.outputs.resources_revision }}
|
||||
MOVIEPILOT_PYTHON_VARIANT=free-threaded
|
||||
MOVIEPILOT_SYSTEM_REFRESH_ID=${{ steps.system_refresh.outputs.key }}
|
||||
labels: |
|
||||
${{ steps.meta_ft.outputs.labels }}
|
||||
org.moviepilot.system-baseline=${{ steps.system_refresh.outputs.baseline }}
|
||||
org.opencontainers.image.revision=${{ env.SOURCE_COMMIT }}
|
||||
org.moviepilot.source-revision=${{ env.SOURCE_COMMIT }}
|
||||
org.moviepilot.frontend-version=${{ steps.release_version.outputs.frontend_version }}
|
||||
|
||||
25
.github/workflows/build-v3.yml
vendored
25
.github/workflows/build-v3.yml
vendored
@@ -172,6 +172,27 @@ jobs:
|
||||
fi
|
||||
echo "release_commit=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Resolve System Refresh Key
|
||||
id: system_refresh
|
||||
run: |
|
||||
# 刷新键决定镜像末尾系统安全更新层何时重建:每 ISO 周最多一次,
|
||||
# docker/system-baseline 变化时立即重建。计算失败只降级为基线值,不阻断发布。
|
||||
baseline=$(tr -d '[:space:]' < docker/system-baseline 2>/dev/null || true)
|
||||
if ! [[ "$baseline" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
|
||||
echo "::warning::docker/system-baseline 缺失或格式无效,系统基线记为 unknown"
|
||||
baseline=unknown
|
||||
fi
|
||||
week=$(date -u +%G-W%V 2>/dev/null || true)
|
||||
if [[ "$week" =~ ^[0-9]{4}-W[0-9]{2}$ ]]; then
|
||||
key="${week}-${baseline}"
|
||||
else
|
||||
echo "::warning::无法计算 ISO 周,系统刷新键仅使用系统基线"
|
||||
key="${baseline}"
|
||||
fi
|
||||
echo "System refresh key: ${key}"
|
||||
echo "baseline=${baseline}" >> "$GITHUB_OUTPUT"
|
||||
echo "key=${key}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Docker Meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
@@ -231,8 +252,10 @@ jobs:
|
||||
MOVIEPILOT_PLUGINS_REF=${{ steps.payloads.outputs.plugins_revision }}
|
||||
MOVIEPILOT_RESOURCES_REF=${{ steps.payloads.outputs.resources_revision }}
|
||||
MOVIEPILOT_PYTHON_VARIANT=standard
|
||||
MOVIEPILOT_SYSTEM_REFRESH_ID=${{ steps.system_refresh.outputs.key }}
|
||||
labels: |
|
||||
${{ steps.meta.outputs.labels }}
|
||||
org.moviepilot.system-baseline=${{ steps.system_refresh.outputs.baseline }}
|
||||
org.opencontainers.image.revision=${{ steps.release_snapshot.outputs.release_commit }}
|
||||
org.moviepilot.source-revision=${{ env.SOURCE_COMMIT }}
|
||||
org.moviepilot.release-snapshot-revision=${{ steps.release_snapshot.outputs.release_commit }}
|
||||
@@ -265,8 +288,10 @@ jobs:
|
||||
MOVIEPILOT_PLUGINS_REF=${{ steps.payloads.outputs.plugins_revision }}
|
||||
MOVIEPILOT_RESOURCES_REF=${{ steps.payloads.outputs.resources_revision }}
|
||||
MOVIEPILOT_PYTHON_VARIANT=free-threaded
|
||||
MOVIEPILOT_SYSTEM_REFRESH_ID=${{ steps.system_refresh.outputs.key }}
|
||||
labels: |
|
||||
${{ steps.meta_ft.outputs.labels }}
|
||||
org.moviepilot.system-baseline=${{ steps.system_refresh.outputs.baseline }}
|
||||
org.opencontainers.image.revision=${{ steps.release_snapshot.outputs.release_commit }}
|
||||
org.moviepilot.source-revision=${{ env.SOURCE_COMMIT }}
|
||||
org.moviepilot.release-snapshot-revision=${{ steps.release_snapshot.outputs.release_commit }}
|
||||
|
||||
@@ -367,6 +367,23 @@ RUN mkdir -p ${HOME} \
|
||||
&& echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen \
|
||||
&& locale-gen zh_CN.UTF-8
|
||||
|
||||
# 系统安全更新层:放在所有大层之后、--link 载荷层之前,刷新时只重建这一小层。
|
||||
# CI 传入 "<ISO 年-周>-<系统基线>" 作为刷新键,每周最多重建一次;docker/system-baseline
|
||||
# 变化时 COPY 内容变化,同样立即重建。未传键的本地构建按普通缓存规则复用。
|
||||
# 基线文件写入镜像,供应用内更新判断当前镜像是否满足目标版本的 MIN_SYSTEM_BASELINE。
|
||||
ARG MOVIEPILOT_SYSTEM_REFRESH_ID=""
|
||||
COPY docker/system-baseline /etc/moviepilot/system-baseline
|
||||
RUN set -eu; \
|
||||
printf 'System refresh key: %s, baseline: %s\n' \
|
||||
"${MOVIEPILOT_SYSTEM_REFRESH_ID:-unset}" "$(cat /etc/moviepilot/system-baseline)"; \
|
||||
apt-get update; \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get -y --no-install-recommends \
|
||||
-o Dpkg::Options::=--force-confdef \
|
||||
-o Dpkg::Options::=--force-confold \
|
||||
upgrade; \
|
||||
apt-get clean; \
|
||||
rm -rf /var/lib/apt/lists/* /var/tmp/*
|
||||
|
||||
# 载荷按独立更新频率写入镜像,后端源码保持在最后一层。
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
1
docker/system-baseline
Normal file
1
docker/system-baseline
Normal file
@@ -0,0 +1 @@
|
||||
2026-10-22
|
||||
@@ -71,6 +71,8 @@ ci: improve docker build cache
|
||||
- The primary Docker image bundles the backend (Python app), frontend static files (from `public/`), and resource data.
|
||||
- Docker build and release are managed by CI. Do not manually trigger or alter the Docker release flow unless the task explicitly requires it.
|
||||
- If a Dockerfile change is needed, update `Dockerfile` and verify the build locally before submitting.
|
||||
- The image ends with a small system security update layer. CI rebuilds it at most once per ISO week; changing the ISO date in `docker/system-baseline` rebuilds it immediately and stamps the new date into `/etc/moviepilot/system-baseline`.
|
||||
- `MIN_SYSTEM_BASELINE` in `version.py` is the oldest image baseline that may install this release through the in-app or Dev updater. Raise it only for severe system-level vulnerabilities, and set it to the same date as `docker/system-baseline` in that release. Older Docker images then refuse the update and ask the user to pull the new image.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -119,15 +119,21 @@ def _run_release_script(
|
||||
)
|
||||
|
||||
|
||||
def test_base_image_uses_refreshable_tag_and_apt_does_not_upgrade_in_place() -> None:
|
||||
def test_base_image_uses_refreshable_tag_and_upgrades_only_in_refresh_layer() -> None:
|
||||
"""
|
||||
使用官方基础镜像及所需运行依赖,不追加系统包扫描补丁。
|
||||
使用官方基础镜像及所需运行依赖,不追加针对扫描结果的逐包补丁;
|
||||
系统包只在 final 末尾由刷新键控制的系统安全更新层统一升级。
|
||||
"""
|
||||
dockerfile = DOCKERFILE.read_text(encoding="utf-8")
|
||||
assert 'ARG MOVIEPILOT_PYTHON_VERSION="3.14.7"' in dockerfile
|
||||
assert "FROM python:${MOVIEPILOT_PYTHON_VERSION}-slim-trixie AS base" in dockerfile
|
||||
assert 'uv python install --no-bin "${MOVIEPILOT_PYTHON_VERSION}t"' in dockerfile
|
||||
assert "apt-get upgrade" not in dockerfile
|
||||
assert dockerfile.count("upgrade;") == 1
|
||||
assert "dist-upgrade" not in dockerfile
|
||||
refresh_layer = dockerfile.split('ARG MOVIEPILOT_SYSTEM_REFRESH_ID=""', maxsplit=1)[1]
|
||||
assert "upgrade;" in refresh_layer
|
||||
assert "apt-get install" not in refresh_layer
|
||||
assert "pip uninstall" not in dockerfile
|
||||
assert "break-system-packages" not in dockerfile
|
||||
browser_install = dockerfile.split("python -m playwright install-deps chromium", maxsplit=1)[1]
|
||||
|
||||
Reference in New Issue
Block a user