Skip to content

Commit af03bb2

Browse files
authored
Merge pull request community#166243 from community/ebndev-2025-07-15
Update actions_labeller.yml to improve discussion handling...
2 parents 55813f9 + c46b8f9 commit af03bb2

File tree

1 file changed

+63
-55
lines changed

1 file changed

+63
-55
lines changed

.github/workflows/actions_labeller.yml

Lines changed: 63 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ jobs:
99
if: ${{ contains(github.event.discussion.category.name, 'Actions') }}
1010
runs-on: ubuntu-latest
1111
env:
12-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Global authentication for gh CLI
12+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1313
steps:
1414
- name: Get discussion body html
1515
id: get_discussion_body_html
16-
env:
16+
env:
1717
OWNER: ${{ github.repository_owner }}
1818
REPO: ${{ github.event.repository.name }}
1919
DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
@@ -30,9 +30,8 @@ jobs:
3030
3131
echo 'DISCUSSION_BODY_HTML='$(jq -r '.data.repository.discussion.bodyHTML' discussion_data.json) >> $GITHUB_ENV
3232
echo 'DISCUSSION_ID='$(jq -r '.data.repository.discussion.id' discussion_data.json) >> $GITHUB_ENV
33-
34-
- run: npm install jsdom
3533
34+
- run: npm install jsdom dompurify
3635

3736
- name: Extract Title and Body Text
3837
id: extract_text
@@ -48,7 +47,6 @@ jobs:
4847
const { DISCUSSION_BODY_HTML } = process.env;
4948
const fragment = JSDOM.fragment(DISCUSSION_BODY_HTML);
5049
let body = '';
51-
// Find all <h3> and <p> pairs
5250
const h3s = Array.from(fragment.querySelectorAll('h3'));
5351
h3s.forEach(h3 => {
5452
const heading = h3.textContent.trim();
@@ -59,7 +57,6 @@ jobs:
5957
body = p.textContent.trim();
6058
}
6159
});
62-
// Remove leading/trailing quotes from body
6360
body = body.replace(/^['\"]+|['\"]+$/g, '');
6461
const title = process.env.DISCUSSION_TITLE || '';
6562
core.info(`Extracted title: ${title}`);
@@ -69,6 +66,8 @@ jobs:
6966
- name: Extract Primary and Secondary Topic Areas
7067
id: extract_topics
7168
uses: actions/github-script@v6
69+
env:
70+
DISCUSSION_BODY_HTML: ${{ env.DISCUSSION_BODY_HTML }}
7271
with:
7372
result-encoding: string
7473
script: |
@@ -78,11 +77,9 @@ jobs:
7877
const fragment = JSDOM.fragment(DISCUSSION_BODY_HTML);
7978
let primary = '';
8079
let secondary = '';
81-
// Find all <h3> and <p> pairs (form headings as h3, answers as p)
8280
const h3s = Array.from(fragment.querySelectorAll('h3'));
8381
h3s.forEach(h3 => {
8482
const heading = h3.textContent.trim();
85-
// Look for the next <p> sibling after each heading
8683
let p = h3.nextElementSibling;
8784
while (p && p.tagName !== 'P') p = p.nextElementSibling;
8885
if (!p) return;
@@ -100,78 +97,87 @@ jobs:
10097
- name: Auto-label by keyword search
10198
id: auto_label_keywords
10299
uses: actions/github-script@v6
100+
env:
101+
EXTRACT_TEXT_RESULT: ${{ steps.extract_text.outputs.result }}
103102
with:
104103
result-encoding: string
105104
script: |
106-
// Keyphrase to label mapping
105+
const jsdom = require('jsdom');
106+
const { JSDOM } = jsdom;
107+
const createDOMPurify = require('dompurify');
108+
const window = (new JSDOM('')).window;
109+
const DOMPurify = createDOMPurify(window);
110+
107111
const labelMap = [
108112
{
109113
label: 'Workflow Deployment',
110114
keywords: [
111-
"deployment error",
112-
"publish artifact",
113-
"release failure",
114-
"deployment target",
115-
"github pages",
116-
"deployment issue",
117-
"release workflow",
118-
"target environment"
119-
]
115+
"deployment error",
116+
"publish artifact",
117+
"release failure",
118+
"deployment target",
119+
"github pages",
120+
"deployment issue",
121+
"release workflow",
122+
"target environment"
123+
]
120124
},
121125
{
122126
label: 'Workflow Configuration',
123127
keywords: [
124-
"yaml syntax",
125-
"job dependency",
126-
"setup error",
127-
"workflow file",
128-
"configuration issue",
129-
"matrix strategy",
130-
"define env",
131-
"secret management",
132-
"environment setup",
133-
"config job"
134-
]
128+
"yaml syntax",
129+
"job dependency",
130+
"setup error",
131+
"workflow file",
132+
"configuration issue",
133+
"matrix strategy",
134+
"define env",
135+
"secret management",
136+
"environment setup",
137+
"config job"
138+
]
135139
},
136140
{
137141
label: 'Schedule & Cron Jobs',
138142
keywords: [
139-
"cron job",
140-
"scheduled workflow",
141-
"timing issue",
142-
"delay trigger",
143-
"timezone error",
144-
"periodic run",
145-
"recurring schedule",
146-
"interval workflow",
147-
"scheduled trigger",
148-
"cron expression"
149-
]
143+
"cron job",
144+
"scheduled workflow",
145+
"timing issue",
146+
"delay trigger",
147+
"timezone error",
148+
"periodic run",
149+
"recurring schedule",
150+
"interval workflow",
151+
"scheduled trigger",
152+
"cron expression"
153+
]
150154
},
151155
{
152156
label: 'Metrics & Insights',
153157
keywords: [
154-
"usage metrics",
155-
"performance trend",
156-
"analytics graph",
157-
"stats dashboard",
158-
"timeseries graph",
159-
"insight report",
160-
"metric tracking",
161-
"workflow analytics",
162-
"performance metric",
163-
"statistics report"
164-
]
158+
"usage metrics",
159+
"performance trend",
160+
"analytics graph",
161+
"stats dashboard",
162+
"timeseries graph",
163+
"insight report",
164+
"metric tracking",
165+
"workflow analytics",
166+
"performance metric",
167+
"statistics report"
168+
]
165169
}
166170
];
167171
const miscLabel = 'Misc';
168172
let title = '';
169173
let body = '';
170174
try {
171-
const parsed = JSON.parse(`${{ steps.extract_text.outputs.result }}`);
172-
title = parsed.title || '';
173-
body = parsed.body || '';
174-
} catch (e) {}
175+
const parsed = JSON.parse(process.env.EXTRACT_TEXT_RESULT);
176+
title = DOMPurify.sanitize(parsed.title || '', { ALLOWED_TAGS: [], ALLOWED_ATTR: [] }).trim();
177+
body = DOMPurify.sanitize(parsed.body || '', { ALLOWED_TAGS: [], ALLOWED_ATTR: [] }).trim();
178+
} catch (e) {
179+
core.error('Failed to parse or sanitize discussion text: ' + e.message);
180+
}
175181
const text = (title + ' ' + body).toLowerCase();
176182
let foundLabel = miscLabel;
177183
core.info(`Auto-label debug: text to match: '${text}'`);
@@ -188,6 +194,7 @@ jobs:
188194
}
189195
core.info(`Auto-label debug: selected label: '${foundLabel}'`);
190196
return foundLabel;
197+
191198
- name: Fetch label ID for primary topic
192199
id: fetch_primary_label_id
193200
env:
@@ -239,6 +246,7 @@ jobs:
239246
240247
SECONDARY_LABEL_ID=$(jq -r '.data.repository.labels.edges[0]?.node?.id // empty' secondary_label_data.json)
241248
echo "SECONDARY_LABEL_ID=$SECONDARY_LABEL_ID" >> $GITHUB_ENV
249+
242250
- name: Fetch label ID for auto-label
243251
id: fetch_auto_label_id
244252
env:

0 commit comments

Comments
 (0)