ci: 添加小程序自动部署配置

- 添加 Gitea Actions workflow: miniapp-preview.yml
- 添加 CI 脚本: upload-ci.cjs, preview-ci.cjs
- 添加版本解析: resolve-version.cjs, resolve-upload-desc.cjs
- 添加 mini/package.json 用于 miniprogram-ci 依赖
This commit is contained in:
gouki
2026-08-06 09:20:43 +00:00
parent a3e6aa9c01
commit 9c178e6d49
6 changed files with 534 additions and 0 deletions
+151
View File
@@ -0,0 +1,151 @@
/**
* Build the WeChat upload "项目备注" from recent change summaries.
* Prefer recent git commit subjects (Chinese commit messages in this repo);
* fall back to the latest CHANGELOG bullets when git history is unavailable.
*/
const fs = require("node:fs");
const path = require("node:path");
const { execFileSync } = require("node:child_process");
const DEFAULT_MAX_LENGTH = 100;
function cleanCommitSubject(subject) {
return String(subject || "")
.trim()
.replace(
/^(feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert)(\([^)]*\))?:\s*/i,
"",
)
.replace(/\s+/g, " ")
.trim();
}
function truncateDesc(text, maxLength = DEFAULT_MAX_LENGTH) {
const value = String(text || "").trim();
if (!value) {
return "";
}
if ([...value].length <= maxLength) {
return value;
}
const chars = [...value].slice(0, Math.max(0, maxLength - 1));
return `${chars.join("")}`;
}
function collectRecentCommitSubjects(repoRoot, limit = 5) {
try {
const output = execFileSync(
"git",
[
"log",
`-${Math.max(1, limit * 3)}`,
"--pretty=%s",
"--",
"mini/",
"CHANGELOG.md",
"Features.md",
],
{
cwd: repoRoot,
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
},
);
const subjects = [];
const seen = new Set();
for (const line of output.split("\n")) {
const cleaned = cleanCommitSubject(line);
if (!cleaned || seen.has(cleaned)) {
continue;
}
// Skip pure docs/chore noise when better subjects exist.
if (/^(说明|文档|记录)/.test(cleaned) && subjects.length > 0) {
continue;
}
seen.add(cleaned);
subjects.push(cleaned);
if (subjects.length >= limit) {
break;
}
}
return subjects;
} catch {
return [];
}
}
function collectRecentChangelogBullets(repoRoot, limit = 5) {
const changelogPath = path.join(repoRoot, "CHANGELOG.md");
if (!fs.existsSync(changelogPath)) {
return [];
}
const lines = fs.readFileSync(changelogPath, "utf8").split(/\r?\n/);
const bullets = [];
const seen = new Set();
for (const line of lines) {
const match = line.match(/^\s*-\s+(.+)\s*$/);
if (!match) {
continue;
}
const bullet = match[1].replace(/\s+/g, " ").trim();
if (!bullet || seen.has(bullet)) {
continue;
}
seen.add(bullet);
bullets.push(bullet);
if (bullets.length >= limit) {
break;
}
}
return bullets;
}
function resolveUploadDesc({
repoRoot,
versionLabel = "",
maxLength = DEFAULT_MAX_LENGTH,
maxItems = 3,
} = {}) {
const root = repoRoot || process.cwd();
const fromGit = collectRecentCommitSubjects(root, maxItems);
const fromChangelog = collectRecentChangelogBullets(root, maxItems);
const parts = fromGit.length > 0 ? fromGit : fromChangelog;
if (parts.length === 0) {
const shortSha = String(versionLabel || "")
.trim()
.slice(0, 7);
return truncateDesc(
shortSha ? `CI upload ${shortSha}` : "CI upload",
maxLength,
);
}
// Fit as many summaries as possible within the WeChat remark limit.
const selected = [];
for (const part of parts) {
const candidate = [...selected, part].join("");
if ([...candidate].length > maxLength) {
if (selected.length === 0) {
return truncateDesc(part, maxLength);
}
break;
}
selected.push(part);
}
return truncateDesc(selected.join(""), maxLength);
}
module.exports = {
cleanCommitSubject,
collectRecentChangelogBullets,
collectRecentCommitSubjects,
resolveUploadDesc,
truncateDesc,
};