Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ on:
- 'components/**'
- 'tests/test_pages_ui.js'
- 'tests/test_pages_policy.sh'
- 'tests/test_component_catalog_staging.py'
- 'devices/**'
- 'scripts/device_metadata.py'
- 'scripts/generate-pages-data.py'
- 'scripts/component_package_policy.py'
- 'scripts/resolve-components.py'
- 'scripts/validate-component-catalogs.py'
- 'scripts/verify-pages-releases.py'
- 'scripts/verify-vm-esxi-evidence.py'
- 'schemas/vm-esxi-evidence.schema.json'
Expand Down Expand Up @@ -76,19 +80,21 @@ jobs:
echo 'The Pages artifact must not contain symbolic or hard links.' >&2
exit 1
fi
- name: Stage component catalog for Pages
- name: Validate and stage component catalogs for Pages
run: |
set -euo pipefail
test -f components/catalog.json
test ! -L components/catalog.json
mkdir -p site/components
cp components/catalog.json site/components/catalog.json
python3 -m json.tool site/components/catalog.json >/dev/null
test ! -L site/components/catalog.json
python3 scripts/validate-component-catalogs.py \
--components-root components \
--site-root site/components
if find site/components \( -type l -o -type f -links +1 \) -print -quit | grep -q .; then
echo 'The staged component catalogs must not contain symbolic or hard links.' >&2
exit 1
fi
- name: Test Pages UI and policy
run: |
set -euo pipefail
node tests/test_pages_ui.js
python3 tests/test_component_catalog_staging.py
bash tests/test_pages_policy.sh
- name: Configure GitHub Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
Expand Down
52 changes: 50 additions & 2 deletions components/catalog.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schema_version": 1,
"catalog_version": "2026.07.20",
"max_selected_components": 8,
"catalog_version": "2026.07.21",
"max_selected_components": 32,
"targets": [
{
"id": "x86_64",
Expand Down Expand Up @@ -48,6 +48,54 @@
"title": "存储支持",
"description": "USB 存储、文件系统和磁盘工具。",
"order": 50
},
{
"id": "official-target",
"title": "目标专用包",
"description": "OpenWrt 官方目标仓库中的设备与平台专用包。",
"order": 110
},
{
"id": "official-base",
"title": "官方基础包",
"description": "OpenWrt 官方 base 仓库中的基础系统与网络包。",
"order": 120
},
{
"id": "official-kernel",
"title": "官方内核模块",
"description": "与目标内核 ABI 匹配的 OpenWrt 官方 kmod 包。",
"order": 130
},
{
"id": "official-luci",
"title": "LuCI 应用",
"description": "OpenWrt 官方 LuCI Web 管理应用与协议支持。",
"order": 140
},
{
"id": "official-packages",
"title": "官方应用包",
"description": "OpenWrt 官方 packages feed 中的用户空间应用。",
"order": 150
},
{
"id": "official-routing",
"title": "路由协议",
"description": "OpenWrt 官方 routing feed 中的路由协议与工具。",
"order": 160
},
{
"id": "official-telephony",
"title": "通信与语音",
"description": "OpenWrt 官方 telephony feed 中的通信组件。",
"order": 170
},
{
"id": "official-video",
"title": "视频与媒体",
"description": "OpenWrt 官方 video feed 中的视频和媒体组件。",
"order": 180
}
],
"components": [
Expand Down
1 change: 1 addition & 0 deletions components/package-catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"catalog_version":"2026.07.21","openwrt_version":"25.12.5","schema_version":1,"shards":[{"flavor":"official","package_count":10947,"path":"components/packages/x86_64-official.json","selectable_count":10722,"sha256":"76957483a7e01e8e9e253babc7557e64bf5ef7780b7382445c8d56d18cd64e9f","sources":[{"feed":"target","sha256":"5b1f78e64094ac3c0338e3c8b1e731fd4cfe99ac41d2a84d1a2d90ea308ef9ca","url":"https://downloads.openwrt.org/releases/25.12.5/targets/x86/64/packages/packages.adb"},{"feed":"base","sha256":"c4fa582b1ffa68a3c1662047ef0c194d63873914dd876fb2149a58681373f4eb","url":"https://downloads.openwrt.org/releases/25.12.5/packages/x86_64/base/packages.adb"},{"feed":"kmods","sha256":"396d8d908ed765664564a86df328ed55d5b7390ea5dfc00dac2931cc3bc3172d","url":"https://downloads.openwrt.org/releases/25.12.5/targets/x86/64/kmods/6.12.94-1-a7bc15f451f9652701ba04af9cfb0b95/packages.adb"},{"feed":"luci","sha256":"b2d26823521958fbb822971583d095d56cd81753b7af4ee4d15fe1e0833132f4","url":"https://downloads.openwrt.org/releases/25.12.5/packages/x86_64/luci/packages.adb"},{"feed":"packages","sha256":"e035e0563f6756b1d715b62604db63a6530dba271d7af30076200dbd6845e5a2","url":"https://downloads.openwrt.org/releases/25.12.5/packages/x86_64/packages/packages.adb"},{"feed":"routing","sha256":"b10fe8cc187eb33d4cf5b2fd082ccee7ff66ef6cef65e3d286432c74d479239b","url":"https://downloads.openwrt.org/releases/25.12.5/packages/x86_64/routing/packages.adb"},{"feed":"telephony","sha256":"0fb0698f41ec500441894d0a7bef6b297ea1634673b7e508e4ebfab5c7cf384b","url":"https://downloads.openwrt.org/releases/25.12.5/packages/x86_64/telephony/packages.adb"},{"feed":"video","sha256":"c1543970056375f056e0fac9bf1d2862673fe9910c6c6984293699b9eda39c87","url":"https://downloads.openwrt.org/releases/25.12.5/packages/x86_64/video/packages.adb"}],"target":"x86_64"},{"flavor":"official","package_count":11154,"path":"components/packages/xiaomi_ax9000-official.json","selectable_count":10857,"sha256":"53dd20dd71e5636ee07831600935b8ffdbe8278485a23a9871425fdd49ef1cff","sources":[{"feed":"target","sha256":"b475666b9d7d56ee281cc99e10a66f513c98dd00a7f249af44f22b19376aee7c","url":"https://downloads.openwrt.org/releases/25.12.5/targets/qualcommax/ipq807x/packages/packages.adb"},{"feed":"base","sha256":"31a28b068dc5410f69c121ee94824884ee2f9c4fd0d271a571bb6fabb60ac6be","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/base/packages.adb"},{"feed":"kmods","sha256":"e1744c89c7516332beddb89c4229271d5c02df95cbd5deb0813a8650ec3bf854","url":"https://downloads.openwrt.org/releases/25.12.5/targets/qualcommax/ipq807x/kmods/6.12.94-1-dbd7ac5945a1d38dbc7f22bedd674e40/packages.adb"},{"feed":"luci","sha256":"289563e984e797396865e6d09142474853b03c20f33610dd54c2174a28cb11f7","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/luci/packages.adb"},{"feed":"packages","sha256":"28ae423e7d70b699491f132647b554da54e4dc4dff6236e97c5c957454e81f60","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/packages/packages.adb"},{"feed":"routing","sha256":"d16b73cae2145ce34aa17e3476a9ec94a8b408b8c9e2ed674b1d4271aeec4f79","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/routing/packages.adb"},{"feed":"telephony","sha256":"c61b70ad648b64baebeccccbdf8293929511233e9dcc13a1bdf7859e25cedf58","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/telephony/packages.adb"},{"feed":"video","sha256":"5717d11f3f2ce033caa4f2f595a010c2b53a84f6d510bf8c41420eb92a3840fc","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/video/packages.adb"}],"target":"xiaomi_ax9000"},{"flavor":"nss","package_count":3903,"path":"components/packages/xiaomi_ax9000-nss.json","selectable_count":3902,"sha256":"b1d6ef48d7a5f94f865429499de3140b9b2d180f1cc84ef0d41de3d4c4fb4ded","sources":[{"feed":"base","sha256":"31a28b068dc5410f69c121ee94824884ee2f9c4fd0d271a571bb6fabb60ac6be","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/base/packages.adb"},{"feed":"luci","sha256":"289563e984e797396865e6d09142474853b03c20f33610dd54c2174a28cb11f7","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/luci/packages.adb"},{"feed":"packages","sha256":"28ae423e7d70b699491f132647b554da54e4dc4dff6236e97c5c957454e81f60","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/packages/packages.adb"},{"feed":"routing","sha256":"d16b73cae2145ce34aa17e3476a9ec94a8b408b8c9e2ed674b1d4271aeec4f79","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/routing/packages.adb"},{"feed":"telephony","sha256":"c61b70ad648b64baebeccccbdf8293929511233e9dcc13a1bdf7859e25cedf58","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/telephony/packages.adb"},{"feed":"video","sha256":"5717d11f3f2ce033caa4f2f595a010c2b53a84f6d510bf8c41420eb92a3840fc","url":"https://downloads.openwrt.org/releases/25.12.5/packages/aarch64_cortex-a53/video/packages.adb"}],"target":"xiaomi_ax9000"}]}
1 change: 1 addition & 0 deletions components/packages/x86_64-official.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions components/packages/xiaomi_ax9000-nss.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions components/packages/xiaomi_ax9000-official.json

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions scripts/component_package_policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""Shared fail-closed policy for generated OpenWrt package records."""

from __future__ import annotations

HIGH_RISK_EXACT = frozenset(
{
"apk-mbedtls",
"base-files",
"busybox",
"fstools",
"fwtool",
"kernel",
"libc",
"mtd",
"opkg",
"procd",
"procd-seccomp",
"procd-ujail",
"ubus",
"ubusd",
"uci",
"urandom-seed",
}
)
HIGH_RISK_PREFIXES = (
"apk-",
"grub",
"ipq-wifi-",
"kexec",
"opkg-",
"trusted-firmware-",
"u-boot",
"uboot-",
)
SYSTEM_PREFIXES = (
"base-files",
"block-mount",
"busybox",
"firewall",
"fstools",
"init",
"mtd",
"netifd",
"nftables",
"odhcp",
"procd",
"ubus",
"uci",
)
ADVANCED_SUFFIXES = ("-dbg", "-dev", "-src", "-static")
ALLOWED_ARCHITECTURES = {
("x86_64", "official"): frozenset({"x86_64", "noarch"}),
("xiaomi_ax9000", "official"): frozenset({"aarch64_cortex-a53", "noarch"}),
("xiaomi_ax9000", "nss"): frozenset({"noarch"}),
}


def blocked_reason_for(package: str) -> str:
"""Return the mandatory block reason, or an empty string when selectable."""
lower = package.lower()
if lower in HIGH_RISK_EXACT or lower.startswith(HIGH_RISK_PREFIXES):
return "核心系统、引导或包管理组件不可由自定义构建请求直接选择。"
if "firmware" in lower or lower.endswith("-fw"):
return "设备固件包需按目标硬件审核,不能由通用组件目录直接选择。"
if lower.startswith("bootloader-") or lower.endswith("-bootloader"):
return "引导加载器组件不可由自定义构建请求直接选择。"
return ""


def risk_for(package: str, feed: str) -> str:
"""Return the mandatory risk label for a package/feed pair."""
lower = package.lower()
if feed == "kmods" or lower.startswith("kmod-") or lower.endswith(ADVANCED_SUFFIXES):
return "advanced"
if blocked_reason_for(package) or feed == "target" or lower.startswith(SYSTEM_PREFIXES):
return "system"
return "standard"


def allowed_architectures_for(target: str, flavor: str) -> frozenset[str]:
"""Return the exact architecture allow-list for a published shard."""
try:
return ALLOWED_ARCHITECTURES[(target, flavor)]
except KeyError as error:
raise ValueError(f"unsupported package shard architecture policy: {target}/{flavor}") from error
Loading
Loading