Skip to content

Commit 83d14a9

Browse files
authored
Merge branch 'main' into fix/flaky-submit-msg.e2e
2 parents 5e83808 + 8396dac commit 83d14a9

66 files changed

Lines changed: 935 additions & 313 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/scripts/bot-assignment-check.sh

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
#!/bin/bash
22
set -Eeuo pipefail
33

4+
# Configuration for labels (overridable from workflow env)
5+
MENTOR_LABEL="${MENTOR_LABEL:-notes: mentor-duty}"
6+
if [ -z "${MENTOR_LABEL}" ]; then
7+
echo "Error: Missing required environment variable (MENTOR_LABEL)." >&2
8+
exit 1
9+
fi
10+
411
# Validate required env vars
512
if [ -z "${ASSIGNEE:-}" ] || [ -z "${ISSUE_NUMBER:-}" ] || [ -z "${REPO:-}" ]; then
613
echo "Error: Missing required environment variables (ASSIGNEE, ISSUE_NUMBER, REPO)."
@@ -36,20 +43,20 @@ issue_has_gfi() {
3643
}
3744

3845
# Count open assignments for a user
39-
# For triage users (mentors), excludes issues with 'mentor-duty' label
46+
# For triage users (mentors), excludes issues with '${MENTOR_LABEL}' label
4047
# This allows mentors to be assigned to mentorship issues without consuming their assignment limit
4148
assignments_count() {
4249
local permission="${1:-none}"
4350

4451
if [[ "$permission" == "triage" ]]; then
45-
echo "Triage user detected — excluding mentor-duty issues from count." >&2
46-
# For triage users, exclude issues with 'mentor-duty' label
52+
echo "Triage user detected — excluding ${MENTOR_LABEL} issues from count." >&2
53+
# For triage users, exclude issues with the configured mentor label
4754
gh api "repos/${REPO}/issues?per_page=100&page=1" \
4855
-f assignee="${ASSIGNEE}" \
4956
-f state=open \
50-
--jq '.[]
57+
--jq --arg mentor_label "$MENTOR_LABEL" '.[]
5158
| select(.pull_request == null)
52-
| select(any(.labels[]; .name == "mentor-duty") | not)
59+
| select(any(.labels[]; .name == $mentor_label) | not)
5360
| .number' | grep -c . || echo 0
5461
else
5562
# For non-triage users, count all open assignments

.github/scripts/bot-p0-issues-notify-team.js

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,37 @@
11
// Script to notify the team when a P0 issue is created.
22

3+
const CRITICAL_LABEL = 'priority: critical';
34
const marker = '<!-- P0 Issue Notification -->';
45

5-
async function notifyTeam(github, owner, repo, issue, marker) {
6-
const comment = `${marker} :rotating_light: Attention Team :rotating_light:
6+
async function notifyTeam(github, owner, repo, issue, marker) {
7+
const safeTitle = String(issue.title || '(no title)')
8+
.replace(/[\r\n]+/g, ' ')
9+
.replace(/@/g, '@\u200b')
10+
.trim();
11+
12+
const comment = `${marker} :rotating_light: Attention Team :rotating_light:
713
@hiero-ledger/hiero-sdk-python-maintainers @hiero-ledger/hiero-sdk-python-committers @hiero-ledger/hiero-sdk-python-triage
814
9-
A new P0 issue has been created: #${issue.number} - ${issue.title || '(no title)'}
15+
A new critical priority issue has been created: #${issue.number} - ${safeTitle}
1016
Please prioritize this issue accordingly.
1117
1218
Best Regards,
1319
Automated Notification System`;
1420

15-
try {
16-
await github.rest.issues.createComment({
17-
owner,
18-
repo,
19-
issue_number: issue.number,
20-
body: comment,
21-
});
22-
console.log(`Notified team about P0 issue #${issue.number}`);
23-
return true;
24-
} catch (commentErr) {
25-
console.log(`Failed to notify team about P0 issue #${issue.number}:`, commentErr.message || commentErr);
26-
return false;
27-
}
21+
try {
22+
await github.rest.issues.createComment({
23+
owner,
24+
repo,
25+
issue_number: issue.number,
26+
body: comment,
27+
});
28+
console.log(`Notified team about ${CRITICAL_LABEL} issue #${issue.number}`);
29+
return true;
30+
} catch (commentErr) {
31+
console.log(`Failed to notify team about ${CRITICAL_LABEL} issue #${issue.number}:`, commentErr.message || commentErr);
32+
return false;
2833
}
34+
}
2935

3036
module.exports = async ({ github, context }) => {
3137
try {
@@ -34,8 +40,8 @@ module.exports = async ({ github, context }) => {
3440

3541
// Validations
3642
if (!issue?.number) return console.log('No issue in payload');
37-
if (label?.name?.toLowerCase() !== 'p0') return;
38-
if (!issue.labels?.some(l => l?.name?.toLowerCase() === 'p0')) return;
43+
if (label?.name?.toLowerCase() !== CRITICAL_LABEL.toLowerCase()) return;
44+
if (!issue.labels?.some((l) => l?.name?.toLowerCase() === CRITICAL_LABEL.toLowerCase())) return;
3945

4046
// Check for existing comment
4147
const comments = await github.paginate(github.rest.issues.listComments, {
@@ -44,7 +50,7 @@ module.exports = async ({ github, context }) => {
4450
if (comments.some(c => c.body?.includes(marker))) {
4551
return console.log(`Notification already exists for #${issue.number}`);
4652
}
47-
// Post notification
53+
// Post notification
4854
await notifyTeam(github, owner, repo, issue, marker);
4955

5056
console.log('=== Summary ===');

.github/scripts/coderabbit_plan_trigger.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@
22

33
const CODERABBIT_MARKER = '<!-- CodeRabbit Plan Trigger -->';
44

5-
async function triggerCodeRabbitPlan(github, owner, repo, issue, marker = CODERABBIT_MARKER, isDryRun = false) {
5+
async function triggerCodeRabbitPlan(github, owner, repo, issue, marker = CODERABBIT_MARKER) {
66
const comment = `${marker} @coderabbitai plan`;
77

8-
if (isDryRun) {
9-
console.log(`[DRY RUN] Would trigger CodeRabbit plan for issue #${issue.number}`);
10-
return true;
11-
}
12-
138
try {
149
await github.rest.issues.createComment({
1510
owner,
@@ -105,11 +100,8 @@ async function main({ github, context }) {
105100
return console.log(`CodeRabbit plan already triggered for #${issue.number}`);
106101
}
107102

108-
// Check for dry run (default to true if not specified, for safety)
109-
const isDryRun = (process.env.DRY_RUN || 'true').toLowerCase() === 'true';
110-
111103
// Post CodeRabbit plan trigger
112-
await triggerCodeRabbitPlan(github, owner, repo, issue, CODERABBIT_MARKER, isDryRun);
104+
await triggerCodeRabbitPlan(github, owner, repo, issue, CODERABBIT_MARKER);
113105

114106
logSummary(owner, repo, issue);
115107
} catch (err) {

.github/scripts/cron-admin-update-spam-list.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,19 @@
88
*/
99

1010
const fs = require('fs').promises;
11+
const { LABEL_AUTOMATED } = require('./labels.js');
1112

1213
const SPAM_LIST_PATH = '.github/spam-list.txt';
1314
const dryRun = (process.env.DRY_RUN || 'false').toString().toLowerCase() === 'true';
1415

16+
/**
17+
* These constants control the GitHub label names used by the spam automation.
18+
* To rename labels, update only the constant values here.
19+
* Ensure corresponding labels exist in the GitHub repository settings.
20+
*/
21+
const LABEL_SPAM = 'notes: spam';
22+
const LABEL_SPAM_LIST_UPDATE = 'notes: spam-list-update';
23+
1524
// Load current spam list and compute updates based on spam vs rehabilitated users
1625

1726
async function computeSpamListUpdates(spamUsers, rehabilitatedUsers) {
@@ -121,7 +130,7 @@ module.exports = async ({github, context, core}) => {
121130
const searches = [
122131
{
123132
name: 'spam PRs',
124-
query: `repo:${owner}/${repo} is:pr is:closed -is:merged label:spam`,
133+
query: `repo:${owner}/${repo} is:pr is:closed -is:merged label:"${LABEL_SPAM}"`,
125134
process: async (pr) => {
126135
if (!pr.user?.login) {
127136
console.log(`Skipping PR #${pr.number}: user account unavailable`);
@@ -208,7 +217,7 @@ module.exports = async ({github, context, core}) => {
208217
const { data: existing } = await github.rest.issues.listForRepo({
209218
owner,
210219
repo,
211-
labels: 'spam-list-update',
220+
labels: LABEL_SPAM_LIST_UPDATE,
212221
state: 'open',
213222
per_page: 1
214223
});
@@ -221,7 +230,7 @@ module.exports = async ({github, context, core}) => {
221230
repo,
222231
title,
223232
body,
224-
labels: ['spam-list-update', 'automated']
233+
labels: [LABEL_SPAM_LIST_UPDATE, LABEL_AUTOMATED]
225234
});
226235
console.log('Issue created successfully');
227236
}

.github/scripts/labels.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Central location for label definitions to facilitate future changes.
3+
* This file serves as the single source of truth for all GitHub label names used by automated workflows.
4+
*/
5+
const LABEL_BROKEN_MARKDOWN_LINKS = 'notes: broken markdown links';
6+
const LABEL_AUTOMATED = 'notes: automated';
7+
8+
module.exports = {
9+
LABEL_BROKEN_MARKDOWN_LINKS,
10+
LABEL_AUTOMATED
11+
};
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env node
2+
3+
const { execSync } = require("child_process");
4+
const fs = require("fs");
5+
6+
// These are the directories we want to check for correct naming
7+
const TEST_DIRS = ["tests/unit", "tests/integration", "tests/tck", "tests/fuzz"];
8+
9+
// These are the excluded paths and file names inside the TEST_DIRS
10+
const IGNORED = ["tests/fuzz/support"];
11+
const EXCEPTIONS = ["conftest.py", "__init__.py", "init.py", "mock_server.py", "utils.py"];
12+
13+
// Collect naming errors to report at the end
14+
const nameErrors = [];
15+
16+
// Use "git ls-files" to get all tracked files in the repository
17+
const output = execSync("git ls-files", { encoding: "utf-8" });
18+
// Split output into lines and filter out empty lines for easy manipulation
19+
// e.g. output = "tests/unit/my_test.py\ntests/integration/other_test.py"
20+
const files = output.split("\n").filter(Boolean);
21+
22+
for (const file of files) {
23+
// --- PATH FILTERING ---
24+
// Skip files that are not in any of the specified test directories
25+
if (!TEST_DIRS.some(dir => file.startsWith(dir))) continue;
26+
27+
// Skip ignored paths (e.g. helpers)
28+
if (IGNORED.some(path => file.startsWith(path))) continue;
29+
30+
// Now we have file paths that we need to check for correct naming
31+
// e.g. file = "tests/unit/my_test.py"
32+
33+
// --- Correct PATH now apply NAMING checks ---
34+
35+
// Extract the file name from the path
36+
// e.g. from file = "tests/unit/my_test.py" get name = "my_test.py"
37+
const name = file.split("/").pop();
38+
39+
// Skip allowed special files
40+
if (EXCEPTIONS.includes(name)) continue;
41+
42+
// Enforce naming rule on files
43+
if (!name.endsWith("_test.py")) {
44+
console.error(`Invalid test file name: ${file}`);
45+
console.error(`::error file=${file}::Must end with '_test.py'`);
46+
nameErrors.push(file);
47+
}
48+
}
49+
50+
// Generate a summary of the results for the GitHub Actions UI
51+
const summaryPath = process.env.GITHUB_STEP_SUMMARY;
52+
53+
if (summaryPath) {
54+
let summary = `## 🧪 Test File Naming Check\n\n`;
55+
56+
if (nameErrors.length === 0) {
57+
summary += `✅ All test files are correctly named\n`;
58+
} else {
59+
// Counts and lists all the incorrectly named test files
60+
summary += `❌ Found ${nameErrors.length} incorrectly named test files:\n\n`;
61+
nameErrors.forEach(f => {
62+
summary += `- \`${f}\`\n`;
63+
});
64+
}
65+
66+
fs.appendFileSync(summaryPath, summary);
67+
}
68+
69+
// Fail job if needed
70+
if (nameErrors.length > 0) {
71+
process.exit(1);
72+
}

.github/scripts/pr-check-test-files.sh

Lines changed: 0 additions & 93 deletions
This file was deleted.

.github/workflows/bot-advanced-check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
runs-on: hl-sdk-py-lin-md
2929
steps:
3030
- name: Harden the runner (Audit all outbound calls)
31-
uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0
31+
uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
3232
with:
3333
egress-policy: audit
3434

.github/workflows/bot-assignment-check.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: hl-sdk-py-lin-md
1313
steps:
1414
- name: Harden the runner
15-
uses: step-security/harden-runner@6c3c2f2c1c457b00c10c4848d6f5491db3b629df # v2.18.0
15+
uses: step-security/harden-runner@8d3c67de8e2fe68ef647c8db1e6a09f647780f40 # v2.19.0
1616
with:
1717
egress-policy: audit
1818

@@ -25,6 +25,7 @@ jobs:
2525
ASSIGNEE: ${{ github.event.assignee.login }}
2626
ISSUE_NUMBER: ${{ github.event.issue.number }}
2727
REPO: ${{ github.repository }}
28+
MENTOR_LABEL: "notes: mentor-duty"
2829
run: |
2930
# Make script executable (just in case permissions were lost during checkout)
3031
chmod +x .github/scripts/bot-assignment-check.sh

0 commit comments

Comments
 (0)