Skip to content

Commit b2dcfd2

Browse files
authored
Update weekly content review workflow configuration
1 parent cc5a4a9 commit b2dcfd2

File tree

1 file changed

+126
-82
lines changed

1 file changed

+126
-82
lines changed
Lines changed: 126 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,136 @@
1-
name: Weekly Content Review and Comment
1+
name: Weekly Triage Issue Comment (Last 7 Days New Issues)
22

33
on:
44
schedule:
5-
- cron: '0 12 * * 1' # Every Monday at 12:00 UTC
5+
- cron: '27 13 * * 1' # 13:27 UTC every Monday (8:27 AM EST in November)
66
workflow_dispatch:
77

8+
permissions:
9+
issues: write
10+
contents: read
11+
812
jobs:
9-
review-issues-and-comment:
13+
weekly-triage-update:
1014
runs-on: ubuntu-latest
11-
permissions:
12-
issues: write
13-
contents: read
1415
steps:
15-
- name: Checkout repository (for context, not strictly necessary)
16-
uses: actions/checkout@v4
17-
18-
- name: Gather all open issues (API call)
19-
id: issue-list
20-
uses: octokit/[email protected]
21-
with:
22-
route: GET /repos/${{ github.repository }}/issues
23-
parameters: |
24-
state=open
25-
per_page=100
26-
27-
- name: Categorize issues and prepare comment
28-
id: summarize
16+
- name: Determine date context
17+
id: dates
2918
run: |
30-
echo "Parsing issues & categorizing for weekly review..."
31-
32-
echo '${{ steps.issue-list.outputs.data }}' > issues.json
33-
34-
COUNT_GRAMMAR=$(jq '[.[] | select(.title | test("grammar|spelling"; "i"))] | length' issues.json)
35-
COUNT_DEPRECATED=$(jq '[.[] | select(.title | test("deprecated|outdated|codeql|dependabot|copilot projects|projects|security"; "i"))] | length' issues.json)
36-
COUNT_SUGGESTED=$(jq '[.[] | select((.title | contains("[REPLACE_WITH_MODULE_TITLE]") | not) and (.title | test("update|improvement|copilot|prompt|exercise|action"; "i")))] | length' issues.json)
37-
COUNT_OTHER=$(jq '[.[] | select(.title | test("broken|support|help|unable|issue|not issued|confused|experience"; "i"))] | length' issues.json)
38-
COUNT_TEMPLATE=$(jq '[.[] | select(.title | contains("[REPLACE_WITH_MODULE_TITLE]"))] | length' issues.json)
39-
40-
REP_DEPRECATED=$(jq -r '[.[] | select(.title | test("deprecated|outdated|codeql|dependabot|copilot projects|projects|security"; "i"))][0].number // ""' issues.json)
41-
REP_SUGGESTED=$(jq -r '[.[] | select((.title | contains("[REPLACE_WITH_MODULE_TITLE]") | not) and (.title | test("update|improvement|copilot|prompt|exercise|action"; "i")))][0].number // ""' issues.json)
42-
REP_OTHER=$(jq -r '[.[] | select(.title | test("broken|support|help|unable|issue|not issued|confused|experience"; "i"))][0].number // ""' issues.json)
43-
REP_TEMPLATE=$(jq -r '[.[] | select(.title | contains("[REPLACE_WITH_MODULE_TITLE]"))][0].number // ""' issues.json)
44-
45-
THIS_WEEK=$(date -u +'%Y-%m-%d')
46-
COMMENT="**November 2025 Weekly Content Review Update**
47-
- Checked as of: $THIS_WEEK
48-
49-
**Issue category counts this week:**
50-
- Grammar/Spelling: $COUNT_GRAMMAR
51-
- Deprecated/Outdated: $COUNT_DEPRECATED"" (e.g., #$REP_DEPRECATED)""
52-
- Suggested Content Updates: $COUNT_SUGGESTED"" (e.g., #$REP_SUGGESTED)""
53-
- Other: $COUNT_OTHER"" (e.g., #$REP_OTHER)""
54-
- Template-Incomplete: $COUNT_TEMPLATE"" (e.g., #$REP_TEMPLATE)""
55-
56-
:octocat: :copilot: Mona (Copilot) has reviewed this update for a Hubber to take further action if needed.
57-
"
58-
59-
echo "$COMMENT" > comment.md
60-
echo "COMMENT_PATH=comment.md" >> $GITHUB_ENV
61-
62-
- name: Create weekly update comment on November review issue
63-
uses: peter-evans/create-or-update-comment@v4
19+
YEAR_MONTH=$(date -u +'%Y-%m')
20+
START_DATE=$(date -u -d '7 days ago' +'%Y-%m-%d')
21+
echo "year_month=$YEAR_MONTH" >> $GITHUB_OUTPUT
22+
echo "start_date=$START_DATE" >> $GITHUB_OUTPUT
23+
24+
- name: Locate current triage issue
25+
id: find-issue
26+
uses: actions/github-script@v7
6427
with:
65-
issue-number: 223
66-
body-path: ${{ env.COMMENT_PATH }}
67-
token: ${{ secrets.GITHUB_TOKEN }}
68-
69-
<!-- next steps
70-
71-
Step 4: Confirm the Workflow is Active
72-
73-
Go to your repo on GitHub.
74-
Click on the Actions tab.
75-
Look for "Weekly Content Review and Comment".
76-
You can also manually run it via “Run workflow” (since workflow_dispatch is enabled).
77-
Step 5: Check Comments on the November Review Issue
78-
79-
The job will comment on issue number 223 ("Monthly Content Review Process for MS Learn Repository") with the updated weekly summary.
80-
Each Monday (or after a manual run), review the new comment for the count update.
81-
Requirements
82-
83-
This workflow uses octokit/request-action for API calls, peter-evans/create-or-update-comment for posting, and requires jq (which is installed by default on GitHub’s runners).
84-
Make sure issue 223 exists and is the correct target for these updates.
85-
If issue numbers or logic changes, adjust the workflow accordingly.
86-
Customization Tips
87-
88-
Adjust the regex matching logic in the jq filters to better fit your issue naming conventions.
89-
For other months, duplicate the workflow and update the target issue number and month text as needed.
90-
You can customize the schedule (the cron line) to run on a different day/time or more frequently.
91-
92-
-->
28+
script: |
29+
const ym = '${{ steps.dates.outputs.year_month }}';
30+
const title = `GitHub Triage: ${ym}`;
31+
32+
async function findIssue(title) {
33+
const perPage = 100;
34+
for (let page = 1; page < 50; page++) {
35+
const { data } = await github.rest.issues.listForRepo({
36+
owner: context.repo.owner,
37+
repo: context.repo.repo,
38+
state: 'open',
39+
per_page: perPage,
40+
page
41+
});
42+
if (!data.length) break;
43+
const hit = data.find(i => i.title === title);
44+
if (hit) return hit;
45+
if (data.length < perPage) break;
46+
}
47+
return null;
48+
}
49+
50+
const issue = await findIssue(title);
51+
if (!issue) {
52+
core.setFailed(`Current triage issue "${title}" not found. Run monthly triage workflow first.`);
53+
return;
54+
}
55+
core.setOutput('issue_number', issue.number);
56+
core.setOutput('issue_title', issue.title);
57+
58+
- name: Collect new issues (last 7 days)
59+
id: search
60+
uses: actions/github-script@v7
61+
with:
62+
script: |
63+
const startDate = '${{ steps.dates.outputs.start_date }}';
64+
const q = `repo:${context.repo.owner}/${context.repo.repo} is:issue is:open created:>=${startDate}`;
65+
const perPage = 100;
66+
let page = 1;
67+
let allItems = [];
68+
69+
while (true) {
70+
const resp = await github.rest.search.issuesAndPullRequests({
71+
q,
72+
per_page: perPage,
73+
page
74+
});
75+
const items = resp.data.items || [];
76+
allItems = allItems.concat(items);
77+
if (items.length < perPage || allItems.length >= 1000) break;
78+
page++;
79+
}
80+
81+
core.setOutput('raw_count', allItems.length);
82+
core.setOutput('items_json', JSON.stringify(allItems));
83+
84+
- name: Build and post comment
85+
uses: actions/github-script@v7
86+
with:
87+
script: |
88+
const issueNumber = Number('${{ steps.find-issue.outputs.issue_number }}');
89+
const startDate = '${{ steps.dates.outputs.start_date }}';
90+
const ym = '${{ steps.dates.outputs.year_month }}';
91+
const items = JSON.parse('${{ steps.search.outputs.items_json }}');
92+
const daysBack = 7;
93+
94+
const reTemplate = /\[REPLACE_WITH_MODULE_TITLE\]|N\/?A/i;
95+
const reGrammar = /\b(grammar|spelling|typo|misspell(ed)?|proofread)\b/i;
96+
const reDeprecated = /\b(deprecated|outdated|codeql|dependabot|projects?|security)\b/i;
97+
const reSuggested = /\b(update|improvement|improve|copilot|prompt|exercise|action|module|enterprise)\b/i;
98+
const reOther = /\b(broken|support|help|unable|issue|not issued|confused|experience|certificate)\b/i;
99+
100+
function categorize(title) {
101+
if (reTemplate.test(title)) return 'template';
102+
if (reGrammar.test(title)) return 'grammar';
103+
if (reDeprecated.test(title)) return 'deprecated';
104+
if (!reTemplate.test(title) && reSuggested.test(title)) return 'suggested';
105+
if (reOther.test(title)) return 'other';
106+
if (/update|request/i.test(title) && !reTemplate.test(title)) return 'suggested';
107+
return 'other';
108+
}
109+
110+
const buckets = { grammar: [], deprecated: [], suggested: [], other: [], template: [] };
111+
for (const i of items) buckets[categorize(i.title)].push(i);
112+
113+
const rep = arr => arr.length ? `#${arr[0].number}` : '';
114+
const todayStr = new Date().toISOString().split('T')[0];
115+
const allIssueLines = items.map(i => `- #${i.number}`).join('\n');
116+
117+
let md = `**${ym} Weekly Triage Update (Issues opened since ${startDate})**\n`;
118+
md += `- Checked as of: ${todayStr} (UTC)\n\n`;
119+
md += `**Counts (last ${daysBack} days):**\n`;
120+
md += `- Grammar/Spelling: ${buckets.grammar.length} ${rep(buckets.grammar)}\n`;
121+
md += `- Deprecated/Outdated: ${buckets.deprecated.length} ${rep(buckets.deprecated)}\n`;
122+
md += `- Suggested Content Updates: ${buckets.suggested.length} ${rep(buckets.suggested)}\n`;
123+
md += `- Other: ${buckets.other.length} ${rep(buckets.other)}\n`;
124+
md += `- Template-Incomplete: ${buckets.template.length} ${rep(buckets.template)}\n\n`;
125+
md += `_Total new issues: ${items.length}_\n\n`;
126+
md += `**Issue References (Last 7 Days):**\n${allIssueLines}\n\n`;
127+
md += `:octocat: :copilot: Mona (Copilot) has reviewed these new issues.\n`;
128+
md += `<!-- Search query: repo:${context.repo.owner}/${context.repo.repo} is:issue is:open created:>=${startDate} -->\n`;
129+
130+
await github.rest.issues.createComment({
131+
owner: context.repo.owner,
132+
repo: context.repo.repo,
133+
issue_number: issueNumber,
134+
body: md
135+
});
136+
core.notice(`Posted weekly triage update to #${issueNumber}.`);

0 commit comments

Comments
 (0)