Skip to content

Discussion TODOs to Issues (25.09.10 Updated) #18

Discussion TODOs to Issues (25.09.10 Updated)

Discussion TODOs to Issues (25.09.10 Updated) #18

name: Discussion TODOs to Issues (25.09.10 Updated)
on:
discussion:
types: [created]
permissions:
issues: write
discussions: read
jobs:
discussion_todos_to_issues:
runs-on: ubuntu-latest
steps:
- name: Create issues from TODOs and link as sub-issues
uses: actions/github-script@v7
with:
script: |
const discussion = context.payload.discussion;
if (discussion.category.name !== "ํšŒ์˜๋ก") {
console.log("์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ํšŒ์˜๋ก์ด ์•„๋‹ˆ๋ฏ€๋กœ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.");
return;
}
const lines = discussion.body.split('\n');
let inTodoSection = false;
let currentAssignee = null;
let parentIssueData = null;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (/^#+\s*TODO/i.test(line.trim())) {
inTodoSection = true;
currentAssignee = null;
parentIssueData = null;
continue;
}
if (inTodoSection && /^#+\s*\S+/.test(line.trim()) && !/^#+\s*TODO/i.test(line.trim())) {
inTodoSection = false;
currentAssignee = null;
parentIssueData = null;
continue;
}
if (!inTodoSection) continue;
// ๋‹ด๋‹น์ž๋ฅผ ์ฐพ๋Š” ์ •๊ทœ์‹ (์—ฌ๋Ÿฌ ๋ช… ์ง€์›)
const assigneeMatches = line.trim().match(/@([\w-]+)/g);
if (assigneeMatches) {
// ๋ชจ๋“  ๋‹ด๋‹น์ž ์ถ”์ถœ
currentAssignee = assigneeMatches.map(match => {
const userMatch = match.match(/@([\w-]+)/);
return userMatch ? userMatch[1] : null;
}).filter(user => user !== null);
parentIssueData = null;
continue;
}
const todoMatch = line.match(/^(\s*)- \[ \] (.+)/);
if (todoMatch && currentAssignee) {
const indent = todoMatch[1].length;
const todoText = todoMatch[2].trim();
// ๋‚ด์šฉ์ด ์—†๋Š” ์ฒดํฌ๋ฐ•์Šค๋Š” ์ด์Šˆ๋กœ ๋งŒ๋“ค์ง€ ์•Š์Œ
if (!todoText) continue;
if (indent === 0) {
// ๋ถ€๋ชจ ์ด์Šˆ ์ƒ์„ฑ
const issue = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: todoText,
body: `์ด ์ด์Šˆ๋Š” ํšŒ์˜๋ก Discussion์—์„œ ์ž๋™ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\n\n[์›๋ณธ Discussion ๋งํฌ](${discussion.html_url})`,
assignees: currentAssignee,
labels: ["ํšŒ์˜๋ก-TODO"]
});
parentIssueData = issue.data;
} else if (indent >= 2 && parentIssueData) {
// 1. sub-issue ์ƒ์„ฑ
const subIssue = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: todoText,
body: `๋ถ€๋ชจ ์ด์Šˆ: #${parentIssueData.number}\n\n์ด ์ด์Šˆ๋Š” ํšŒ์˜๋ก Discussion์—์„œ ์ž๋™ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.\n\n[์›๋ณธ Discussion ๋งํฌ](${discussion.html_url})`,
assignees: currentAssignee,
labels: ["ํšŒ์˜๋ก-TODO", "sub-issue"]
});
// 2. ๋ถ€๋ชจ ์ด์Šˆ ๋ณธ๋ฌธ์— sub-issue๋ฅผ ์ฒดํฌ๋ฐ•์Šค๋กœ ์ถ”๊ฐ€ํ•˜์—ฌ ์—…๋ฐ์ดํŠธ
const newBody = parentIssueData.body + `\n- [ ] #${subIssue.data.number}`;
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: parentIssueData.number,
body: newBody
});
parentIssueData.body = newBody;
}
}
}