-
Notifications
You must be signed in to change notification settings - Fork 0
Test protobuf packag two #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
bf195ce
f1dba68
b165f63
3bc8082
f9f3341
16d0271
6a9bd62
1c91a34
d5bd856
61447c2
65db8bc
96aa9cb
b1050dc
e2aad1f
412baea
85d5006
e3f71f8
eea18b4
8f490d3
38e48fc
aeba5ef
47fd35e
3073702
39c8a34
744dee6
6ad1973
2718e96
2f0cba9
4432ab9
a39c90d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| hiero-sdk-python/.github/coderabbit/release-pr-prompt.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| /** | ||
| * Posts a single "@coderabbit review" comment on release PRs, embedding the | ||
| * release review prompt. Designed to run with: | ||
| * - permissions: contents: read, pull-requests: write | ||
| * | ||
| * Safety: | ||
| * - Only runs for maintainer-authored PRs (MEMBER/OWNER) | ||
| * - Dedupe via hidden marker comment | ||
| */ | ||
|
|
||
| const fs = require("fs"); | ||
| const path = require("path"); | ||
|
|
||
| const MARKER = "<!-- coderabbit-release-gate: v1 -->"; | ||
|
|
||
|
|
||
| function loadPrompt() { | ||
| const promptPath = path.join( | ||
| process.env.GITHUB_WORKSPACE || ".", | ||
| ".github/coderabbit/release-pr-prompt.md" | ||
| ); | ||
| try { | ||
| const content = fs.readFileSync(promptPath, "utf8").trim(); | ||
| if (!content) { | ||
| throw new Error("Release prompt file is empty"); | ||
| } | ||
| return content; | ||
| } catch (error) { | ||
| throw new Error(`Failed to load release prompt from ${promptPath}: ${error.message}`); | ||
| } | ||
| } | ||
|
|
||
| async function commentAlreadyExists({ github, owner, repo, issue_number }) { | ||
| try { | ||
| // Pull a bounded number of recent comments to avoid pagination complexity. | ||
| const { data } = await github.rest.issues.listComments({ | ||
| owner, | ||
| repo, | ||
| issue_number, | ||
| per_page: 100, | ||
| }); | ||
| return data.some((c) => typeof c.body === "string" && c.body.includes(MARKER)); | ||
| } | ||
| catch (error) { | ||
| console.error(`Error checking for existing comments: ${error.message}`); | ||
| return false; // Fail open: allow posting if check fails | ||
| } | ||
| } | ||
|
|
||
|
|
||
| function buildBody({ prompt, baseRef, headRef, baseLooksLikeTag }) { | ||
| // Keep it human-friendly but compact; instructions are collapsible. | ||
| const lines = [ | ||
| "@coderabbitai review", | ||
| "", | ||
| MARKER, | ||
| "", | ||
| `This is a **release-gate** review request for diff **${baseRef} → ${headRef}**.`, | ||
| "", | ||
| ]; | ||
| if (!baseLooksLikeTag) { | ||
| lines.push( | ||
| "⚠️ Warning: The base ref does not look like a release tag. For a full release diff, set base to the previous tag (e.g., release-v0.1.10).", | ||
| "" | ||
| ); | ||
| } | ||
|
|
||
| lines.push( | ||
| "<details>", | ||
| "<summary>CodeRabbit release review instructions</summary>", | ||
| "", | ||
| prompt, | ||
| "", | ||
| "</details>", | ||
| ); | ||
| return lines.join("\n"); | ||
|
|
||
| } | ||
|
|
||
| module.exports = async ({ github, context }) => { | ||
| try { | ||
| const owner = context.repo.owner; | ||
| const repo = context.repo.repo; | ||
| const pr = context.payload.pull_request; | ||
|
|
||
| if (!pr) { | ||
| console.log("No pull_request payload; exiting."); | ||
| return; | ||
| } | ||
|
|
||
| // Safety: only maintainers | ||
| const assoc = pr.author_association; | ||
| if (!(assoc === "MEMBER" || assoc === "OWNER")) { | ||
| console.log(`author_association=${assoc}; skipping.`); | ||
| return; | ||
| } | ||
|
|
||
| const title = pr.title || ""; | ||
| if (!title.toLowerCase().startsWith("chore: release v")) { | ||
| console.log("Not a release PR title; skipping."); | ||
| return; | ||
| } | ||
|
|
||
| const baseRef = pr.base?.ref || ""; | ||
| const headRef = pr.head?.ref || ""; | ||
|
|
||
| // Optional sanity check: base should look like a tag. If it doesn't, still comment but warn. | ||
| const baseLooksLikeTag = baseRef.startsWith("release-v") && /\d+\.\d+\.\d+/.test(baseRef); | ||
|
|
||
| const issue_number = pr.number; | ||
| if (await commentAlreadyExists({ github, owner, repo, issue_number })) { | ||
| console.log("Marker comment already exists; not posting again."); | ||
| return; | ||
| } | ||
|
|
||
| const prompt = loadPrompt(); | ||
|
|
||
| const body = buildBody({ prompt, baseRef, headRef, baseLooksLikeTag }); | ||
|
|
||
| await github.rest.issues.createComment({ | ||
| owner, | ||
| repo, | ||
| issue_number, | ||
| body, | ||
| }); | ||
|
|
||
| console.log("Posted CodeRabbit release-gate comment."); | ||
| console.log(`PR #${issue_number} (${headRef} → ${baseRef})`); | ||
| } catch (error) { | ||
| console.error(`Error in release PR coderabbit gate: ${error.message}`); | ||
| console.log(`PR #${issue_number || 'unknown'} (${headRef || '?'} → ${baseRef || '?'})`); | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| name: CodeRabbit Release Gate Comment | ||
|
|
||
| on: | ||
| pull_request: | ||
| types: [opened, reopened, synchronize, edited] | ||
|
|
||
| permissions: | ||
| contents: read | ||
| pull-requests: write | ||
|
|
||
| concurrency: | ||
| group: coderabbit-release-gate-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| coderabbit-release-gate: | ||
| runs-on: ubuntu-latest | ||
| # Only run for release PRs /title check as initial filter | ||
| if: | | ||
| github.event.pull_request && | ||
| (startsWith(github.event.pull_request.title, 'chore: release v') || | ||
| startsWith(github.event.pull_request.title, 'release v') || | ||
| startsWith(github.event.pull_request.title, 'Release v')) | ||
|
|
||
| steps: | ||
| - name: Harden the runner | ||
| uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1 | ||
| with: | ||
| egress-policy: audit | ||
|
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 | ||
| with: | ||
| sparse-checkout: | | ||
| .github/coderabbit/release-pr-prompt.md | ||
| .github/scripts/post-coderabbit-release-gate-comment.js | ||
| sparse-checkout-cone-mode: false | ||
|
|
||
| - name: Post CodeRabbit release-gate prompt comment | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 | ||
| with: | ||
| script: | | ||
| const script = require('./.github/scripts/release-pr-coderabbit-gate.js'); | ||
| await script({ github, context}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,6 @@ | |
|
|
||
| from hiero_sdk_python.timestamp import Timestamp | ||
| from hiero_sdk_python.hapi.mirror import consensus_service_pb2 as mirror_proto | ||
| from hiero_sdk_python.transaction.transaction_id import TransactionId | ||
|
|
||
|
|
||
| class TopicMessageChunk: | ||
|
|
@@ -41,7 +40,7 @@ def __init__( | |
| consensus_timestamp: datetime, | ||
| message_data: Dict[str, Union[bytes, int]], | ||
| chunks: List[TopicMessageChunk], | ||
| transaction_id: Optional[TransactionId] = None, | ||
| transaction_id: Optional[str] = None, | ||
| ) -> None: | ||
| """ | ||
| Args: | ||
|
|
@@ -53,14 +52,14 @@ def __init__( | |
| "sequence_number": int | ||
| } | ||
| chunks (List[TopicMessageChunk]): All individual chunks that form this message. | ||
| transaction_id (Optional[Transaction]): The transaction ID if available. | ||
| transaction_id (Optional[str]): The transaction ID string if available. | ||
| """ | ||
| self.consensus_timestamp: datetime = consensus_timestamp | ||
| self.contents: Union[bytes, int] = message_data["contents"] | ||
| self.running_hash: Union[bytes, int] = message_data["running_hash"] | ||
| self.sequence_number: Union[bytes, int] = message_data["sequence_number"] | ||
| self.chunks: List[TopicMessageChunk] = chunks | ||
| self.transaction_id: Optional[TransactionId] = transaction_id | ||
| self.transaction_id: Optional[str] = transaction_id | ||
|
|
||
| @classmethod | ||
| def of_single(cls, response: mirror_proto.ConsensusTopicResponse) -> "TopicMessage": # type: ignore | ||
|
|
@@ -73,9 +72,13 @@ def of_single(cls, response: mirror_proto.ConsensusTopicResponse) -> "TopicMessa | |
| running_hash: Union[bytes, int] = response.runningHash | ||
| sequence_number: Union[bytes, int] = chunk.sequence_number | ||
|
|
||
| transaction_id: Optional[TransactionId] = None | ||
| transaction_id: Optional[str] = None | ||
| if response.HasField("chunkInfo") and response.chunkInfo.HasField("initialTransactionID"): | ||
| transaction_id = TransactionId._from_proto(response.chunkInfo.initialTransactionID) | ||
| tx_id = response.chunkInfo.initialTransactionID | ||
| transaction_id = ( | ||
| f"{tx_id.shardNum}.{tx_id.realmNum}.{tx_id.accountNum}-" | ||
| f"{tx_id.transactionValidStart.seconds}.{tx_id.transactionValidStart.nanos}" | ||
| ) | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+75
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Extract duplicated transaction ID formatting into a helper method. The transaction ID string construction logic is duplicated verbatim in both ♻️ Proposed refactor# Add as a static method on TopicMessage:
`@staticmethod`
def _format_transaction_id(tx_id) -> str:
"""Format a protobuf TransactionID as a canonical string."""
acct = tx_id.accountID
return (
f"{acct.shardNum}.{acct.realmNum}.{acct.accountNum}@"
f"{tx_id.transactionValidStart.seconds}.{tx_id.transactionValidStart.nanos:09d}"
)Then replace both occurrences with: transaction_id = cls._format_transaction_id(tx_id)Also applies to: 117-121 |
||
|
|
||
| return cls( | ||
| consensus_timestamp, | ||
|
|
@@ -99,24 +102,25 @@ def of_many(cls, responses: List[mirror_proto.ConsensusTopicResponse]) -> "Topic | |
|
|
||
| chunks: List[TopicMessageChunk] = [] | ||
| total_size: int = 0 | ||
| transaction_id: Optional[TransactionId] = None | ||
| transaction_id: Optional[str] = None | ||
|
|
||
| for r in sorted_responses: | ||
| c = TopicMessageChunk(r) | ||
| chunks.append(c) | ||
|
|
||
| total_size += len(r.message) | ||
|
|
||
|
|
||
| if ( | ||
| transaction_id is None | ||
| and r.HasField("chunkInfo") | ||
| and r.chunkInfo.HasField("initialTransactionID") | ||
| ): | ||
| transaction_id = TransactionId._from_proto(r.chunkInfo.initialTransactionID) | ||
| tx_id = r.chunkInfo.initialTransactionID | ||
| transaction_id = ( | ||
| f"{tx_id.shardNum}.{tx_id.realmNum}.{tx_id.accountNum}-" | ||
| f"{tx_id.transactionValidStart.seconds}.{tx_id.transactionValidStart.nanos}" | ||
| ) | ||
|
|
||
| contents = bytearray(total_size) | ||
|
|
||
| offset: int = 0 | ||
| for r in sorted_responses: | ||
| end = offset + len(r.message) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.