mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-10-29 03:36:15 +08:00
- 部署文档、升级指南与 README 改为正式版说法:latest = 4.0,3.3 固定为 3.3.7 - docs/changelog/4.0.md 新增 4.0.0 汇总(升级前必读、破坏性变更、新功能、主要修复),链接改为绝对地址 - 文档站与插件市场改为从 main 发布,插件上架 PR 的目标分支改为 main - 文档站页脚版本 v4.0.0;en/ja README 的 star history 地址
181 lines
6.4 KiB
YAML
181 lines
6.4 KiB
YAML
name: Plugin Registry
|
||
|
||
# 插件市场:plugins/registry/<id>.toml 指向作者仓库的固定 commit。
|
||
# - check:PR 上运行作者的代码(测试、pnpm 构建),只读权限、不读 secret。
|
||
# 检查脚本与 ab_sdk 取自 base 分支,PR 不能改掉检查规则。
|
||
# - plan / build:合并后。build 每个插件一个 job(会运行作者的前端构建,没有密钥),
|
||
# 一个插件的构建篡改不到别的插件。
|
||
# - sign:唯一读 PLUGIN_SIGNING_KEY 的 job,不运行作者代码。它自己下载复用的 zip
|
||
# 并校验 sha256,核对每个新 zip 的 id 与来源,再签名发布。
|
||
on:
|
||
pull_request:
|
||
branches: ["main"]
|
||
paths: ["plugins/**"]
|
||
push:
|
||
branches: ["main"]
|
||
paths: ["plugins/**"]
|
||
workflow_dispatch:
|
||
inputs:
|
||
rebuild:
|
||
description: "忽略已发布的 zip,全部重新打包(打包逻辑变更后使用)"
|
||
type: boolean
|
||
default: false
|
||
|
||
permissions:
|
||
contents: read
|
||
|
||
concurrency:
|
||
group: plugin-registry-${{ github.event_name == 'pull_request' && github.ref || 'publish' }}
|
||
cancel-in-progress: false
|
||
|
||
env:
|
||
REBUILD: ${{ inputs.rebuild && 'true' || '' }}
|
||
|
||
jobs:
|
||
check:
|
||
if: github.event_name == 'pull_request'
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
ref: ${{ github.event.pull_request.base.sha }}
|
||
fetch-depth: 0
|
||
persist-credentials: false
|
||
- name: Fetch PR head
|
||
run: |
|
||
git fetch -q origin "refs/pull/${{ github.event.number }}/head"
|
||
# 固定为 SHA:作者代码在检查过程中可以改写 .git/FETCH_HEAD
|
||
echo "HEAD_SHA=$(git rev-parse FETCH_HEAD)" >> "$GITHUB_ENV"
|
||
# 引入本脚本的那个 PR 时 base 上还没有它,只能用 PR 自己的版本
|
||
if [ ! -f scripts/plugin_registry.py ]; then
|
||
echo "::warning::base 分支没有 scripts/plugin_registry.py,使用 PR 中的版本"
|
||
git checkout "$(git rev-parse FETCH_HEAD)" -- scripts/plugin_registry.py
|
||
fi
|
||
- &python
|
||
uses: actions/setup-python@v5
|
||
with:
|
||
python-version: "3.14"
|
||
- &uv
|
||
uses: astral-sh/setup-uv@v10.3.0
|
||
with:
|
||
version: "0.13.x"
|
||
- &pnpm
|
||
uses: pnpm/action-setup@v6
|
||
with:
|
||
version: 12.14.0
|
||
run_install: false
|
||
- &node
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: 24
|
||
- &deps
|
||
name: Install backend
|
||
run: mkdir -p backend/config && cd backend && uv sync --group dev
|
||
- &catalog
|
||
name: Download published catalog
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
run: gh release download plugins -p catalog.json -p catalog.json.sig -D old || echo "release plugins 还不存在"
|
||
- name: Check changed entries
|
||
run: |
|
||
set -o pipefail
|
||
uv run --project backend python scripts/plugin_registry.py check \
|
||
--base "${{ github.event.pull_request.base.sha }}" --head "$HEAD_SHA" \
|
||
--catalog old/catalog.json --out dist | tee -a "$GITHUB_STEP_SUMMARY"
|
||
|
||
plan:
|
||
# 带着签名密钥的发布只从 main 运行
|
||
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
build: ${{ steps.plan.outputs.build }}
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
persist-credentials: false
|
||
- *python
|
||
- *uv
|
||
- *deps
|
||
- *catalog
|
||
- id: plan
|
||
run: |
|
||
uv run --project backend python scripts/plugin_registry.py plan --catalog old/catalog.json ${REBUILD:+--rebuild} > plan.json
|
||
cat plan.json
|
||
echo "build=$(jq -c .build plan.json)" >> "$GITHUB_OUTPUT"
|
||
|
||
build:
|
||
needs: plan
|
||
if: needs.plan.outputs.build != '[]'
|
||
runs-on: ubuntu-latest
|
||
strategy:
|
||
fail-fast: true
|
||
matrix:
|
||
id: ${{ fromJSON(needs.plan.outputs.build) }}
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
persist-credentials: false
|
||
- *python
|
||
- *uv
|
||
- *pnpm
|
||
- *node
|
||
- *deps
|
||
- run: uv run --project backend python scripts/plugin_registry.py build-one "${{ matrix.id }}" --out dist
|
||
- uses: actions/upload-artifact@v4
|
||
with:
|
||
name: plugin-${{ matrix.id }}
|
||
path: dist/
|
||
retention-days: 7
|
||
|
||
sign:
|
||
needs: [plan, build]
|
||
if: always() && needs.plan.result == 'success' && (needs.build.result == 'success' || needs.build.result == 'skipped')
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: write
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
persist-credentials: false
|
||
- *python
|
||
- *uv
|
||
- *deps
|
||
- *catalog
|
||
- uses: actions/download-artifact@v4
|
||
with:
|
||
pattern: plugin-*
|
||
path: dist
|
||
- name: Collect
|
||
run: |
|
||
mkdir -p dist
|
||
uv run --project backend python scripts/plugin_registry.py collect \
|
||
--catalog old/catalog.json ${REBUILD:+--rebuild} --dist dist --out stage
|
||
- name: Sign catalog
|
||
env:
|
||
PLUGIN_SIGNING_KEY: ${{ secrets.PLUGIN_SIGNING_KEY }}
|
||
run: |
|
||
if [ -z "$PLUGIN_SIGNING_KEY" ]; then
|
||
echo "::error::PLUGIN_SIGNING_KEY secret is not set" >&2
|
||
exit 1
|
||
fi
|
||
umask 077
|
||
printf '%s\n' "$PLUGIN_SIGNING_KEY" > "$RUNNER_TEMP/key.pem"
|
||
shopt -s nullglob # 全部下架时没有 zip,签一个空目录
|
||
zips=(stage/*.zip)
|
||
uv run --no-project --with cryptography python scripts/build_plugin_catalog.py \
|
||
--key "$RUNNER_TEMP/key.pem" --sources stage/sources.json --out release-assets "${zips[@]}"
|
||
rm -f "$RUNNER_TEMP/key.pem"
|
||
- name: Publish
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
run: |
|
||
# tag 名不含 beta / alpha,不会触发 build.yml 的镜像构建
|
||
gh release view plugins >/dev/null 2>&1 || gh release create plugins \
|
||
--target "${{ github.sha }}" --latest=false --title "Plugin catalog" \
|
||
--notes "AutoBangumi 插件市场的签名目录,由 plugin-registry 工作流维护。"
|
||
gh release upload plugins release-assets/* --clobber
|
||
# 下架:删除不在新目录中的旧 zip 与签名
|
||
for asset in $(gh release view plugins --json assets -q '.assets[].name'); do
|
||
[ -e "release-assets/$asset" ] || gh release delete-asset plugins "$asset" -y
|
||
done
|