Skip to content

[Character Bug]: 野营晴摸头后会闪(顿)一下 #5

[Character Bug]: 野营晴摸头后会闪(顿)一下

[Character Bug]: 野营晴摸头后会闪(顿)一下 #5

name: Auto Replace Issue Category Labels
on:
issues:
types: [opened, edited]
permissions:
issues: write
contents: read
jobs:
replace-category-label:
if: ${{ github.event.action == 'opened' || github.event.changes.body != null }}
runs-on: ubuntu-latest
steps:
- name: Replace category labels based on issue form
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const body = issue.body || "";
const issueNumber = issue.number;
const currentLabels = (issue.labels || []).map(label =>
typeof label === "string" ? label : label.name
);
const characterCategoryLabels = [
"character:bug:metadata",
"character:bug:opening-animation",
"character:bug:interaction-animation",
"character:bug:animation-blend",
"character:bug:subtitle",
"character:bug:bgm",
"character:bug:voice",
"character:bug:vfx",
"character:bug:other"
];
const softwareCategoryLabels = [
"software:bug:ui-interaction",
"software:bug:ui-animation",
"software:bug:logic",
"software:bug:function",
"software:bug:performance",
"software:bug:other",
"software:bug:ui-interaction",
"software:bug:ui-animation",
"software:bug:logic",
"software:bug:function",
"software:bug:performance",
"software:bug:other",
"software:feat:logic-function",
"software:feat:ui-function",
"software:feat:logic-optimization",
"software:feat:setting"
];
const characterMap = {
"元数据异常": "character:bug:metadata",
"开场动画异常": "character:bug:opening-animation",
"交互动画异常": "character:bug:interaction-animation",
"动画混合异常": "character:bug:animation-blend",
"字幕异常": "character:bug:subtitle",
"背景音乐异常": "character:bug:bgm",
"语音异常": "character:bug:voice",
"视效异常": "character:bug:vfx",
"其他": "character:bug:other"
};
const softwareMap = {
"UI 交互异常": "software:bug:ui-interaction",
"UI 动画异常": "software:bug:ui-animation",
"操作逻辑异常": "software:bug:logic",
"功能异常": "software:bug:function",
"性能异常": "software:bug:performance",
"其他": "software:bug:other"
};
const softwareFeatureMap = {
"逻辑功能": "software:feat:logic-function",
"UI 功能": "software:feat:ui-function",
"逻辑优化": "software:feat:logic-optimization",
"设置条目": "software:feat:setting"
};
const labelMetadata = {
"software:bug:ui-interaction": {
color: "d73a4a",
description: "软件缺陷:UI 交互异常。"
},
"software:bug:ui-animation": {
color: "d73a4a",
description: "软件缺陷:UI 动画异常。"
},
"software:bug:logic": {
color: "d73a4a",
description: "软件缺陷:操作逻辑异常。"
},
"software:bug:function": {
color: "d73a4a",
description: "软件缺陷:功能异常。"
},
"software:bug:performance": {
color: "d73a4a",
description: "软件缺陷:性能异常。"
},
"software:bug:other": {
color: "d73a4a",
description: "软件缺陷:其他软件异常。"
},
"software:feat:logic-function": {
color: "a2eeef",
description: "软件建议:逻辑功能。"
},
"software:feat:ui-function": {
color: "a2eeef",
description: "软件建议:UI 功能。"
},
"software:feat:logic-optimization": {
color: "a2eeef",
description: "软件建议:逻辑优化。"
},
"software:feat:setting": {
color: "a2eeef",
description: "软件建议:设置条目。"
}
};
function extractField(fieldName) {
const escaped = fieldName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const regex = new RegExp(
`###\\s*${escaped}\\s*\\n+([\\s\\S]*?)(?=\\n###\\s|$)`,
"m"
);
const match = body.match(regex);
return match ? match[1].trim() : "";
}
async function removeLabelIfExists(labelName) {
if (!currentLabels.includes(labelName)) return;
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
name: labelName
});
core.info(`Removed label: ${labelName}`);
} catch (error) {
core.warning(`Failed to remove label "${labelName}": ${error.message}`);
}
}
async function addLabelIfMissing(labelName) {
if (!labelName) return;
if (currentLabels.includes(labelName)) {
core.info(`Label already exists: ${labelName}`);
return;
}
await ensureLabelExists(labelName);
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
labels: [labelName]
});
core.info(`Added label: ${labelName}`);
}
async function ensureLabelExists(labelName) {
const metadata = labelMetadata[labelName];
if (!metadata) return;
try {
await github.rest.issues.getLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: labelName
});
} catch (error) {
if (error.status !== 404) {
throw error;
}
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: labelName,
color: metadata.color,
description: metadata.description
});
core.info(`Created label: ${labelName}`);
}
}
const issueType = extractField("问题类型");
core.info(`Extracted 问题类型: ${issueType || "(empty)"}`);
const suggestionType = extractField("建议类型");
core.info(`Extracted 建议类型: ${suggestionType || "(empty)"}`);
const isCharacter = currentLabels.includes("character");
const isSoftware = currentLabels.includes("software");
const isFeature = currentLabels.includes("enhancement");
if (!isCharacter && !isSoftware) {
core.info('Skip: neither "character" nor "software" label found.');
return;
}
if (isCharacter && isSoftware) {
core.warning('Issue has both "character" and "software" labels. Skip to avoid ambiguity.');
return;
}
if (isCharacter) {
if (!issueType) {
core.info('Skip: character issue form does not contain a bug category field.');
return;
}
const newLabel = characterMap[issueType];
if (!newLabel) {
core.warning(`No mapped character label for issue type: ${issueType}`);
return;
}
for (const label of characterCategoryLabels) {
if (label !== newLabel) {
await removeLabelIfExists(label);
}
}
await addLabelIfMissing(newLabel);
return;
}
if (isSoftware) {
const newLabel = isFeature ? softwareFeatureMap[suggestionType] : softwareMap[issueType];
if (!newLabel) {
core.warning(`No mapped software label for category: ${isFeature ? suggestionType : issueType}`);
return;
}
for (const label of softwareCategoryLabels) {
if (label !== newLabel) {
await removeLabelIfExists(label);
}
}
await addLabelIfMissing(newLabel);
return;
}