Skip to content

Commit 78cd3ce

Browse files
authored
remove Type after setting
removed the Type section from the issue body after the issue type has been detected and set automatically
1 parent 7db3e6a commit 78cd3ce

File tree

1 file changed

+108
-8
lines changed

1 file changed

+108
-8
lines changed

.github/workflows/sync-issue-type.yml

Lines changed: 108 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
let body = issue.body || "";
2020
2121
// ---------- 1) Extract selected Type from the "### Type" section ----------
22+
// Capture the whole Type block (from "### Type" until next heading or EOF)
2223
const typeBlockMatch = body.match(/(^|\n)#{2,}\s*Type\s*\n+([\s\S]*?)(?=\n#{2,}\s|\n*$)/i);
2324
let selected = null;
2425
if (typeBlockMatch) {
@@ -28,17 +29,23 @@ jobs:
2829
}
2930
3031
// ---------- 2) Map to official GitHub issue type ----------
32+
let typeMapped = false;
3133
if (selected) {
3234
const map = { bug: "bug", feature: "feature", task: "task" };
3335
const ghType = map[selected];
3436
if (ghType) {
35-
await github.request("PATCH /repos/{owner}/{repo}/issues/{issue_number}", {
36-
owner: context.repo.owner,
37-
repo: context.repo.repo,
38-
issue_number: issue.number,
39-
type: ghType,
40-
});
41-
core.info(`Set GitHub issue type to: ${ghType}`);
37+
try {
38+
await github.request("PATCH /repos/{owner}/{repo}/issues/{issue_number}", {
39+
owner: context.repo.owner,
40+
repo: context.repo.repo,
41+
issue_number: issue.number,
42+
type: ghType,
43+
});
44+
typeMapped = true;
45+
core.info(`Set GitHub issue type to: ${ghType}`);
46+
} catch (e) {
47+
core.warning(`Failed to set GitHub issue type: ${e.message}`);
48+
}
4249
}
4350
} else {
4451
core.info("No Type detected; skipping type mapping.");
@@ -61,4 +68,97 @@ jobs:
6168
const heading = m[2];
6269
const content = m[3];
6370
const end = start + full.length;
64-
return
71+
return { re, start, end, heading, content };
72+
}
73+
74+
// Remove entire section if content is exactly "_No response_"
75+
function removeIfNoResponse(headingPattern) {
76+
const sec = findSection(headingPattern);
77+
if (!sec) return false;
78+
if (/^\s*_No response_\s*$/i.test(sec.content.trim())) {
79+
newBody = newBody.slice(0, sec.start) + "\n" + newBody.slice(sec.end);
80+
core.info(`Removed empty section: ${headingPattern}`);
81+
return true;
82+
}
83+
return false;
84+
}
85+
86+
// Rename a heading only if section exists and we didn't remove it
87+
function renameHeading(onlyForType, fromPattern, toHeading) {
88+
if (selected !== onlyForType) return false;
89+
const sec = findSection(fromPattern);
90+
if (!sec) return false;
91+
const before = newBody.slice(0, sec.start);
92+
const after = newBody.slice(sec.end);
93+
const newSection =
94+
(newBody[sec.start - 1] === "\n" ? "\n" : "") +
95+
`### ${toHeading}\n` +
96+
sec.content;
97+
newBody = before + newSection + after;
98+
core.info(`Renamed heading to: ${toHeading}`);
99+
return true;
100+
}
101+
102+
// Generic rename (no type condition), e.g., to strip "(optional)"
103+
function renameHeadingAny(fromPattern, toHeading) {
104+
const sec = findSection(fromPattern);
105+
if (!sec) return false;
106+
const before = newBody.slice(0, sec.start);
107+
const after = newBody.slice(sec.end);
108+
const newSection =
109+
(newBody[sec.start - 1] === "\n" ? "\n" : "") +
110+
`### ${toHeading}\n` +
111+
sec.content;
112+
newBody = before + newSection + after;
113+
core.info(`Renamed heading to: ${toHeading}`);
114+
return true;
115+
}
116+
117+
// Remove a section by exact heading (no content check)
118+
function removeSection(headingPattern) {
119+
const sec = findSection(headingPattern);
120+
if (!sec) return false;
121+
newBody = newBody.slice(0, sec.start) + "\n" + newBody.slice(sec.end);
122+
core.info(`Removed section: ${headingPattern}`);
123+
return true;
124+
}
125+
126+
// ---------- 3) FIRST: remove empty sections ----------
127+
const bugPattern = String.raw`Bug\s+[-—]\s*Steps to Reproduce\s*&\s*Expected Result\s*\(only\s*if\s*Type\s*=\s*Bug\)`;
128+
const featurePattern = String.raw`Feature\s+[-—]\s*Solution\s*&\s*Expected Benefits\s*\(only\s*if\s*Type\s*=\s*Feature\)`;
129+
const bugRemoved = removeIfNoResponse(bugPattern);
130+
const featureRemoved = removeIfNoResponse(featurePattern);
131+
132+
// ---------- 4) THEN: tidy headings ----------
133+
if (!bugRemoved) {
134+
renameHeading("bug", bugPattern, "Steps to Reproduce & Expected Result");
135+
}
136+
if (!featureRemoved) {
137+
renameHeading("feature", featurePattern, "Solution & Expected Benefits");
138+
}
139+
// Strip "(optional)" from "Additional Context (optional)"
140+
renameHeadingAny(String.raw`Additional Context\s*\(optional\)`, "Additional Context");
141+
142+
// ---------- 5) FINALLY: remove the "Type" section if mapping succeeded ----------
143+
if (typeMapped && selected) {
144+
// Remove "### Type" section entirely (whatever its inner content)
145+
removeSection(String.raw`Type`);
146+
} else {
147+
core.info("Keeping 'Type' section (type not mapped or not detected).");
148+
}
149+
150+
// Normalize: collapse >2 blank lines into 1 for cleanliness
151+
newBody = newBody.replace(/\n{3,}/g, "\n\n");
152+
153+
// ---------- 6) Patch body if changed ----------
154+
if (newBody !== body) {
155+
await github.request("PATCH /repos/{owner}/{repo}/issues/{issue_number}", {
156+
owner: context.repo.owner,
157+
repo: context.repo.repo,
158+
issue_number: issue.number,
159+
body: newBody.trim() + "\n",
160+
});
161+
core.info("Issue body updated.");
162+
} else {
163+
core.info("No body changes needed.");
164+
}

0 commit comments

Comments
 (0)