2026-05-10 13:12:44 +08:00

79 lines
2.3 KiB
JavaScript

/*
* 复用 scripts/preflight/secrets-manifest.json 的 schema, 把 secret 列表按
* workflow 分组返回前端. 遵循 cc-004: 字段名走 `用途` 而不是 secret 名 (Awen
* 一眼看懂).
*/
"use strict";
const fs = require("fs");
const path = require("path");
const REPO_ROOT = path.resolve(__dirname, "..", "..", "..");
const DEFAULT_MANIFEST = path.join(
REPO_ROOT,
"scripts",
"preflight",
"secrets-manifest.json"
);
function loadManifest(manifestPath) {
const p = manifestPath || DEFAULT_MANIFEST;
if (!fs.existsSync(p)) {
throw new Error("密钥清单文件不存在: " + p);
}
const raw = JSON.parse(fs.readFileSync(p, "utf8"));
if (!raw || !raw.workflows) throw new Error("密钥清单 schema 不识别 (缺 workflows)");
return raw;
}
function buildGroups(manifestPath) {
const raw = loadManifest(manifestPath);
const groups = [];
for (const [wf, def] of Object.entries(raw.workflows || {})) {
const group = {
workflow: wf,
describe: def._describe || wf,
subject: def._主体 || "",
group_action: wf === "autodl-inference" ? "save_and_refresh" : null,
secrets: []
};
for (const s of def.secrets || []) {
group.secrets.push({
name: s.name,
level: s.level || "optional",
stages: s.stages || [],
targets: s.targets || [],
用途: s["用途"] || s.name,
如何配置: s["如何配置"] || s.where || s["更新方式"] || "",
default_hint: s.default_hint || "",
default: s.default || "",
强校验: s["强校验"] || ""
});
}
groups.push(group);
}
return groups;
}
function findSecretMeta(name, manifestPath) {
const raw = loadManifest(manifestPath);
for (const [wf, def] of Object.entries(raw.workflows || {})) {
for (const s of def.secrets || []) {
if (s.name === name) return { workflow: wf, ...s };
}
}
return null;
}
// 列出所有合法的 key (write 路由白名单校验用)
function knownKeys(manifestPath) {
const raw = loadManifest(manifestPath);
const keys = new Set();
for (const def of Object.values(raw.workflows || {})) {
for (const s of def.secrets || []) keys.add(s.name);
}
return keys;
}
module.exports = { loadManifest, buildGroups, findSecretMeta, knownKeys, DEFAULT_MANIFEST };