Skip to content

Commit 23b2ed0

Browse files
authored
Merge branch 'hiero-ledger:main' into main
2 parents 2ce8e6e + 89afede commit 23b2ed0

20 files changed

+1627
-115
lines changed

.coderabbit.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ reviews:
1919
poem: false # Do not write a literal poem (spammy)
2020
enable_prompt_for_ai_agents: false # Disable prompts for AI agents (spammy)
2121

22+
# ============================================================
23+
# GLOBAL REVIEW INSTRUCTIONS (APPLY TO ALL FILES)
24+
# ============================================================
25+
instructions: |
26+
You are a code reviewer whose primary responsibility is to verify that the code changes in this pull request fully address the specific requirements outlined in the associated issue description or pull request description.
27+
**ABSOLUTE RULES**
28+
- Only provide review feedback that is directly relevant to the issue description or the pull request description.
29+
- Do NOT propose improvements, refactors, or enhancements to the developer beyond what the PR explicitly claims to address.
30+
**SCOPE CONTROL**
31+
- If you identify issues that are real but outside the PR's stated scope:
32+
- Do NOT block the PR on them.
33+
- Do NOT suggest fixes inline.
34+
- Instead, aggregate all out-of-scope issues into a single comment with a list of recommendations for one or more follow-up issues that can be created.
35+
2236
path_instructions:
2337
# --- CUSTOM INSTRUCTIONS FOR EXAMPLES DIRECTORY ---
2438
- path: "examples/**/*"

.github/ISSUE_TEMPLATE/06_intermediate_issue.yml

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,26 @@ body:
1414
We truly appreciate your time and effort.
1515
This template is designed to help you create an Intermediate issue.
1616
17-
⚠️ **Important:**
18-
Intermediate contributors are still building **conceptual awareness and responsibility skills**.
19-
Issues created using this template **must be selected and framed carefully** to avoid breaking
20-
changes or unintended behavior.
21-
2217
The goal is to create an issue for users that have:
23-
- familiarity with the Hiero Python SDK codebase
18+
- basic familiarity with the Hiero Python SDK codebase
2419
- experience following our contribution workflow
2520
- confidence navigating existing source code and examples
2621
---
2722
2823
- type: textarea
2924
id: intro
3025
attributes:
31-
label: 🛠️ Intermediate Contributors
26+
label: 🧩 Intermediate Contributors
3227
description: Who is this issue for?
3328
value: |
3429
This issue is intended for contributors who already have some familiarity with the
3530
[Hiero Python SDK](https://hiero.org) codebase and contribution workflow.
36-
31+
3732
You should feel comfortable:
3833
- navigating existing source code and examples
3934
- understanding SDK concepts without step-by-step guidance
4035
- following the standard PR workflow without additional onboarding
41-
36+
4237
If this is your very first contribution to the project, we recommend starting with a few
4338
**Good First Issues** before working on this one.
4439
validations:
@@ -58,7 +53,6 @@ body:
5853
> - May involve **refactors or small feature additions**
5954
> - Provides **enough documentation or examples** to reason about a solution
6055
> - Often has **similar patterns elsewhere in the codebase**
61-
> - Involves unit and integration testing
6256
>
6357
> **What this issue is NOT:**
6458
> - A beginner-friendly onboarding task
@@ -91,7 +85,7 @@ body:
9185
attributes:
9286
value: |
9387
<!-- Example for Problem (hidden in submission) -->
94-
## 📌 Problem – Example
88+
## 🐞 Problem – Example
9589
9690
The `TransactionGetReceiptQuery` currently exposes the `get_children()` method,
9791
but the behavior is inconsistent with how child receipts are returned by the Mirror Node.
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
DRY_RUN="${DRY_RUN:-true}"
5+
6+
ANCHOR_DATE="2025-11-12"
7+
MEETING_LINK="https://zoom-lfx.platform.linuxfoundation.org/meeting/92041330205?password=2f345bee-0c14-4dd5-9883-06fbc9c60581"
8+
CALENDAR_LINK="https://zoom-lfx.platform.linuxfoundation.org/meetings/hiero?view=week"
9+
10+
CANCELLED_DATES=(
11+
"2025-12-24"
12+
)
13+
14+
EXCLUDED_AUTHORS=(
15+
"rbair23"
16+
"nadineloepfe"
17+
"exploreriii"
18+
"manishdait"
19+
"Dosik13"
20+
"hendrikebbers"
21+
)
22+
23+
if [ "$DRY_RUN" = "true" ]; then
24+
echo "=== DRY RUN MODE ENABLED ==="
25+
echo "No comments will be posted."
26+
fi
27+
28+
TODAY=$(date -u +"%Y-%m-%d")
29+
for CANCELLED in "${CANCELLED_DATES[@]}"; do
30+
if [ "$TODAY" = "$CANCELLED" ]; then
31+
echo "Community Call cancelled on $TODAY. Exiting."
32+
exit 0
33+
fi
34+
done
35+
36+
IS_MEETING_WEEK=$(python3 - <<EOF
37+
from datetime import datetime, date, timezone
38+
d1 = date.fromisoformat("$ANCHOR_DATE")
39+
d2 = datetime.now(timezone.utc).date()
40+
print("true" if (d2 - d1).days % 14 == 0 else "false")
41+
EOF
42+
)
43+
44+
if [ "$IS_MEETING_WEEK" = "false" ]; then
45+
echo "Not a fortnightly meeting week. Exiting."
46+
exit 0
47+
fi
48+
49+
if [ -z "${GITHUB_REPOSITORY:-}" ]; then
50+
echo "ERROR: GITHUB_REPOSITORY is not set."
51+
exit 1
52+
fi
53+
54+
REPO="$GITHUB_REPOSITORY"
55+
56+
ISSUE_DATA=$(gh issue list \
57+
--repo "$REPO" \
58+
--state open \
59+
--json number,author,createdAt)
60+
61+
if [ -z "$ISSUE_DATA" ] || [ "$ISSUE_DATA" = "[]" ]; then
62+
echo "No open issues found."
63+
exit 0
64+
fi
65+
66+
COMMENT_BODY=$(cat <<EOF
67+
Hello, this is CommunityCallBot.
68+
69+
This is a reminder that the Hiero Python SDK Community Call will begin in approximately 4 hours (14:00 UTC).
70+
71+
The call is an open forum where contributors and users can discuss topics, raise issues, and influence the direction of the Python SDK.
72+
73+
Details:
74+
- Time: 14:00 UTC
75+
- Join Link: [Zoom Meeting]($MEETING_LINK)
76+
77+
Disclaimer: This is an automated reminder. Please verify the schedule [here]($CALENDAR_LINK) for any changes.
78+
EOF
79+
)
80+
81+
echo "$ISSUE_DATA" |
82+
jq -r '
83+
group_by(.author.login)
84+
| .[]
85+
| sort_by(.createdAt)
86+
| reverse
87+
| .[0]
88+
| "\(.number) \(.author.login)"
89+
' |
90+
while read ISSUE_NUM AUTHOR; do
91+
for EXCLUDED in "${EXCLUDED_AUTHORS[@]}"; do
92+
if [ "$AUTHOR" = "$EXCLUDED" ]; then
93+
echo "Skipping issue #$ISSUE_NUM by excluded author @$AUTHOR"
94+
continue 2
95+
fi
96+
done
97+
98+
ALREADY_COMMENTED=$(gh issue view "$ISSUE_NUM" \
99+
--repo "$REPO" \
100+
--json comments \
101+
--jq '.comments[].body' | grep -F "CommunityCallBot" || true)
102+
103+
if [ -n "$ALREADY_COMMENTED" ]; then
104+
echo "Issue #$ISSUE_NUM already notified. Skipping."
105+
continue
106+
fi
107+
108+
if [ "$DRY_RUN" = "true" ]; then
109+
echo "----------------------------------------"
110+
echo "[DRY RUN] Would comment on issue #$ISSUE_NUM"
111+
echo "[DRY RUN] Author: @$AUTHOR"
112+
echo "----------------------------------------"
113+
echo "$COMMENT_BODY"
114+
echo "----------------------------------------"
115+
else
116+
gh issue comment "$ISSUE_NUM" --repo "$REPO" --body "$COMMENT_BODY"
117+
echo "Reminder posted to issue #$ISSUE_NUM"
118+
fi
119+
done
File renamed without changes.
Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,46 @@
11
module.exports = async ({ github, context }) => {
2-
const body = context.payload.pull_request.body || "";
3-
const regex = /\bFixes\s*:?\s*(#\d+)(\s*,\s*#\d+)*/i;
2+
let prNumber;
3+
try {
4+
const isDryRun = process.env.DRY_RUN === 'true';
5+
prNumber = parseInt(process.env.PR_NUMBER) || context.payload.pull_request.number;
6+
7+
console.log(`Processing PR #${prNumber} (Dry run: ${isDryRun})`);
8+
9+
// For workflow_dispatch, we need to fetch PR details
10+
let prData;
11+
if (context.payload.pull_request) {
12+
prData = context.payload.pull_request;
13+
} else {
14+
// workflow_dispatch case - fetch PR data
15+
const prResponse = await github.rest.pulls.get({
16+
owner: context.repo.owner,
17+
repo: context.repo.repo,
18+
pull_number: prNumber,
19+
});
20+
prData = prResponse.data;
21+
}
422

5-
const comments = await github.rest.issues.listComments({
6-
owner: context.repo.owner,
7-
repo: context.repo.repo,
8-
issue_number: context.payload.pull_request.number,
9-
});
23+
const body = prData.body || "";
24+
const regex = /\bFixes\s*:?\s*(#\d+)(\s*,\s*#\d+)*/i;
1025

11-
const alreadyCommented = comments.data.some(comment =>
12-
comment.body.includes("this is LinkBot")
13-
);
14-
15-
if (alreadyCommented) {
16-
return;
17-
}
18-
19-
if (!regex.test(body)) {
20-
await github.rest.issues.createComment({
26+
const comments = await github.rest.issues.listComments({
2127
owner: context.repo.owner,
2228
repo: context.repo.repo,
23-
issue_number: context.payload.pull_request.number,
24-
body: [
25-
`Hi @${context.payload.pull_request.user.login}, this is **LinkBot** 👋`,
29+
issue_number: prNumber,
30+
});
31+
32+
const alreadyCommented = comments.data.some(comment =>
33+
comment.body.includes("this is LinkBot")
34+
);
35+
36+
if (alreadyCommented) {
37+
console.log('LinkBot already commented on this PR');
38+
return;
39+
}
40+
41+
if (!regex.test(body)) {
42+
const commentBody = [
43+
`Hi @${prData.user.login}, this is **LinkBot** 👋`,
2644
``,
2745
`Linking pull requests to issues helps us significantly with reviewing pull requests and keeping the repository healthy.`,
2846
``,
@@ -38,8 +56,30 @@ module.exports = async ({ github, context }) => {
3856
`[docs/sdk_developers/creating_issues.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/docs/sdk_developers/creating_issues.md)`,
3957
``,
4058
`Thanks!`
41-
].join('\n')
42-
});
59+
].join('\n');
60+
61+
if (isDryRun) {
62+
console.log('DRY RUN: Would post the following comment:');
63+
console.log('---');
64+
console.log(commentBody);
65+
console.log('---');
66+
} else {
67+
await github.rest.issues.createComment({
68+
owner: context.repo.owner,
69+
repo: context.repo.repo,
70+
issue_number: prNumber,
71+
body: commentBody,
72+
});
73+
console.log('LinkBot comment posted successfully');
74+
}
75+
} else {
76+
console.log('PR has linked issue - no comment needed');
77+
}
78+
} catch (error) {
79+
console.error('Error processing PR:', error);
80+
console.error('PR number:', prNumber);
81+
console.error('Repository:', `${context.repo.owner}/${context.repo.repo}`);
82+
throw error;
4383
}
4484
};
4585

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Script to trigger CodeRabbit plan for intermediate and advanced issues
2+
3+
const marker = '<!-- CodeRabbit Plan Trigger -->';
4+
5+
async function triggerCodeRabbitPlan(github, owner, repo, issue, marker) {
6+
const comment = `${marker} @coderabbitai plan`;
7+
8+
try {
9+
await github.rest.issues.createComment({
10+
owner,
11+
repo,
12+
issue_number: issue.number,
13+
body: comment,
14+
});
15+
console.log(`Triggered CodeRabbit plan for issue #${issue.number}`);
16+
return true;
17+
} catch (commentErr) {
18+
console.log(`Failed to trigger CodeRabbit plan for issue #${issue.number}:`, commentErr.message || commentErr);
19+
return false;
20+
}
21+
}
22+
23+
function hasIntermediateOrAdvancedLabel(issue, label) {
24+
// Check if issue has intermediate or advanced label (case-insensitive)
25+
const hasIntermediateLabel = issue.labels?.some(l => l?.name?.toLowerCase() === 'intermediate');
26+
const hasAdvancedLabel = issue.labels?.some(l => l?.name?.toLowerCase() === 'advanced');
27+
28+
// Also check if newly added label is intermediate/advanced
29+
const isNewLabelIntermediate = label?.name?.toLowerCase() === 'intermediate';
30+
const isNewLabelAdvanced = label?.name?.toLowerCase() === 'advanced';
31+
32+
return hasIntermediateLabel || hasAdvancedLabel || isNewLabelIntermediate || isNewLabelAdvanced;
33+
}
34+
35+
async function hasExistingCodeRabbitPlan(github, owner, repo, issueNumber) {
36+
// Check for existing CodeRabbit plan comment (limited to first 500 comments)
37+
const comments = [];
38+
const iterator = github.paginate.iterator(github.rest.issues.listComments, {
39+
owner, repo, issue_number: issueNumber, per_page: 100
40+
});
41+
42+
let count = 0;
43+
for await (const { data: page } of iterator) {
44+
comments.push(...page);
45+
count += page.length;
46+
if (count >= 500) break; // Hard upper bound to prevent unbounded pagination
47+
}
48+
49+
return comments.some(c => c.body?.includes('@coderabbitai plan'));
50+
}
51+
52+
function logSummary(owner, repo, issue) {
53+
console.log('=== Summary ===');
54+
console.log(`Repository: ${owner}/${repo}`);
55+
console.log(`Issue Number: ${issue.number}`);
56+
console.log(`Issue Title: ${issue.title || '(no title)'}`);
57+
console.log(`Labels: ${issue.labels?.map(l => l.name).join(', ') || 'none'}`);
58+
}
59+
60+
module.exports = async ({ github, context }) => {
61+
try {
62+
const { owner, repo } = context.repo;
63+
const { issue, label } = context.payload;
64+
65+
// Validations
66+
if (!issue?.number) return console.log('No issue in payload');
67+
68+
if (!hasIntermediateOrAdvancedLabel(issue, label)) {
69+
return console.log('Issue does not have intermediate or advanced label');
70+
}
71+
72+
if (await hasExistingCodeRabbitPlan(github, owner, repo, issue.number)) {
73+
return console.log(`CodeRabbit plan already triggered for #${issue.number}`);
74+
}
75+
76+
// Post CodeRabbit plan trigger
77+
await triggerCodeRabbitPlan(github, owner, repo, issue, marker);
78+
79+
logSummary(owner, repo, issue);
80+
} catch (err) {
81+
console.log('❌ Error:', err.message);
82+
}
83+
};

0 commit comments

Comments
 (0)