fix: replace vulnerable container bases and release v0.1.21
This commit is contained in:
+1
-2
@@ -28,5 +28,4 @@ SYNOLOGY_PHOTOS_CERT_SHA256=
|
||||
|
||||
# Build-only mirror hosts; official defaults work outside mainland China.
|
||||
# For mainland NAS builds: source ./deploy/build-cn.env before build-verify.sh.
|
||||
DEBIAN_MIRROR=deb.debian.org
|
||||
DEBIAN_SECURITY_MIRROR=deb.debian.org
|
||||
ALPINE_MIRROR=dl-cdn.alpinelinux.org
|
||||
|
||||
@@ -15,8 +15,7 @@ jobs:
|
||||
DOCKER_PIP_FALLBACK_INDEX_URL: ${{ vars.DOCKER_PIP_FALLBACK_INDEX_URL }}
|
||||
CI_PIP_INDEX_URL: ${{ vars.CI_PIP_INDEX_URL }}
|
||||
CI_PIP_FALLBACK_INDEX_URL: ${{ vars.CI_PIP_FALLBACK_INDEX_URL }}
|
||||
DEBIAN_MIRROR: ${{ vars.DEBIAN_MIRROR }}
|
||||
DEBIAN_SECURITY_MIRROR: ${{ vars.DEBIAN_SECURITY_MIRROR }}
|
||||
ALPINE_MIRROR: ${{ vars.ALPINE_MIRROR }}
|
||||
steps:
|
||||
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
- uses: https://github.com/actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
||||
|
||||
@@ -16,8 +16,6 @@ dist/
|
||||
|
||||
.mypy_cache/
|
||||
|
||||
build-cache/debs/*
|
||||
!build-cache/debs/.gitkeep
|
||||
build-cache/wheels/*
|
||||
!build-cache/wheels/.gitkeep
|
||||
|
||||
|
||||
+11
-22
@@ -1,36 +1,24 @@
|
||||
ARG PYTHON_BASE=python:3.14.5-slim-bookworm@sha256:ec58d916f9e24a6035cab2bdf07f6206c4cc092a16613c60597534711332d9d6
|
||||
ARG PYTHON_BASE=python:3.14.8-alpine3.24@sha256:f6a589d43c42b9e7f7dc67a12d37132491f362859a5d750607710cc56da3bc72
|
||||
FROM ${PYTHON_BASE} AS prepared
|
||||
ARG DEBIAN_MIRROR=deb.debian.org
|
||||
ARG DEBIAN_SECURITY_MIRROR=deb.debian.org
|
||||
ARG ALPINE_MIRROR=dl-cdn.alpinelinux.org
|
||||
ARG TARGETARCH
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 TZ=Asia/Shanghai \
|
||||
DATA_DIR=/data CONFIG_DIR=/config
|
||||
WORKDIR /app
|
||||
# CJK fonts intentionally retained for readable Chinese rendering.
|
||||
RUN --mount=type=cache,id=frameflow-bookworm-apt-${TARGETARCH},target=/var/cache/apt,sharing=locked \
|
||||
--mount=type=cache,id=frameflow-bookworm-lists-${TARGETARCH},target=/var/lib/apt/lists,sharing=locked \
|
||||
--mount=type=bind,source=build-cache/debs,target=/build-debs,readonly \
|
||||
rm -f /etc/apt/apt.conf.d/docker-clean \
|
||||
&& printf 'Binary::apt::APT::Keep-Downloaded-Packages "true";\n' > /etc/apt/apt.conf.d/keep-cache \
|
||||
&& sed -i "s|http://deb.debian.org/debian-security|https://${DEBIAN_SECURITY_MIRROR}/debian-security|g; s|http://deb.debian.org/debian|https://${DEBIAN_MIRROR}/debian|g" /etc/apt/sources.list.d/debian.sources \
|
||||
&& apt-get -o Acquire::Retries=3 -o Acquire::https::Timeout=60 update \
|
||||
&& apt-get -y --no-install-recommends upgrade \
|
||||
&& if [ -f /build-debs/fonts-noto-cjk.deb ]; then \
|
||||
font_version=$(apt-cache policy fonts-noto-cjk | awk '$1=="Candidate:" {print $2}'); \
|
||||
font_sha=$(apt-cache show "fonts-noto-cjk=$font_version" | awk '$1=="SHA256:" {print $2;exit}'); \
|
||||
test -n "$font_sha"; \
|
||||
echo "$font_sha /build-debs/fonts-noto-cjk.deb" | sha256sum -c -; \
|
||||
apt-get install -y --no-install-recommends tzdata; \
|
||||
dpkg -i /build-debs/fonts-noto-cjk.deb; \
|
||||
else apt-get install -y --no-install-recommends fonts-noto-cjk tzdata; fi \
|
||||
&& groupadd --gid 10333 frameflow && useradd --uid 10333 --gid 10333 --no-create-home frameflow \
|
||||
# Preserve the existing FONT_PATH contract for deployments and Chinese rendering.
|
||||
RUN sed -i "s|https://dl-cdn.alpinelinux.org/alpine|https://${ALPINE_MIRROR}/alpine|g" /etc/apk/repositories \
|
||||
&& apk upgrade --no-cache \
|
||||
&& apk add --no-cache font-noto-cjk tzdata \
|
||||
&& mkdir -p /usr/share/fonts/opentype/noto \
|
||||
&& ln -s /usr/share/fonts/noto/NotoSansCJK-Regular.ttc /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc \
|
||||
&& addgroup -g 10333 frameflow && adduser -D -H -u 10333 -G frameflow frameflow \
|
||||
&& mkdir -p /data/images /data/generated /data/cache /config \
|
||||
&& chown -R 10333:10333 /data /config
|
||||
COPY requirements.lock ./
|
||||
COPY scripts/ci-install.py /build-tools/install.py
|
||||
ARG DOCKER_PIP_INDEX_URL=https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
|
||||
ARG DOCKER_PIP_FALLBACK_INDEX_URL=https://pypi.org/simple
|
||||
RUN --mount=type=cache,id=frameflow-pip-py314-${TARGETARCH},target=/root/.cache/pip,sharing=locked \
|
||||
RUN --mount=type=cache,id=frameflow-pip-py314-musl-${TARGETARCH},target=/root/.cache/pip,sharing=locked \
|
||||
--mount=type=bind,source=build-cache/wheels,target=/build-wheels,readonly \
|
||||
if [ -f /build-wheels/SHA256SUMS ]; then \
|
||||
(cd /build-wheels && sha256sum -c SHA256SUMS) \
|
||||
@@ -55,6 +43,7 @@ WORKDIR /app
|
||||
ARG BUILD_COMMIT=development
|
||||
ARG BUILD_TIME=unknown
|
||||
ENV BUILD_COMMIT=$BUILD_COMMIT BUILD_TIME=$BUILD_TIME
|
||||
LABEL org.opencontainers.image.title="PIGWay Frame Flow" org.opencontainers.image.version="0.1.21" org.opencontainers.image.revision=$BUILD_COMMIT
|
||||
USER 10333:10333
|
||||
EXPOSE 18787
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
||||
|
||||
@@ -21,7 +21,8 @@ for endpoint coverage. Their source code was not incorporated into runtime.
|
||||
|
||||
FastAPI, Starlette, Uvicorn, Requests, croniter, PyYAML, Pydantic and their transitive
|
||||
dependencies retain their respective upstream licenses. Pillow uses its upstream
|
||||
HPND license. Debian Noto CJK fonts retain their font package license.
|
||||
HPND license. Noto CJK fonts use SIL OFL 1.1; the license is included in
|
||||
`vendor/noto-cjk-OFL-1.1.txt`, with copyright notices retained in font metadata.
|
||||
Development dependencies (pytest, Ruff, mypy, pip-audit, HTTPX2, Playwright) retain
|
||||
their upstream licenses and are not shipped in the runtime image.
|
||||
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
# pigway-frame-flow v0.1.20
|
||||
# pigway-frame-flow v0.1.21
|
||||
|
||||
统一开源许可证、贡献和安全反馈入口;完善当前版本的文档导航、源码分发和校验和。插件 ZIP 携带许可证。运行功能边界保持项目首页所述。
|
||||
基础映像改为固定摘要的官方 Python 3.14 Alpine 3.24,并应用系统安全更新,移除 Debian 基础系统遗留告警。保留原字体路径、中文字体、时区和第三方许可。
|
||||
|
||||
本轮 585 项 Python 测试通过。源码语法、文档入口、打包和校验和检查通过;生产运行状态以实际部署验收为准。
|
||||
发布脚本统一从完整 Dockerfile 构建,避免复用旧运行映像继续携带漏洞;版本标签读取项目元数据。移除旧 Debian 离线字体缓存和运行映像覆盖构建方式,同步构建参数与文档。
|
||||
|
||||
Ruff、格式、mypy、25 项锁定依赖的漏洞检查通过;AMD64 Docker 构建和两轮隔离启动/重启只读冒烟验证通过。
|
||||
585 项测试、Ruff、格式和 mypy 通过。AMD64 容器启动/重启、只读接口及中文实际字形和 PNG 渲染验证通过。Trivy 0.76.0 扫描系统包和全部 25 项 Python 运行依赖,各严重级别均未检出已知漏洞;结论限于 2026-10-18 漏洞库快照。
|
||||
|
||||
Docker 构建增加发行版安全更新,清除可修复系统包告警;仍有上游未修复包级告警,分析及默认部署边界见 [安全说明](SECURITY.md),不宣称映像零漏洞。
|
||||
生产升级须通过现有挂载身份校验和部署流程完成,发布源码不等同于生产升级。
|
||||
|
||||
+3
-7
@@ -14,12 +14,8 @@ A useful private report includes the affected version, deployment mode, required
|
||||
permissions, impact, and minimal steps using mock data. Do not test on another
|
||||
person's deployment or write to real frames without explicit authorization.
|
||||
|
||||
## 当前容器基础系统扫描
|
||||
## 当前容器映像检查
|
||||
|
||||
2026-10-18 使用 Trivy 0.76.0 扫描当前映像。在构建阶段应用 Debian 安全更新后,可修复的 HIGH/CRITICAL 项已清除;仍有 63 条发行版包级告警,合并为 16 个 CVE,当前 Bookworm 无可用修复版本。不能将 Python 依赖检查通过描述为整个映像零漏洞。
|
||||
v0.1.21 使用官方 Python Alpine 3.24 基础映像并固定摘要,构建时应用 APK 安全更新。2026-10-18 使用 Trivy 0.76.0 扫描构建的 Linux AMD64 映像,涵盖操作系统和 Python 包、全部严重级别,未检出已知漏洞;未配置漏洞忽略规则。该结果是当日漏洞库快照,不是未来无漏洞的保证,也不代表旧运行容器已升级。
|
||||
|
||||
- [CVE-2023-45853](https://security-tracker.debian.org/tracker/CVE-2023-45853) 针对 MiniZip;Debian 明确 Bookworm 的 zlib 未构建相应代码,本映像也未安装 MiniZip。
|
||||
- [CVE-2025-7458](https://security-tracker.debian.org/tracker/CVE-2025-7458) 需要攻击者执行特制 SQL;Frame Flow 不接受任意 SQL 或上传外部 SQLite 数据库。FTS5 相关 [CVE-2026-11822](https://security-tracker.debian.org/tracker/CVE-2026-11822)、[CVE-2026-11824](https://security-tracker.debian.org/tracker/CVE-2026-11824) 的匹配查询也未被应用使用。此结论不适用于自行替换数据库或修改服务 SQL 的部署。
|
||||
- 其他告警涉及挂载/命名空间工具、systemd-homed、ACL、ncurses、Perl/LZH CLI 及 DTLS;应用未调用这些路径。默认 UID/GID 10333、只读根目录、清空 capabilities、禁提权和独立数据卷仍是必要边界。
|
||||
|
||||
本轮未发现这些遗留项在默认应用路径中的可达利用入口,不将该判断扩展为基础系统已修复。后续基础映像更新仍须复扫;不得为消除扫描数字而混装其他 Debian 发行版包或删除许可声明。
|
||||
基础映像更新后须重新构建并复扫。默认非 root、只读根目录、清空 capabilities 和 no-new-privileges 的部署限制继续保留。中文字体、第三方许可证和依赖元数据均保留;不以删除包清单掩盖告警。
|
||||
|
||||
+21
-22
@@ -1,48 +1,46 @@
|
||||
c2792b2c75880ff09822804632b1b3b6dd6190b38841b8c3567bb1b7e7b59a8c .dockerignore
|
||||
fe4b8e57c14d6f4df261de0ec274f33153def558227a47f38c3f91d5cfc77f80 .env.example
|
||||
d20031a8e861a0f3e19b7750ddb53bc84c480c469c44a70ecdf8261ec05431c0 .env.example
|
||||
0c7f4585d62a8d35bfc22e0bebdf7a479a179122b2b092bfe434e3038cddd3d5 .gitattributes
|
||||
b45d35d737f119a70bf40cb1f9626ff80772ed7913cb35f6e9b870d6ada01a15 .github/workflows/community.yml
|
||||
c93afa220096b0a3a27115e74617db9dbe97e98c6a3735a0abfb528cdca7e668 .github/workflows/verify.yml
|
||||
342242379194ca16021542722407a42858f22685293d16162d0e6fe004cbd62c .gitignore
|
||||
d3ad09bdc5dc60c41a774e1cad43f3e3f8ae5c851303ae6ec2aac030392a2939 .github/workflows/verify.yml
|
||||
3931cc314019760a582e0914e2d9c0f3b862a004d0a30d374900edcad5f599e5 .gitignore
|
||||
4b4ed4926a350cbeb71436541b4566e4ba7d2494ac95236b88827a9f5dd171c2 CONTRIBUTING.md
|
||||
6588694aee24d5e662061be78027a049f6726d50dd99ef00a60fba05051ef299 Dockerfile
|
||||
660c76fccccae8643633d052d0d6733ecf278f2a3016de29e6850b312a365413 Dockerfile
|
||||
6eb7728e6e73f9568ca6fd5ad6383d13ffc638f2870fefa2d86f72f39685c0fc LICENSE
|
||||
ef0d1ecd6427325fc92324032fbf7b880624a68629acbaf430cd8be80c73b698 NOTICE.md
|
||||
250a2bcec248b074786d90e0329874628d70d5a0fe3b4fba47c8c57d4f84dcce NOTICE.md
|
||||
26ad0d9063c0ee843f0f532604b8fd66e8b39fd72d129595ed078677c0d6d13c README.md
|
||||
ee00cb267b38485f1e574d610f0a57b51d4ae575731a18e57d06a7c43dc0a8b0 README.zh-CN.md
|
||||
3c0ab38958a3bdb17ee95b5642c2ee691affc3da44252a5c4a3048ebf7860fe4 RELEASE_NOTES.md
|
||||
d1233db9c8da6d391028e1e515813cd45ce8d8f97e48087daa325a61789987bc SECURITY.md
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 build-cache/debs/.gitkeep
|
||||
304bec983ac8242107b1ec4154522f451a5d33b6a77ed26669926cb3e161f863 RELEASE_NOTES.md
|
||||
6a0c85c8d52a2d4a3b779dce306a93c4efc4dfe3ab3b23e4a6a3bb7c55079910 SECURITY.md
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 build-cache/wheels/.gitkeep
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 config/.gitkeep
|
||||
a897bf4a9f95f3e7b96b286a4bf7d124bb4a50fd47a16c6a3d9fbb70bce47f15 deploy/Dockerfile.runtime-update
|
||||
4cc0b0813f527ac0ca311993f791005de5c8e89e6810ecbf5cf058e58e2fe572 deploy/build-cn.env
|
||||
dff739157875c8a70235c4994df868afc6824e0d3861b2716ac28014bb38144f deploy/build-cn.env
|
||||
3683a3cfb63f08cc9e6144162117ab68c607d38bdeaae0e82cb418e812a450f2 deploy/compose.ubuntu-photos-api.yml
|
||||
d68d727e01c592c098fde71a900bcdd234a9ca6610d0799019a6f585983b4494 deploy/devices.yml.example
|
||||
fd53125a5359dcae1d81e95b8447aac755270f9aeb354d3e1140d7fccb57c42e deploy/docker-compose.photos.yml
|
||||
4464545a9d91bbc9fff9cd9941db63f44fa61120caca426687d1ed06635cc3e6 deploy/organized-photos-source.json
|
||||
582dae3db4a08192d714e81e5e8234b170b4ac4231faf251b2c26eeec54f0942 docker-compose.yml
|
||||
f78d6c3d40e6c5246601bb99c2b46eef91e883a8f83841d85c925394708af0c0 docker-compose.yml
|
||||
30d3e705870ebb012ce122bd7d8f95192d86664c4d2bb45a3169c86988fbaf72 docs/AUTOMATIC_COLLAGE.md
|
||||
6b602b686db5b25060f91cfecf05a840a09ee5b2a6d5099636cb3f47880a4a4d docs/BUILDING.md
|
||||
c14983d5c65775ad80244fcbb77fe5c0c4a413cc27945b7184bbc923a53d38a8 docs/EXTENSIONS.md
|
||||
5f727c9588504a18009ea892f3204fce9520b03754a56dbc9f59e3505ce8a1b2 docs/BUILDING.md
|
||||
d9f07164c75c757e85f4ace2b55deaf82b8b904216c5222be6c0e3ab7b28cb36 docs/EXTENSIONS.md
|
||||
1d8c5f79eff3115b1cd13d8f63fff1332b80d1fe1bec6b0f2713b5f80b0cbf67 docs/KOKONNA_RECOVERY.md
|
||||
3b4d24d633dea8474a6a7b8868c5afdd37a5205df32356d3967cf838bcafdba9 docs/NAS.md
|
||||
0fe1896a53cef4cfd2e380a0b979eceda493733082a9b56c3d7e89e7f62a65b3 docs/NAS.md
|
||||
3280bddcbe2d2721bb7efeb0eb2ec03d9d5ef867c69f3e70066b69f1ad5926e2 docs/PHOTO_SOURCES.md
|
||||
edf44436fd044561539c48480c481e66c1a38164f51ba5226cde04c756f7bacb docs/PHOTO_SOURCE_CONNECTIONS.md
|
||||
4b00d08eb5a2425b205af13b87f9be04dd6870a734b42463a3e075658039dac9 docs/PUBLICATION.md
|
||||
5fe4641e75e0746929f71256c6ff11116c777cca8d4288ccc2d7aee91bd7a6ac docs/README.md
|
||||
5eb19e7e4ed1ceddbdf388fd55697e40f1b7ecd9a4fbdf8ab485132cc684dcb2 docs/REAL_DEVICE_TEST.md
|
||||
bfc38b889fa966031e195c3131db1d4a713e0dc35c644e3047c7ed94f2354700 docs/RESEARCH.md
|
||||
6772ddfd79b28bb52ce469e40188f8781f66275bdf4b84861f81c32a87aea6eb docs/SYNOLOGY_PHOTOS_API.md
|
||||
fac36f986e1a7a331d3669aa8e2013e6c0ea7a99c16a61ba3ff573e836aa87e1 docs/SYNOLOGY_PHOTOS_API.md
|
||||
ac0481196e593ff9cca2e5133ff41fb3614268e6a10728a0deca3ad3bfb80b34 docs/integrations/TICKTAR.md
|
||||
757a4d87aec789054dc5268d314cd218f6d7cab49082cfacef55f9860d2362b0 docs/openapi.json
|
||||
b191be41aec1dab92ff0d2956d32ec6a325b49786ce9051e5299fe20e2b6b62d docs/openapi.json
|
||||
54bf7061e0626900ce35e19e81efc5c32c8fd6a0438bdad68f494e1ce81616d4 docs/research/KOKONNA_ACCOUNT_CAPABILITIES.md
|
||||
a07cbe71571c6e2d5a1b94897bd63321c74675c05d15438c4964eef39db0fd76 docs/research/KOKONNA_CONTENT_SUBSCRIPTIONS.md
|
||||
ec53d587b855be84283c50f8fb45be62a4c1caba78b28d436a8260fd171943a2 docs/research/KOKONNA_LOCAL_CONTROL.md
|
||||
2a68fe95ba4afc24aec6abd3e6ab24a360eb6bc3005ab0fefd696190915d76c1 docs/research/KOKONNA_WIDGET_CATALOG.json
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 pigway_frame_flow/__init__.py
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 pigway_frame_flow/api/__init__.py
|
||||
632e8be140d1c206388b84e6e08039fc42d6449e83ea23b58d7a57c3404a8747 pigway_frame_flow/api/app.py
|
||||
06e2e5156383120271ec989b89236bd1baa2d7ba3d6e51b3018de2b23bd39d91 pigway_frame_flow/api/app.py
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 pigway_frame_flow/core/__init__.py
|
||||
fbadf6beaf25b9670dcbf125ec9d192188cf9e076ee4d4a0b5decdaf3834417c pigway_frame_flow/core/accounts.py
|
||||
818e8fb29d22c13159a6cb22bcbc6b9e211a8a1301588126eb192ac4ed71441b pigway_frame_flow/core/auth.py
|
||||
@@ -84,7 +82,7 @@ a518965aa4db9abeb60865c315229c3053c8e9edd26d80f24dc0af0528bad9e6 pigway_frame_f
|
||||
2a68fe95ba4afc24aec6abd3e6ab24a360eb6bc3005ab0fefd696190915d76c1 pigway_frame_flow/integrations/kokonna_official/widget_catalog.json
|
||||
aea594fb4e4c9a6e2094d4d7973eb627ac02fb632811b2d1a558a0ee1cd12e77 pigway_frame_flow/integrations/kokonna_official/widgets.py
|
||||
1fe53f4bfb407b8db774fe730131ecf1213e16d752a3506c4c56b46365ea14e8 pigway_frame_flow/main.py
|
||||
fb41e20b181815a62e213a1d179f6479b155586fc7000c0a103737ddc16b1c83 pigway_frame_flow/models.py
|
||||
0a7a96f84c3c1248eadf80ae412df36c71d308771f9f53512f3fc3c9bc6d5976 pigway_frame_flow/models.py
|
||||
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 pigway_frame_flow/providers/__init__.py
|
||||
b7a6cb8eb40d8dedfbce18777f8fbd433a174f14bcdadf498bd834132aa568fd pigway_frame_flow/providers/cloud_drives.py
|
||||
58b070f0c814d639a4a912d079479d751d459816d59f2199d0be03e4d573ec3b pigway_frame_flow/providers/external.py
|
||||
@@ -122,12 +120,12 @@ c43faa235848bec6370d7a3d8a7b3475cbd8eb4a6e494518dfaf160ca8f77bfa pigway_frame_f
|
||||
d7d55b06ead173b4c23a277fa39800cadfc18f1163c500e8617cfc1f4ee0dea9 pigway_frame_flow/web/extensions.js
|
||||
fe19e508ad60fab0ab4ca61f5d966f8340143e89f1572de00e78b3f1fed8384b pigway_frame_flow/web/features.js
|
||||
3c4e3be6321d40547d45724fc3c54af090ebbbc2a41dec717966596577c72c5d pigway_frame_flow/web/i18n.js
|
||||
0ff0e5c80f6cfb3dc71a63813e01fd8cde5355b0f135a4fbb2781d43383a569f pigway_frame_flow/web/index.html
|
||||
d4518595bc39adfd88d908f98c8c14c02ffbc67a4289003e792b2ceade2838dd pigway_frame_flow/web/index.html
|
||||
0609e796b5ca8346405b1bb6e65ac9f88ee163f7a93024d96d54d4e6ab96ba41 pigway_frame_flow/web/style.css
|
||||
cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 pigway_frame_flow/web/swagger-LICENSE
|
||||
050bc415ee7048dcd881682678f720264e7da5e373f7461d7c58c755305255f7 pigway_frame_flow/web/swagger-ui-bundle.js
|
||||
1ac324f7dcd27e4b9386b4bd6421271ec147e922a22c05ba24b11515e9aa6321 pigway_frame_flow/web/swagger-ui.css
|
||||
a363adb54463d0345cd4e8d0ebe6cac758856e8c0e1d4da49468ddee1ca1aec6 pyproject.toml
|
||||
da96be4eeb3b57f6805ca766919e3899968179f1e7e6a5cb25dbabfd13bc1569 pyproject.toml
|
||||
d34ac82e4c3feacd38546aa2f0a4491ab17ddbf3ad8f489375783166d78923f0 requirements.lock
|
||||
ae264ad19391bb2515def85963f39458cfa75a8611ff54e5329106c35bd8cc6e scripts/build-verify.sh
|
||||
43e8345ac5f29c2a5d1fa751c0e7c963b00b5391817393541e72c52919f0f2b4 scripts/check-compose-remote.py
|
||||
@@ -138,9 +136,9 @@ a11e660a0343f2631c1a3dd0aa28471db827fb1f43d1af4217f51209aa3afe32 scripts/create
|
||||
cdabf30144ea089ae8e64228f6762951f53d4fe8c191673fb5676331d249473d scripts/migrate-photos-api.py
|
||||
80813607835c19d321085fac4cabb17d865d98ed62a09b7f45195ac48bec94a8 scripts/package-nas.py
|
||||
b0b877cfbb2bdf830e2e41097c2057538bb9d0b61a3c39952fe505d910cd5c29 scripts/persistence-check.py
|
||||
3213ef2c17dbcf7423b04440794b842c691dc65616d56c1e1a85dd286ee34ada scripts/production-deploy.py
|
||||
b7247c5590fe17ae461311f2fbdbeda0daa8a34c0804cef22a314c7ff8f4c389 scripts/production-deploy.py
|
||||
11627ecbd8a3be01aa079bdf6166b4368e670f5ad4a165b5971754b8187bbc2c scripts/run_local.py
|
||||
0fe19e94ffa4e9ff56d4f4a079b19f74991b35f0e18679ac793e8de38ecc3833 scripts/server-release.py
|
||||
792dafe1ffb2be6a50aba549e642aa95357469ac1ec94a04bdc93a0f419d5f63 scripts/server-release.py
|
||||
1fc16c43485a60a05012322cb1e4a219309dbd7e11f002f510602beea743ce30 scripts/smoke-test.py
|
||||
1236d3b2d27559cbe73a27dcf56248ef3c60404c6fb21453caa7225570d4ac45 scripts/ui-audit-regressions.cjs
|
||||
57a79a534a71442f5e3a70ed9ff96f426007d9f6dd0bb9b1f5d79eac773d2254 scripts/ui-auto-collage.cjs
|
||||
@@ -224,5 +222,6 @@ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 vendor/__init_
|
||||
4cae8606769fdb590c427bc1716a871017bf22d91aabf8a52513bf126cfb847f vendor/guooscar_kokonna.py
|
||||
63c7a2f1a6adf98e7fb83a83ae2d6a2dddcecd7bce4d7de25dd6f26bd496019f vendor/guooscar_protocol.py
|
||||
e5f5b7a5955f2438da131859a08c9d78cda3718ada8a9365a74cbbb9ac5e7853 vendor/metadata.json
|
||||
6a73f9541c2de74158c0e7cf6b0a58ef774f5a780bf191f2d7ec9cc53efe2bf2 vendor/noto-cjk-OFL-1.1.txt
|
||||
e8cf7d54ea46c19aba793983889b7f7425e1ebfcaaccec764a7db091646e203c vendor/paho-mqtt-EDL-1.0.txt
|
||||
57938f47d5f05f7de119b17fcecd4509c5d13644c8d5f43db30e45684d09d07e vendor/swagger-metadata.json
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
# Reuse a reviewed image only when the locked Python dependencies are identical.
|
||||
# For a fresh installation use the repository's main Dockerfile instead.
|
||||
ARG BASE_IMAGE
|
||||
FROM ${BASE_IMAGE} AS prepared
|
||||
# Cleanup runs only in the disposable preparation stage.
|
||||
USER 0
|
||||
COPY requirements.lock /app/requirements.expected.lock
|
||||
RUN python -c "from pathlib import Path; assert Path('/app/requirements.lock').read_bytes() == Path('/app/requirements.expected.lock').read_bytes(), 'Dependency lock changed; use the full Dockerfile'"
|
||||
COPY pigway_frame_flow /app/pigway_frame_flow
|
||||
COPY vendor /app/vendor
|
||||
COPY LICENSE NOTICE.md /app/
|
||||
# Publish only the cleaned filesystem, without retaining build-stage layers.
|
||||
RUN rm -rf /usr/local/lib/python*/site-packages/pip \
|
||||
/usr/local/lib/python*/site-packages/pip-*.dist-info \
|
||||
/usr/local/lib/python*/ensurepip \
|
||||
&& rm -f /usr/local/bin/pip /usr/local/bin/pip[0-9]* \
|
||||
&& find / -name .DS_Store -type f -delete
|
||||
|
||||
FROM scratch
|
||||
COPY --from=prepared / /
|
||||
ENV PATH=/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin LANG=C.UTF-8
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 TZ=Asia/Shanghai \
|
||||
DATA_DIR=/data CONFIG_DIR=/config
|
||||
WORKDIR /app
|
||||
USER 10333:10333
|
||||
EXPOSE 18787
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
||||
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:18787/health',timeout=3)"
|
||||
CMD ["python", "-m", "uvicorn", "pigway_frame_flow.main:app", "--host", "0.0.0.0", "--port", "18787", "--workers", "1", "--no-access-log"]
|
||||
ARG BUILD_COMMIT
|
||||
ARG BUILD_TIME
|
||||
ENV BUILD_COMMIT=$BUILD_COMMIT BUILD_TIME=$BUILD_TIME
|
||||
LABEL org.opencontainers.image.title="PIGWay Frame Flow" org.opencontainers.image.version="0.1.19" org.opencontainers.image.revision=$BUILD_COMMIT
|
||||
+3
-5
@@ -1,5 +1,3 @@
|
||||
# Shared mainland-China build profile; source this file before Compose builds.
|
||||
# Nonempty environment / Gitea repository variables override these defaults.
|
||||
DEBIAN_MIRROR=${DEBIAN_MIRROR:-mirrors.tuna.tsinghua.edu.cn}
|
||||
DEBIAN_SECURITY_MIRROR=${DEBIAN_SECURITY_MIRROR:-mirrors.tuna.tsinghua.edu.cn}
|
||||
export DEBIAN_MIRROR DEBIAN_SECURITY_MIRROR
|
||||
# Shared mainland-China build profile; source before Compose builds.
|
||||
ALPINE_MIRROR=${ALPINE_MIRROR:-mirrors.tuna.tsinghua.edu.cn}
|
||||
export ALPINE_MIRROR
|
||||
|
||||
+1
-2
@@ -7,8 +7,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
DEBIAN_MIRROR: ${DEBIAN_MIRROR:-deb.debian.org}
|
||||
DEBIAN_SECURITY_MIRROR: ${DEBIAN_SECURITY_MIRROR:-deb.debian.org}
|
||||
ALPINE_MIRROR: ${ALPINE_MIRROR:-dl-cdn.alpinelinux.org}
|
||||
DOCKER_PIP_INDEX_URL: ${DOCKER_PIP_INDEX_URL:-https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple}
|
||||
DOCKER_PIP_FALLBACK_INDEX_URL: ${DOCKER_PIP_FALLBACK_INDEX_URL:-https://pypi.org/simple}
|
||||
BUILD_COMMIT: ${BUILD_COMMIT:-development}
|
||||
|
||||
+18
-38
@@ -2,50 +2,30 @@
|
||||
|
||||
### Build networking and cache
|
||||
|
||||
The Dockerfile retains the pinned Python base, locked Python dependencies,
|
||||
`fonts-noto-cjk`, Debian repository signature checks, and offline artifact
|
||||
SHA256 verification. Production uses `scripts/build-verify.sh`; CI uses `scripts/ci-compose-verify.py`.
|
||||
Both build the same Dockerfile with BuildKit and retain `docker compose build --pull`.
|
||||
The runtime uses an official Python 3.14 Alpine 3.24 image pinned by digest,
|
||||
locked Python dependencies, and `font-noto-cjk` for Chinese rendering. APK
|
||||
repository signatures and offline wheel SHA256 checks remain enabled.
|
||||
Production uses `scripts/build-verify.sh`; CI uses `scripts/ci-compose-verify.py`.
|
||||
Both build the same Dockerfile with BuildKit and `docker compose build --pull`.
|
||||
|
||||
APT mirror hosts are configurable through `DEBIAN_MIRROR` and
|
||||
`DEBIAN_SECURITY_MIRROR` (hosts only, without scheme or path). Defaults are
|
||||
`deb.debian.org`; HTTPS is used for both Debian and security repositories.
|
||||
For mainland-China NAS builds, use the shared profile:
|
||||
`ALPINE_MIRROR` accepts a mirror host (without scheme or path), defaulting to
|
||||
`dl-cdn.alpinelinux.org`. For mainland-China builds:
|
||||
|
||||
```sh
|
||||
. ./deploy/build-cn.env
|
||||
./scripts/build-verify.sh
|
||||
```
|
||||
|
||||
CI loads this same profile, using Tsinghua TUNA for both repositories unless
|
||||
Gitea repository variables `DEBIAN_MIRROR` / `DEBIAN_SECURITY_MIRROR` override
|
||||
it. Production may also set the two hosts directly in `.env` when calling the
|
||||
build script without the profile. An alternate mainland mirror is
|
||||
`mirrors.ustc.edu.cn`; availability and throughput depend on the Runner network.
|
||||
No fallback disables signature verification or removes packages.
|
||||
CI uses this profile; the Gitea `ALPINE_MIRROR` repository variable can override
|
||||
it. APK upgrades available packages during a fresh dependency-layer build.
|
||||
Use `docker compose build --pull --no-cache` to refresh OS packages explicitly.
|
||||
|
||||
Layer order stays: pinned base → APT/font dependencies → `requirements.lock`
|
||||
→ pip dependencies → application/vendor source → build metadata.
|
||||
A source-only change therefore reuses the APT and pip layers, provided the
|
||||
same builder, base digest, mirror arguments, and optional offline artifacts
|
||||
are used. Changing the lockfile rebuilds pip and later layers, not APT.
|
||||
Changing the mirror or APT instructions rebuilds APT and later layers.
|
||||
|
||||
Previously an APT layer miss redownloaded indexes/packages, and pip used
|
||||
`--no-cache-dir`. Now locked BuildKit mounts retain APT indexes, downloaded
|
||||
`.deb` files, and pip downloads/wheels outside the final image. Debian's
|
||||
`docker-clean` hook is disabled so it cannot discard cached packages.
|
||||
Re-executed APT steps still run `apt-get update` and validate repository
|
||||
signatures; cached packages and pip artifacts can avoid repeat large downloads.
|
||||
The initial build after this Dockerfile change will miss dependency layers;
|
||||
subsequent builds benefit. No measured speedup is claimed before CI completes.
|
||||
|
||||
Caches belong to the Docker builder, not the ephemeral CI workspace. Keep the
|
||||
NAS Runner's builder storage across jobs; removing the builder, pruning caches,
|
||||
or using a fresh Docker daemon loses the benefit. Cache mounts are disposable:
|
||||
an empty cache still builds correctly. `--pull` remains enabled; a pinned base
|
||||
digest check alone does not invalidate dependency layers. To deliberately
|
||||
refresh installed APT versions, use `docker compose build --pull --no-cache`.
|
||||
Layer order is pinned base → APK/fonts → requirements → Python dependencies
|
||||
→ application source → metadata. BuildKit caches pip downloads separately for
|
||||
musl and architecture. Optional `build-cache/wheels/` must contain compatible
|
||||
musllinux wheels and their SHA256 manifest; empty-cache builds work normally.
|
||||
Do not reuse Debian/manylinux wheels on Alpine. Caches are disposable builder
|
||||
resources and are not runtime mounts or dependencies.
|
||||
|
||||
### CI with a host Docker socket
|
||||
|
||||
@@ -94,8 +74,8 @@ certificate environment settings, and proxy settings remain in effect.
|
||||
These `CI_PIP_*` settings apply only to the Job's pip install. They are not
|
||||
passed into Docker build arguments or persisted into the production image.
|
||||
The Dockerfile keeps its own cached/offline dependency installation and logs
|
||||
the Docker pip index host for online installs. Debian mirror variables affect
|
||||
APT only and are loaded later in the Docker verification step.
|
||||
the Docker pip index host for online installs. The Alpine mirror variable affects
|
||||
APK only and are loaded later in the Docker verification step.
|
||||
|
||||
If dependency installation fails, the always() cleanup step still executes.
|
||||
It skips the Python/PyYAML cleanup script when no CI Compose manifest exists,
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ A failed mirror installation retries the same locked requirements against the
|
||||
fallback, without extra indexes, version downgrades, or disabling build isolation.
|
||||
Logs show index hosts and redact URL credentials/query parameters.
|
||||
|
||||
APT/font layers remain cached when Python dependencies change. The Python layer
|
||||
APK/font layers remain cached when Python dependencies change. The Python layer
|
||||
changes only when the lock, installer, base image, or mirror arguments change;
|
||||
application source changes reuse it. BuildKit pip cache survives layer misses.
|
||||
An explicitly supplied, checksum-verified offline wheel directory still takes
|
||||
|
||||
+4
-8
@@ -128,23 +128,19 @@ all uncompressed rootfs diff IDs before loading. With the verified local tag loa
|
||||
|
||||
```sh
|
||||
sudo env DOCKER_BUILDKIT=1 /usr/local/bin/docker compose build \
|
||||
--build-arg PYTHON_BASE=python:3.14.5-slim-bookworm
|
||||
--build-arg PYTHON_BASE=python:3.14.8-alpine3.24
|
||||
```
|
||||
|
||||
This per-build override does not change global registry or network configuration.
|
||||
|
||||
A slow Debian CDN can be overridden only for this build, retaining APT GPG
|
||||
A slow Alpine CDN can be overridden for this build, retaining APK signature
|
||||
verification and changing no NAS system settings:
|
||||
|
||||
```sh
|
||||
sudo /usr/local/bin/docker compose build --build-arg DEBIAN_MIRROR=mirrors.aliyun.com
|
||||
sudo /usr/local/bin/docker compose build --build-arg ALPINE_MIRROR=mirrors.tuna.tsinghua.edu.cn
|
||||
```
|
||||
|
||||
Optional `build-cache/debs/fonts-noto-cjk.deb` avoids a slow build-network download.
|
||||
Dockerfile verifies it against SHA-256 from the GPG-authenticated APT index before use.
|
||||
The cache is not a runtime mount or committed dependency, and empty-cache builds work.
|
||||
|
||||
Optional `build-cache/wheels/` can hold all 24 Linux AMD64/Python 3.14 wheels
|
||||
Optional `build-cache/wheels/` can hold all locked Linux AMD64/Python 3.14 musllinux wheels
|
||||
and `SHA256SUMS`, verified against official PyPI release metadata. Builds verify
|
||||
the manifest and use pip `--no-index`; incomplete caches fail explicitly.
|
||||
Build commit/time are set after dependency installation to preserve build cache.
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
FRAME_FLOW_IMAGE='<已验证的镜像标签>' docker compose -f deploy/compose.ubuntu-photos-api.yml config --quiet
|
||||
```
|
||||
|
||||
完整构建使用根目录 Dockerfile。若使用 `deploy/Dockerfile.runtime-update`,必须指定已审核的基础镜像,构建步骤会检查依赖锁与基础镜像相同;不相同时必须完整构建。本次依赖未新增,已比对现有 0.1.8 基础镜像的锁文件。
|
||||
发布统一使用根目录 Dockerfile 完整构建,包含固定基础映像、系统安全更新和锁定依赖,避免继承旧映像中的系统漏洞。
|
||||
|
||||
## 旧来源转换与恢复
|
||||
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "PIGWay Frame Flow API",
|
||||
"version": "0.1.19"
|
||||
"version": "0.1.21"
|
||||
},
|
||||
"paths": {
|
||||
"/api/v1/devices/{device_id}/widgets/selection": {
|
||||
@@ -15227,7 +15227,7 @@
|
||||
"version": {
|
||||
"type": "string",
|
||||
"title": "Version",
|
||||
"default": "0.1.19"
|
||||
"default": "0.1.21"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -17490,7 +17490,7 @@
|
||||
"version": {
|
||||
"type": "string",
|
||||
"title": "Version",
|
||||
"default": "0.1.19"
|
||||
"default": "0.1.21"
|
||||
},
|
||||
"api_version": {
|
||||
"type": "string",
|
||||
|
||||
@@ -126,7 +126,7 @@ def create_app(settings=None, start_worker=True):
|
||||
app = FastAPI(
|
||||
title="PIGWay Frame Flow API",
|
||||
docs_url=None,
|
||||
version="0.1.20",
|
||||
version="0.1.21",
|
||||
lifespan=lifespan,
|
||||
responses=error_responses,
|
||||
)
|
||||
@@ -1040,7 +1040,7 @@ def create_app(settings=None, start_worker=True):
|
||||
supports_upload=True,
|
||||
),
|
||||
],
|
||||
version="0.1.20",
|
||||
version="0.1.21",
|
||||
mock=settings.mock,
|
||||
write_enabled=settings.write_enabled,
|
||||
api_key_configured=bool(settings.api_key)
|
||||
|
||||
@@ -366,7 +366,7 @@ class SettingsView(BaseModel):
|
||||
|
||||
class Health(BaseModel):
|
||||
status: str
|
||||
version: str = "0.1.20"
|
||||
version: str = "0.1.21"
|
||||
|
||||
|
||||
class Readiness(BaseModel):
|
||||
@@ -397,7 +397,7 @@ class RestoreRequest(StrictModel):
|
||||
|
||||
class Version(BaseModel):
|
||||
product: str = "PIGWay Frame Flow"
|
||||
version: str = "0.1.20"
|
||||
version: str = "0.1.21"
|
||||
api_version: str = "v1"
|
||||
commit: str = "development"
|
||||
build_time: str = "unknown"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><meta name="color-scheme" content="light dark"><title>PIGWay Frame Flow</title><link rel="stylesheet" href="/ui/style.css"></head>
|
||||
<body><aside class="sidebar"><a class="brand" href="/"><span>PIGWay Frame Flow<small>Smart Frame Automation</small></span></a><nav id="nav"></nav><div class="sidebar-bottom"><small>Version 0.1.19</small></div></aside><div class="workspace"><header><div><span class="eyebrow">PIGWay Frame Flow</span><h1 id="page-title"></h1></div><div class="toolbar"><select id="device" aria-label="Device"></select><button id="lang" class="icon-button" aria-label="Change language">EN</button><button id="theme" class="icon-button" aria-label="Change theme">◐</button></div></header><main id="main"></main><footer id="footer"></footer></div><div id="toast" role="status" aria-live="polite"></div><dialog id="modal"><div id="modal-content"></div></dialog><script src="/ui/i18n.js?v=photo-quality-v0117"></script><script src="/ui/features.js?v=photo-quality-v0117"></script><script src="/ui/extensions.js?v=photo-quality-v0117"></script><script src="/ui/app.js?v=photo-quality-v0117"></script></body></html>
|
||||
<body><aside class="sidebar"><a class="brand" href="/"><span>PIGWay Frame Flow<small>Smart Frame Automation</small></span></a><nav id="nav"></nav><div class="sidebar-bottom"><small>Version 0.1.21</small></div></aside><div class="workspace"><header><div><span class="eyebrow">PIGWay Frame Flow</span><h1 id="page-title"></h1></div><div class="toolbar"><select id="device" aria-label="Device"></select><button id="lang" class="icon-button" aria-label="Change language">EN</button><button id="theme" class="icon-button" aria-label="Change theme">◐</button></div></header><main id="main"></main><footer id="footer"></footer></div><div id="toast" role="status" aria-live="polite"></div><dialog id="modal"><div id="modal-content"></div></dialog><script src="/ui/i18n.js?v=0.1.21"></script><script src="/ui/features.js?v=0.1.21"></script><script src="/ui/extensions.js?v=0.1.21"></script><script src="/ui/app.js?v=0.1.21"></script></body></html>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "pigway-frame-flow"
|
||||
version = "0.1.20"
|
||||
version = "0.1.21"
|
||||
readme = "README.md"
|
||||
license = {file = "LICENSE"}
|
||||
requires-python = ">=3.14,<3.15"
|
||||
|
||||
@@ -375,9 +375,7 @@ class Deploy:
|
||||
"DOCKER_PIP_FALLBACK_INDEX_URL"
|
||||
)
|
||||
or "https://pypi.org/simple",
|
||||
"DEBIAN_MIRROR": self.env.get("DEBIAN_MIRROR") or "deb.debian.org",
|
||||
"DEBIAN_SECURITY_MIRROR": self.env.get("DEBIAN_SECURITY_MIRROR")
|
||||
or "deb.debian.org",
|
||||
"ALPINE_MIRROR": self.env.get("ALPINE_MIRROR") or "dl-cdn.alpinelinux.org",
|
||||
"BUILD_COMMIT": commit,
|
||||
"BUILD_TIME": now,
|
||||
}.items():
|
||||
|
||||
+21
-26
@@ -10,6 +10,7 @@ import shutil
|
||||
import sqlite3
|
||||
import subprocess
|
||||
import time
|
||||
import tomllib
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
@@ -139,9 +140,6 @@ def release(lock):
|
||||
before = inspect()
|
||||
old_env = dict(s.split("=", 1) for s in before["Config"]["Env"])
|
||||
verify_runtime(old_env["BUILD_COMMIT"])
|
||||
assert run("docker", "exec", CONTAINER, "cat", "/app/requirements.lock") == (
|
||||
(ctx / "requirements.lock").read_text().strip()
|
||||
), "Dependencies differ; full build required"
|
||||
stamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
||||
backup = RECOVERY / ("release-" + stamp + "-" + commit[:12])
|
||||
backup.mkdir(mode=0o700)
|
||||
@@ -153,29 +151,26 @@ def release(lock):
|
||||
with sqlite3.connect(backup / "frameflow.before.db") as dst:
|
||||
src.backup(dst)
|
||||
assert dst.execute("pragma quick_check").fetchone()[0] == "ok"
|
||||
base = "pigway-frame-flow:release-base-" + commit[:12]
|
||||
run("docker", "image", "tag", before["Image"], base)
|
||||
image = "pigway-frame-flow:0.1.19-" + commit[:12]
|
||||
try:
|
||||
run(
|
||||
"docker",
|
||||
"build",
|
||||
"--pull=false",
|
||||
"--network=none",
|
||||
"-f",
|
||||
str(ctx / "deploy/Dockerfile.runtime-update"),
|
||||
"--build-arg",
|
||||
"BASE_IMAGE=" + base,
|
||||
"--build-arg",
|
||||
"BUILD_COMMIT=" + commit,
|
||||
"--build-arg",
|
||||
"BUILD_TIME=" + stamp,
|
||||
"-t",
|
||||
image,
|
||||
str(ctx),
|
||||
)
|
||||
finally:
|
||||
run("docker", "image", "rm", base)
|
||||
version = tomllib.loads((ctx / "pyproject.toml").read_text())["project"]["version"]
|
||||
assert re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+", version)
|
||||
image = "pigway-frame-flow:" + version + "-" + commit[:12]
|
||||
# A source-only overlay would retain vulnerable packages from the old image.
|
||||
run(
|
||||
"docker",
|
||||
"build",
|
||||
"--pull",
|
||||
"-f",
|
||||
str(ctx / "Dockerfile"),
|
||||
"--build-arg",
|
||||
"BUILD_COMMIT=" + commit,
|
||||
"--build-arg",
|
||||
"BUILD_TIME=" + stamp,
|
||||
"--build-arg",
|
||||
"ALPINE_MIRROR=" + os.getenv("ALPINE_MIRROR", "dl-cdn.alpinelinux.org"),
|
||||
"-t",
|
||||
image,
|
||||
str(ctx),
|
||||
)
|
||||
compose = json.loads((APP / "compose.json").read_text())
|
||||
service = compose["services"][CONTAINER]
|
||||
service["image"] = image
|
||||
|
||||
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font
|
||||
creation efforts of academic and linguistic communities, and to
|
||||
provide a free and open framework in which fonts may be shared and
|
||||
improved in partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply to
|
||||
any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software
|
||||
components as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to,
|
||||
deleting, or substituting -- in part or in whole -- any of the
|
||||
components of the Original Version, by changing formats or by porting
|
||||
the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed,
|
||||
modify, redistribute, and sell modified and unmodified copies of the
|
||||
Font Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components, in
|
||||
Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the
|
||||
corresponding Copyright Holder. This restriction only applies to the
|
||||
primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created using
|
||||
the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
Reference in New Issue
Block a user