From 5c485bcc441958a01638db1f7894f6e458551a7b Mon Sep 17 00:00:00 2001 From: cheese-cakee Date: Thu, 19 Feb 2026 02:16:55 +0530 Subject: [PATCH 1/5] feat: sync linked issue labels to pull requests Signed-off-by: cheese-cakee --- .coderabbit.yaml | 22 +-- .github/scripts/sync-issue-labels.js | 208 ++++++++++++++++++++++++ .github/workflows/sync-issue-labels.yml | 51 ++++++ 3 files changed, 270 insertions(+), 11 deletions(-) create mode 100644 .github/scripts/sync-issue-labels.js create mode 100644 .github/workflows/sync-issue-labels.yml diff --git a/.coderabbit.yaml b/.coderabbit.yaml index de84d766f..c2f2d8db5 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -277,7 +277,7 @@ reviews: - Payment-safe - Execution-consistent - Strictly aligned with Hedera query semantics - + # TRANSACTION REVIEW INSTRUCTIONS - CORE FOUNDATION (MOST CRITICAL MODULE) transaction_review_instructions: &transaction_review_instructions | You are acting as a senior maintainer and security architect reviewing the **core transaction module** in the hiero-sdk-python project. @@ -599,7 +599,7 @@ reviews: - Changes encoding/decoding results for same inputs - Modifies ContractId EVM alias ↔ numeric mapping - Alters payable amount (amount vs initial_balance) semantics - + If breaking: require deprecation warnings (e.g. warnings.warn(..., DeprecationWarning)), migration docs, dual-behavior tests. ---------------------------------------------------------- REVIEW FOCUS 2 — ABI ENCODING/DECODING SAFETY (CRITICAL) @@ -670,7 +670,7 @@ reviews: - Protobuf-aligned with Hedera/Hiero - Gas/value safe - Deterministic and user-protective - + # NODES REVIEW INSTRUCTIONS — PRIVILEGED NODE LIFECYCLE OPERATIONS node_review_instructions: &node_review_instructions | You are acting as a senior maintainer and security architect reviewing the nodes module @@ -795,7 +795,7 @@ reviews: - Certificate and endpoint handling edge cases are tested Missing coverage should be flagged clearly. - + ---------------------------------------------------------- EXPLICIT NON-GOALS ---------------------------------------------------------- @@ -819,7 +819,7 @@ reviews: file_review_instructions: &file_review_instructions | You are acting as a senior maintainer reviewing file service-related code in the hiero-sdk-python project. - + This includes: - File transactions (FileCreateTransaction, FileUpdateTransaction, FileAppendTransaction, FileDeleteTransaction) - File query (FileContentsQuery, FileInfoQuery) @@ -839,19 +839,19 @@ reviews: (HIGH SENSITIVITY) ---------------------------------------------------------- Public API contracts for FileId, FileInfo, and file transactions are user-facing. - + Verify that: - Setter method signatures (e.g., set_contents, set_file_memo) stay backward compatible. - Method chaining (returning self) is preserved. - FileId constructors and string representations don't break existing use cases. - + If breaking changes are necessary, they must be explicit and deprecation warnings should be added. ---------------------------------------------------------- REVIEW FOCUS 2 — CHUNKING SEMANTICS (HIGH VERIFICATION) ---------------------------------------------------------- Specific to FileAppendTransaction, which natively handles chunking. - + Verify that: - freeze_with() correctly generates sequential TransactionIds for each chunk. - valid_start timestamps for each chunk are spaced out correctly (e.g., incremented by at least 1 nanosecond). @@ -864,7 +864,7 @@ reviews: REVIEW FOCUS 3 — MEMO HANDLING ---------------------------------------------------------- Nuanced memo distinction across the file module: - + Verify that: - The distinction between file_memo (the metadata attribute of the file) and transaction_memo (the note on the transaction itself) is respected. - FileCreateTransaction handles file_memo as a native string. @@ -876,7 +876,7 @@ reviews: REVIEW FOCUS 4 — TRANSACTION BASE CLASS CONTRACT ---------------------------------------------------------- All file transaction classes MUST inherit from Transaction. - + Required implementations: - _build_proto_body() - build_transaction_body() @@ -891,7 +891,7 @@ reviews: REVIEW FOCUS 5 — PROTOBUF ALIGNMENT ---------------------------------------------------------- Serialization and deserialization MUST map directly to Hedera protobufs. - + Verify that: - fileCreate, fileUpdate, fileAppend, and fileDelete fields map exactly to their respective protobuf bodies. - Null-safe conversions are handling optional properties safely. diff --git a/.github/scripts/sync-issue-labels.js b/.github/scripts/sync-issue-labels.js new file mode 100644 index 000000000..6d2d4d91e --- /dev/null +++ b/.github/scripts/sync-issue-labels.js @@ -0,0 +1,208 @@ +// Checks if the given login belongs to a bot account (ends with [bot] or contains "dependabot"). +function isBotLogin(login = "") { + return /\[bot\]$/i.test(login) || /dependabot/i.test(login); +} + +// Extracts issue numbers from PR body closing keywords (Fixes #123, Closes #456, Resolves #789, etc.). +function extractLinkedIssueNumbers(prBody = "") { + const closingReferenceRegex = + /\b(?:fix(?:es|ed)?|close(?:s|d)?|resolve(?:s|d)?)\s*:?\s*((?:#\d+)(?:\s*(?:,|and)\s*#\d+)*)/gi; + const numbers = new Set(); + let referenceMatch; + + while ((referenceMatch = closingReferenceRegex.exec(prBody)) !== null) { + const referencesText = referenceMatch[1] || ""; + const issueMatches = referencesText.matchAll(/#(\d+)/g); + + for (const issueMatch of issueMatches) { + numbers.add(Number(issueMatch[1])); + } + } + + return [...numbers]; +} + +// Normalizes label objects/strings to an array of trimmed label names. +function normalizeLabelNames(labels = []) { + const names = []; + for (const label of labels) { + if (typeof label === "string" && label.trim()) { + names.push(label.trim()); + continue; + } + + if (label && typeof label.name === "string" && label.name.trim()) { + names.push(label.name.trim()); + } + } + return names; +} + +// Fetches PR data from the payload or GitHub API if not present in payload. +async function getPullRequestData({ github, context, prNumber }) { + if (context.payload.pull_request) { + return context.payload.pull_request; + } + + const response = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + + return response.data; +} + +// Resolves PR number from environment or context, and determines if dry-run mode is enabled. +function resolveExecutionContext(context) { + const isDryRun = /^true$/i.test(process.env.DRY_RUN || ""); + const prNumber = Number(process.env.PR_NUMBER) || context.payload.pull_request?.number; + return { prNumber, isDryRun, owner: context.repo.owner, repo: context.repo.repo }; +} + +// Determines if the PR should be skipped (e.g., bot-authored PRs, no linked issues). +function shouldSkipPR(prData, linkedIssueNumbers) { + const prAuthor = prData?.user?.login || ""; + + if (isBotLogin(prAuthor)) { + return { skip: true, reason: `Skipping bot-authored PR from ${prAuthor}.` }; + } + + if (!linkedIssueNumbers.length) { + return { skip: true, reason: "No linked issue references found in PR body." }; + } + + return { skip: false }; +} + +// Collects labels from all linked issues, handling 404s and PR references. +async function collectLabelsFromLinkedIssues({ github, owner, repo, linkedIssueNumbers }) { + const labelsFromIssues = new Set(); + + for (const issueNumber of linkedIssueNumbers) { + try { + const issueResponse = await github.rest.issues.get({ + owner, + repo, + issue_number: issueNumber, + }); + + if (issueResponse?.data?.pull_request) { + console.log(`[sync-issue-labels] Skipping #${issueNumber}: reference points to a pull request.`); + continue; + } + + const issueLabelNames = normalizeLabelNames(issueResponse?.data?.labels || []); + console.log( + `[sync-issue-labels] Issue #${issueNumber} labels: ${ + issueLabelNames.length ? issueLabelNames.join(", ") : "(none)" + }` + ); + + for (const label of issueLabelNames) { + labelsFromIssues.add(label); + } + } catch (error) { + if (error?.status === 404) { + console.log(`[sync-issue-labels] Linked issue #${issueNumber} not found. Skipping.`); + continue; + } + + throw error; + } + } + + return labelsFromIssues; +} + +// Computes which labels should be added to the PR (missing from PR but present in issues). +function computeLabelsToAdd(prData, labelsFromIssues) { + const prLabelNames = new Set(normalizeLabelNames(prData?.labels || [])); + return [...labelsFromIssues].filter((label) => !prLabelNames.has(label)); +} + +// Adds labels to the pull request via GitHub API. +async function addLabelsToPullRequest({ github, owner, repo, prNumber, labelsToAdd }) { + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: prNumber, + labels: labelsToAdd, + }); + + console.log(`[sync-issue-labels] Added labels to PR #${prNumber}: ${labelsToAdd.join(", ")}`); +} + +// Main entry point: syncs labels from linked issues to the PR. +module.exports = async ({ github, context }) => { + const { prNumber, isDryRun, owner, repo } = resolveExecutionContext(context); + + if (!prNumber) { + throw new Error("PR number could not be determined."); + } + + console.log( + `[sync-issue-labels] Processing PR #${prNumber} in ${owner}/${repo} (dry_run=${isDryRun}).` + ); + + let prData; + try { + prData = await getPullRequestData({ github, context, prNumber }); + } catch (error) { + throw new Error(`[sync-issue-labels] Failed to fetch PR #${prNumber}: ${error?.message || error}`); + } + + const linkedIssueNumbers = extractLinkedIssueNumbers(prData?.body || ""); + const skipResult = shouldSkipPR(prData, linkedIssueNumbers); + + if (skipResult.skip) { + console.log(`[sync-issue-labels] ${skipResult.reason}`); + return; + } + + console.log( + `[sync-issue-labels] Linked issues detected: ${linkedIssueNumbers.map((n) => `#${n}`).join(", ")}` + ); + + const labelsFromIssues = await collectLabelsFromLinkedIssues({ + github, + owner, + repo, + linkedIssueNumbers, + }); + + if (!labelsFromIssues.size) { + console.log("[sync-issue-labels] No labels found on linked issues. Nothing to sync."); + return; + } + + const labelsToAdd = computeLabelsToAdd(prData, labelsFromIssues); + const prLabelNames = new Set(normalizeLabelNames(prData?.labels || [])); + + console.log( + `[sync-issue-labels] Existing PR labels: ${ + prLabelNames.size ? [...prLabelNames].join(", ") : "(none)" + }` + ); + console.log( + `[sync-issue-labels] Labels to add: ${labelsToAdd.length ? labelsToAdd.join(", ") : "(none)"}` + ); + + if (!labelsToAdd.length) { + console.log("[sync-issue-labels] PR already contains all labels from linked issues."); + return; + } + + if (isDryRun) { + console.log(`[sync-issue-labels] DRY_RUN enabled; would add labels: ${labelsToAdd.join(", ")}`); + return; + } + + try { + await addLabelsToPullRequest({ github, owner, repo, prNumber, labelsToAdd }); + } catch (error) { + throw new Error( + `[sync-issue-labels] Failed to add labels to PR #${prNumber}: ${error?.message || error}` + ); + } +}; diff --git a/.github/workflows/sync-issue-labels.yml b/.github/workflows/sync-issue-labels.yml new file mode 100644 index 000000000..294485f51 --- /dev/null +++ b/.github/workflows/sync-issue-labels.yml @@ -0,0 +1,51 @@ +name: Sync Linked Issue Labels to PR + +on: + pull_request_target: + types: [opened, edited, reopened, synchronize, ready_for_review] + workflow_dispatch: + inputs: + pr_number: + description: "PR number to sync labels for" + required: true + type: number + dry_run: + description: "Dry run (log only, do not apply labels)" + required: false + type: boolean + default: true + +permissions: + pull-requests: read + issues: write + contents: read + +jobs: + sync-issue-labels: + runs-on: ubuntu-latest + + concurrency: + group: sync-issue-labels-${{ github.event.pull_request.number || github.event.inputs.pr_number }} + cancel-in-progress: true + + steps: + - name: Harden the runner + uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 + with: + egress-policy: audit + + - name: Checkout repository + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: main + + - name: Sync linked issue labels to PR + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} + DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const script = require('./.github/scripts/sync-issue-labels.js'); + await script({ github, context, core }); From 957cc56a75569d0dba735ddd06d6f087b959b1de Mon Sep 17 00:00:00 2001 From: exploreriii <133720349+exploreriii@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:22:48 +0000 Subject: [PATCH 2/5] chore: remove other workflows Signed-off-by: exploreriii <133720349+exploreriii@users.noreply.github.com> --- .github/workflows/bot-advanced-check.yml | 66 ------- .github/workflows/bot-assignment-check.yml | 33 ---- .../bot-beginner-assign-on-comment.yml | 38 ---- .../workflows/bot-coderabbit-plan-trigger.yml | 52 ------ .github/workflows/bot-community-calls.yml | 42 ----- .../workflows/bot-gfi-assign-on-comment.yml | 38 ---- .../bot-gfi-candidate-notification.yaml | 39 ---- .github/workflows/bot-inactivity-unassign.yml | 41 ----- .../workflows/bot-intermediate-assignment.yml | 47 ----- .../workflows/bot-issue-reminder-no-pr.yml | 38 ---- .../workflows/bot-linked-issue-enforcer.yml | 42 ----- .github/workflows/bot-merge-conflict.yml | 50 ------ .../bot-next-issue-recommendation.yml | 36 ---- .github/workflows/bot-office-hours.yml | 41 ----- .../workflows/bot-p0-issues-notify-team.yml | 38 ---- .../bot-pr-draft-ready-reminder.yaml | 36 ---- .../workflows/bot-pr-inactivity-reminder.yml | 42 ----- .../workflows/bot-pr-missing-linked-issue.yml | 54 ------ .github/workflows/bot-verified-commits.yml | 109 ------------ .github/workflows/bot-workflows.yml | 71 -------- .github/workflows/cron-check-broken-links.yml | 103 ----------- .github/workflows/cron-update-spam-list.yml | 40 ----- .github/workflows/deps-check.yml | 76 -------- .github/workflows/pr-check-broken-links.yml | 29 --- .github/workflows/pr-check-changelog.yml | 28 --- .github/workflows/pr-check-codecov.yml | 49 ----- .github/workflows/pr-check-examples.yml | 69 ------- .github/workflows/pr-check-test-files.yml | 34 ---- .github/workflows/pr-check-test.yml | 168 ------------------ .github/workflows/pr-check-title.yml | 41 ----- .github/workflows/publish.yml | 44 ----- .github/workflows/unassign-on-comment.yml | 37 ---- .github/workflows/working-on-comment.yml | 41 ----- 33 files changed, 1712 deletions(-) delete mode 100644 .github/workflows/bot-advanced-check.yml delete mode 100644 .github/workflows/bot-assignment-check.yml delete mode 100644 .github/workflows/bot-beginner-assign-on-comment.yml delete mode 100644 .github/workflows/bot-coderabbit-plan-trigger.yml delete mode 100644 .github/workflows/bot-community-calls.yml delete mode 100644 .github/workflows/bot-gfi-assign-on-comment.yml delete mode 100644 .github/workflows/bot-gfi-candidate-notification.yaml delete mode 100644 .github/workflows/bot-inactivity-unassign.yml delete mode 100644 .github/workflows/bot-intermediate-assignment.yml delete mode 100644 .github/workflows/bot-issue-reminder-no-pr.yml delete mode 100644 .github/workflows/bot-linked-issue-enforcer.yml delete mode 100644 .github/workflows/bot-merge-conflict.yml delete mode 100644 .github/workflows/bot-next-issue-recommendation.yml delete mode 100644 .github/workflows/bot-office-hours.yml delete mode 100644 .github/workflows/bot-p0-issues-notify-team.yml delete mode 100644 .github/workflows/bot-pr-draft-ready-reminder.yaml delete mode 100644 .github/workflows/bot-pr-inactivity-reminder.yml delete mode 100644 .github/workflows/bot-pr-missing-linked-issue.yml delete mode 100644 .github/workflows/bot-verified-commits.yml delete mode 100644 .github/workflows/bot-workflows.yml delete mode 100644 .github/workflows/cron-check-broken-links.yml delete mode 100644 .github/workflows/cron-update-spam-list.yml delete mode 100644 .github/workflows/deps-check.yml delete mode 100644 .github/workflows/pr-check-broken-links.yml delete mode 100644 .github/workflows/pr-check-changelog.yml delete mode 100644 .github/workflows/pr-check-codecov.yml delete mode 100644 .github/workflows/pr-check-examples.yml delete mode 100644 .github/workflows/pr-check-test-files.yml delete mode 100644 .github/workflows/pr-check-test.yml delete mode 100644 .github/workflows/pr-check-title.yml delete mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/unassign-on-comment.yml delete mode 100644 .github/workflows/working-on-comment.yml diff --git a/.github/workflows/bot-advanced-check.yml b/.github/workflows/bot-advanced-check.yml deleted file mode 100644 index f998b71c9..000000000 --- a/.github/workflows/bot-advanced-check.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: PythonBot - Advanced Requirement Check -on: - issues: - types: [assigned, labeled] - workflow_dispatch: - inputs: - dry_run: - description: "If true, run in log-only mode (no comments or unassignments)" - required: false - default: "true" - type: string - username: - description: "GitHub username to dry-run qualification check" - required: true - type: string -permissions: - contents: read - issues: write -concurrency: - group: ${{ github.workflow }}-${{ github.event.issue.number || github.run_id }} - cancel-in-progress: true -jobs: - ####################################### - # Automatic enforcement + manual dry-run - ####################################### - check-advanced-qualification: - # steps are skipped, job completes successfully - runs-on: ubuntu-latest - steps: - - name: Filter - id: should_run - run: echo "value=true" >> $GITHUB_OUTPUT - if: | - github.event_name == 'workflow_dispatch' || - ( - github.event_name == 'issues' && - contains(github.event.issue.labels.*.name, 'advanced') && - ( - github.event.action == 'assigned' || - (github.event.action == 'labeled' && github.event.label.name == 'advanced' && join(github.event.issue.assignees.*.login, ',') != '') - ) - ) - - name: Log skip reason - if: steps.should_run.outputs.value != 'true' - run: | - echo "::notice::Skipping: event=${{ github.event_name }}, action=${{ github.event.action }}, has_advanced_label=${{ contains(github.event.issue.labels.*.name, 'advanced') }}" - - name: Checkout scripts - if: steps.should_run.outputs.value == 'true' - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - sparse-checkout: | - .github/scripts - sparse-checkout-cone-mode: false - - - name: Verify User Qualification - if: steps.should_run.outputs.value == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: ${{ github.repository }} - TRIGGER_ASSIGNEE: ${{ github.event.assignee.login || '' }} - ISSUE_NUMBER: ${{ github.event.issue.number || '' }} - DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }} - DRY_RUN_USER: ${{ github.event_name == 'workflow_dispatch' && inputs.username || '' }} - run: | - chmod +x .github/scripts/bot-advanced-check.sh - .github/scripts/bot-advanced-check.sh \ No newline at end of file diff --git a/.github/workflows/bot-assignment-check.yml b/.github/workflows/bot-assignment-check.yml deleted file mode 100644 index 0a5b5320c..000000000 --- a/.github/workflows/bot-assignment-check.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: PythonBot - Assignment Limit - -on: - issues: - types: [assigned] - -permissions: - issues: write - -jobs: - check-assignment-limit: - runs-on: ubuntu-latest - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Check Assignment Count - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ASSIGNEE: ${{ github.event.assignee.login }} - ISSUE_NUMBER: ${{ github.event.issue.number }} - REPO: ${{ github.repository }} - run: | - # Make script executable (just in case permissions were lost during checkout) - chmod +x .github/scripts/bot-assignment-check.sh - - # Run the script - ./.github/scripts/bot-assignment-check.sh \ No newline at end of file diff --git a/.github/workflows/bot-beginner-assign-on-comment.yml b/.github/workflows/bot-beginner-assign-on-comment.yml deleted file mode 100644 index 9d581651c..000000000 --- a/.github/workflows/bot-beginner-assign-on-comment.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Beginner Assign on /assign - -on: - issue_comment: - types: - - created - -permissions: - issues: write - contents: read - -jobs: - beginner-assign: - # Only run on issue comments (not PR comments) - if: github.event.issue.pull_request == null - - runs-on: ubuntu-latest - - # Prevent race conditions unique to beginner assignment - concurrency: - group: beginner-assign-${{ github.event.issue.number }} - cancel-in-progress: false - - steps: - - name: Harden runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Run Beginner /assign handler - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 - with: - script: | - const script = require('./.github/scripts/bot-beginner-assign-on-comment.js'); - await script({ github, context }); \ No newline at end of file diff --git a/.github/workflows/bot-coderabbit-plan-trigger.yml b/.github/workflows/bot-coderabbit-plan-trigger.yml deleted file mode 100644 index 287dc6c53..000000000 --- a/.github/workflows/bot-coderabbit-plan-trigger.yml +++ /dev/null @@ -1,52 +0,0 @@ -# This workflow automatically triggers CodeRabbit's plan feature for intermediate and advanced issues. -# Fix for #1427: Only triggers when a beginner/intermediate/advanced label is specifically added, -# preventing duplicate runs when other labels are added to the same issue. -name: CodeRabbit Plan Trigger -on: - issues: - types: [labeled] - workflow_dispatch: - inputs: - dry_run: - description: "Run without posting comments" - required: false - default: "true" - type: choice - options: - - "true" - - "false" - -permissions: - issues: write - contents: read - -jobs: - coderabbit_plan_trigger: - runs-on: ubuntu-latest - concurrency: - group: coderabbit-plan-${{ github.event.issue.number }} - cancel-in-progress: false - # Only run when the newly added label is beginner, intermediate, or advanced (case-insensitive) - if: > - github.event_name == 'workflow_dispatch' || - (github.event.action == 'labeled' && - contains(fromJson('["beginner","intermediate","advanced","Beginner","Intermediate","Advanced"]'), github.event.label.name)) - - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - - - name: Trigger CodeRabbit Plan - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }} - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 - with: - script: | - const script = require('./.github/scripts/coderabbit_plan_trigger.js'); - await script({ github, context}); diff --git a/.github/workflows/bot-community-calls.yml b/.github/workflows/bot-community-calls.yml deleted file mode 100644 index 826ce5817..000000000 --- a/.github/workflows/bot-community-calls.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: PythonBot - Community Call Reminder - -on: - schedule: - - cron: "0 10 * * 3" - workflow_dispatch: - inputs: - dry_run: - description: "Run in dry mode (no comments will be posted)" - required: false - default: "true" - type: choice - options: - - "true" - - "false" - -permissions: - contents: read - issues: write - -concurrency: - group: community-call-reminder - cancel-in-progress: false - -jobs: - office-hour-reminder: - runs-on: ubuntu-latest - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e #2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - - - name: Check Schedule and Notify - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }} - run: | - bash .github/scripts/bot-community-calls.sh diff --git a/.github/workflows/bot-gfi-assign-on-comment.yml b/.github/workflows/bot-gfi-assign-on-comment.yml deleted file mode 100644 index 706c53b73..000000000 --- a/.github/workflows/bot-gfi-assign-on-comment.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: GFI Assign on /assign - -on: - issue_comment: - types: - - created - -permissions: - issues: write - contents: read - -jobs: - gfi-assign: - # Only run on issue comments (not PR comments) - if: github.event.issue.pull_request == null - - runs-on: ubuntu-latest - - # Prevent race conditions: always wait for the first assignment request to finish processing - concurrency: - group: gfi-assign-${{ github.event.issue.number }} - cancel-in-progress: false - - steps: - - name: Harden runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Run GFI /assign handler - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 - with: - script: | - const script = require('./.github/scripts/bot-gfi-assign-on-comment.js'); - await script({ github, context }); diff --git a/.github/workflows/bot-gfi-candidate-notification.yaml b/.github/workflows/bot-gfi-candidate-notification.yaml deleted file mode 100644 index b3973ac00..000000000 --- a/.github/workflows/bot-gfi-candidate-notification.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# This workflow notifies the GFI support team when an issue is labeled as GFI Candidate. - -name: Good First Issue Candidate Notification - -on: - issues: - types: - - labeled - -permissions: - issues: write - contents: read - -jobs: - gfi_candidate_notify_team: - runs-on: ubuntu-latest - if: contains(github.event.issue.labels.*.name, 'good first issue candidate') - concurrency: - group: gfi-candidate-${{ github.event.issue.number }} - cancel-in-progress: false - - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - - - name: Notify team of GFI candidate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: ${{ github.repository_owner != 'hiero-ledger' }} - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 - with: - script: | - const script = require('./.github/scripts/bot-gfi-candidate-notification.js'); - await script({ github, context }); diff --git a/.github/workflows/bot-inactivity-unassign.yml b/.github/workflows/bot-inactivity-unassign.yml deleted file mode 100644 index ae7f98aad..000000000 --- a/.github/workflows/bot-inactivity-unassign.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: bot-inactivity-unassign - -on: - schedule: - - cron: "0 12 * * *" - workflow_dispatch: - inputs: - dry_run: - description: "Run in dry-run mode (no unassign / close / comment)" - required: true - default: true - type: boolean - -permissions: - contents: read - issues: write - pull-requests: write - -jobs: - inactivity-unassign: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e - with: - egress-policy: audit - - - name: Run inactivity bot - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: ${{ github.repository }} - DAYS: 21 - # Behaviour: - # - schedule: DRY_RUN = 0 (real actions) - # - workflow_dispatch: DRY_RUN derived from the "dry_run" input - DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.dry_run == 'true' && '1' || '0') || '0' }} - run: bash .github/scripts/bot-inactivity-unassign.sh diff --git a/.github/workflows/bot-intermediate-assignment.yml b/.github/workflows/bot-intermediate-assignment.yml deleted file mode 100644 index f3da1ec22..000000000 --- a/.github/workflows/bot-intermediate-assignment.yml +++ /dev/null @@ -1,47 +0,0 @@ -# Prevents intermediate issues from being assigned to contributors without prior GFI experience. -name: Intermediate Issue Assignment Guard - -on: - issues: - types: - - assigned - workflow_dispatch: - inputs: - dry_run: - description: 'Run without making changes' - required: false - default: true - type: boolean - -permissions: - issues: write - contents: read - -jobs: - enforce-intermediate-guard: - concurrency: - group: intermediate-guard-${{ github.event.issue.number || github.run_id }} - cancel-in-progress: false - if: contains(github.event.issue.labels.*.name, 'intermediate') - runs-on: ubuntu-latest - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Enforce intermediate assignment guard - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - env: - INTERMEDIATE_LABEL: intermediate - GFI_LABEL: Good First Issue - INTERMEDIATE_COMMENT_MARKER: "" - INTERMEDIATE_EXEMPT_PERMISSIONS: admin,maintain,write,triage - DRY_RUN: "${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run != 'false' }}" - with: - script: | - const script = require('./.github/scripts/bot-intermediate-assignment.js'); - await script({ github, context }); diff --git a/.github/workflows/bot-issue-reminder-no-pr.yml b/.github/workflows/bot-issue-reminder-no-pr.yml deleted file mode 100644 index 60d467497..000000000 --- a/.github/workflows/bot-issue-reminder-no-pr.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: bot-issue-reminder-no-pr - -on: - schedule: - - cron: "0 13 * * *" #runs daily at 13:00 UTC - workflow_dispatch: - inputs: - dry_run: - description: "Dry run (log only, do not post comments)" - required: false - default: true #safe default for manual testing - type: boolean - -permissions: - contents: read - issues: write #needed to comment on issues - pull-requests: read #needed to check PR state - -jobs: - reminder: - runs-on: ubuntu-latest - - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #6.0.1 - - - name: Post reminder on assigned issues with no PRs - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: ${{ github.repository }} - DAYS: 7 - DRY_RUN: ${{ inputs.dry_run || 'false' }} - run: bash .github/scripts/bot-issue-reminder-no-pr.sh diff --git a/.github/workflows/bot-linked-issue-enforcer.yml b/.github/workflows/bot-linked-issue-enforcer.yml deleted file mode 100644 index 58f7a6b3b..000000000 --- a/.github/workflows/bot-linked-issue-enforcer.yml +++ /dev/null @@ -1,42 +0,0 @@ -# This workflow automatically closes pull requests without a linked issue after 3 days. - -name: Linked Issue Enforcer - -on: - schedule: - - cron: '45 11 * * 1,4' - workflow_dispatch: - inputs: - dry_run: - description: 'If true, do not post comments (dry run). Accepts "true" or "false". Default true for manual runs.' - required: false - default: 'true' - -permissions: - pull-requests: write - contents: read - -jobs: - pr-linked-issue-checker: - runs-on: ubuntu-latest - env: - DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} - - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - - name: Enforce linked issues on PRs - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: ${{ env.DRY_RUN }} - DAYS_BEFORE_CLOSE: '3' - REQUIRE_AUTHOR_ASSIGNED: 'true' - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 - with: - script: | - const script = require('./.github/scripts/linked_issue_enforce.js'); - await script({ github, context}); diff --git a/.github/workflows/bot-merge-conflict.yml b/.github/workflows/bot-merge-conflict.yml deleted file mode 100644 index c40344ccf..000000000 --- a/.github/workflows/bot-merge-conflict.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Merge Conflict Bot - -on: - pull_request_target: - types: [opened, synchronize, reopened] - push: - branches: - - main - workflow_dispatch: - inputs: - dry_run: - description: 'Run in dry-run mode (no comments or status updates)' - type: boolean - default: true - -permissions: - contents: read - pull-requests: write - issues: write - statuses: write - -concurrency: - group: "check-conflicts-${{ github.event.pull_request.number || github.sha }}" - cancel-in-progress: true - -jobs: - check-conflicts: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ github.event.repository.default_branch }} - - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Check for merge conflicts - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - env: - DRY_RUN: ${{ inputs.dry_run || 'false' }} - with: - script: | - const path = require('path') - const scriptPath = path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/bot-merge-conflict.js') - console.log(`Loading script from: ${scriptPath}`) - const script = require(scriptPath) - await script({github, context, core}) \ No newline at end of file diff --git a/.github/workflows/bot-next-issue-recommendation.yml b/.github/workflows/bot-next-issue-recommendation.yml deleted file mode 100644 index b73747b37..000000000 --- a/.github/workflows/bot-next-issue-recommendation.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Next Issue Recommendation Bot - -on: - pull_request_target: - types: [closed] - -permissions: - pull-requests: write - issues: read - contents: read - -concurrency: - group: next-issue-bot-${{ github.event.pull_request.number || github.run_id }} - cancel-in-progress: false - -jobs: - recommend-next-issue: - runs-on: ubuntu-latest - if: github.event.pull_request.merged == true - - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Recommend next issue - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # 8.0.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const script = require('./.github/scripts/bot-next-issue-recommendation.js'); - await script({ github, context, core }); diff --git a/.github/workflows/bot-office-hours.yml b/.github/workflows/bot-office-hours.yml deleted file mode 100644 index 9a777cb37..000000000 --- a/.github/workflows/bot-office-hours.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: PythonBot - Office Hour Reminder - -on: - schedule: - - cron: "0 10 * * 3" - workflow_dispatch: - inputs: - dry_run: - description: "Run in dry-run mode (log only, no comments posted)" - required: false - default: "true" - type: choice - options: - - "true" - - "false" - -permissions: - contents: read - pull-requests: write - -jobs: - office-hour-reminder: - runs-on: ubuntu-latest - concurrency: - group: office-hour-reminder - cancel-in-progress: false - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e #2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - - - name: Check Schedule and Notify - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }} - run: | - bash .github/scripts/bot-office-hours.sh diff --git a/.github/workflows/bot-p0-issues-notify-team.yml b/.github/workflows/bot-p0-issues-notify-team.yml deleted file mode 100644 index 37360eb2c..000000000 --- a/.github/workflows/bot-p0-issues-notify-team.yml +++ /dev/null @@ -1,38 +0,0 @@ -# This workflow warns the team about P0 issues immediately when they are created. -name: P0 Issue Alert -on: - - issues: - types: - - labeled - -permissions: - issues: write - contents: read - -jobs: - p0_notify_team: - runs-on: ubuntu-latest - # Only run for issues labeled with 'p0' (case-insensitive) - if: > - (github.event_name == 'issues' && ( - (github.event.label.name == 'p0' || github.event.label.name == 'P0')) - ) - - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 #v6.0.1 - - - name: Notify team of P0 issues - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 - with: - script: | - const script = require('./.github/scripts/bot-p0-issues-notify-team.js'); - await script({ github, context}); \ No newline at end of file diff --git a/.github/workflows/bot-pr-draft-ready-reminder.yaml b/.github/workflows/bot-pr-draft-ready-reminder.yaml deleted file mode 100644 index 33395709b..000000000 --- a/.github/workflows/bot-pr-draft-ready-reminder.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# This workflow reminds draft PR authors to mark ready for review after pushing changes - -name: PR Draft Ready Reminder Bot -on: - pull_request_target: - types: [synchronize] - -permissions: - contents: read - pull-requests: read - issues: write - -jobs: - draft-ready-reminder: - runs-on: ubuntu-latest - concurrency: - group: draft-ready-reminder-${{ github.event.pull_request.number }} - cancel-in-progress: true - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: main - - - name: Run draft-ready reminder bot - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd #v8.0.0 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const script = require('./.github/scripts/bot-pr-draft-ready-reminder.js'); - await script({ github, context }); \ No newline at end of file diff --git a/.github/workflows/bot-pr-inactivity-reminder.yml b/.github/workflows/bot-pr-inactivity-reminder.yml deleted file mode 100644 index 44999a5a9..000000000 --- a/.github/workflows/bot-pr-inactivity-reminder.yml +++ /dev/null @@ -1,42 +0,0 @@ -# This workflow warns PRs that have had no activity for a specified amount of time(10 Days). - -name: PR Inactivity Reminder Bot - -on: - schedule: - - cron: '0 11 * * *' - workflow_dispatch: - inputs: - dry_run: - description: 'If true, do not post comments (dry run). Accepts "true" or "false". Default true for manual runs.' - required: false - default: 'true' - -permissions: - pull-requests: write - issues: write - contents: read - - -jobs: - remind_inactive_prs: - runs-on: ubuntu-latest - env: - DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} - - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - name: Remind authors of inactive PRs - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: ${{ env.DRY_RUN }} - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd - with: - script: | - const script = require('./.github/scripts/pr_inactivity_reminder.js') - await script({ github, context }); \ No newline at end of file diff --git a/.github/workflows/bot-pr-missing-linked-issue.yml b/.github/workflows/bot-pr-missing-linked-issue.yml deleted file mode 100644 index 39269a4c9..000000000 --- a/.github/workflows/bot-pr-missing-linked-issue.yml +++ /dev/null @@ -1,54 +0,0 @@ -# This workflow checks PRs for linked issues and posts a reminder comment if missing. -# Uses pull_request_target to enable write permissions for fork PRs while checking out -# only the base branch code (ref: main) to avoid executing untrusted fork code. -name: PR Missing Linked Issue Reminder - -on: - pull_request_target: - types: [opened, edited, reopened] - workflow_dispatch: - inputs: - pr_number: - description: 'PR number to check' - required: true - type: number - dry_run: - description: 'Dry run (only log, no comments)' - required: false - type: boolean - default: true - -permissions: - pull-requests: write - contents: read - issues: write - -jobs: - check-linked-issue: - runs-on: ubuntu-latest - - concurrency: - group: bot-pr-missing-linked-issue-${{ github.event.pull_request.number || github.event.inputs.pr_number }} - cancel-in-progress: true - - steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: main - - - name: Check PR body for linked issue - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} - PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const script = require('./.github/scripts/bot-pr-missing-linked-issue.js'); - await script({ github, context }); diff --git a/.github/workflows/bot-verified-commits.yml b/.github/workflows/bot-verified-commits.yml deleted file mode 100644 index 3adb0479a..000000000 --- a/.github/workflows/bot-verified-commits.yml +++ /dev/null @@ -1,109 +0,0 @@ -# .github/workflows/bot-verified-commits.yml -# -# Verifies that all commits in a pull request are GPG-signed. -# Posts a one-time VerificationBot comment if unverified commits are found. -# -# This workflow uses pull_request_target for security with fork PRs. -# Logic is handled by .github/scripts/bot-verified-commits.js -# -# Configuration is done via environment variables for easy customization. - -name: PythonBot - Verify PR Commits - -on: - pull_request_target: - types: [opened, synchronize] - workflow_dispatch: - inputs: - pr_number: - description: "PR number to verify (required for manual runs)" - required: true - dry_run: - description: "Run without posting comments" - required: false - default: "true" - -permissions: - contents: read - pull-requests: write - issues: write - -concurrency: - group: "verify-commits-${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.pull_request.number }}" - cancel-in-progress: true - -jobs: - verify-commits: - runs-on: ubuntu-latest - - # ========================================================================= - # CONFIGURATION - All customizable values are defined here as env vars - # ========================================================================= - env: - # Bot identity - BOT_NAME: "VerificationBot" - BOT_LOGIN: "github-actions" - - # Comment marker for duplicate detection - COMMENT_MARKER: "[commit-verification-bot]" - - # Documentation links - SIGNING_GUIDE_URL: "https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/sdk_developers/signing.md" - README_URL: "https://github.com/hiero-ledger/hiero-sdk-python/blob/main/README.md" - DISCORD_URL: "https://github.com/hiero-ledger/hiero-sdk-python/blob/main/docs/discord.md" - - # Team signature - TEAM_NAME: "Hiero Python SDK Team" - - # Dry-run mode (workflow_dispatch uses input, PR events default to false) - DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || 'false' }} - - # PR number (supports both PR events and manual workflow_dispatch) - PR_NUMBER: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.pull_request.number }} - - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - sparse-checkout: .github/scripts - persist-credentials: false - - - name: Log workflow context - run: | - echo "Repository: ${{ github.repository }}" - echo "PR: ${{ env.PR_NUMBER }}" - echo "Actor: ${{ github.actor }}" - echo "Event: ${{ github.event_name }}" - echo "Dry run mode: ${{ env.DRY_RUN }}" - - - name: Verify PR commits - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - id: verify - env: - PR_NUMBER: ${{ env.PR_NUMBER }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - result-encoding: json - script: | - const script = require('./.github/scripts/bot-verified-commits.js'); - const result = await script({ github, context }); - - // Set outputs for downstream steps if needed - core.setOutput('success', result.success); - core.setOutput('unverified_count', result.unverifiedCount); - - return result; - - - name: Fail if unverified commits found - if: steps.verify.outputs.success != 'true' && env.DRY_RUN != 'true' - run: | - echo "❌ Pull request has unverified commits." - echo "Unverified commits: ${{ steps.verify.outputs.unverified_count }}" - echo "Please sign your commits with GPG." - echo "See: ${{ env.SIGNING_GUIDE_URL }}" - exit 1 diff --git a/.github/workflows/bot-workflows.yml b/.github/workflows/bot-workflows.yml deleted file mode 100644 index 93f4778d1..000000000 --- a/.github/workflows/bot-workflows.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: PythonBot - Workflow Failure Notifier -on: - workflow_dispatch: - workflow_run: - workflows: - - "PR Formatting" - - "PR Changelog Check" - - "Hiero Solo Integration & Unit Tests" - - "Run Examples" - types: - - completed -permissions: - contents: read - pull-requests: write -concurrency: - group: "workflow-failure-${{ github.event.workflow_run.head_branch }}" - cancel-in-progress: true -jobs: - notify-pr: - if: ${{ github.event.workflow_run.conclusion == 'failure' }} - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Get associated PR number - id: get-pr - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # Get branch from the workflow run - HEAD_BRANCH=$(gh run view ${{ github.event.workflow_run.id }} \ - --repo ${{ github.repository }} \ - --json headBranch --jq '.headBranch') - - # Find the PR number for this branch (only open PRs) - PR_NUMBER=$(gh pr list --repo ${{ github.repository }} --state open --head "$HEAD_BRANCH" --json number --jq '.[0].number') - echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV - - - name: Comment on PR - if: env.PR_NUMBER != '' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - REPO="${{ github.repository }}" - COMMENT=$(cat < **Note:** We use [Lychee](https://github.com/lycheeverse/lychee) for link checking. ` + - `Please check the "Check Markdown links" step in the logs to see the specific URLs that failed.`; - - if (dryRun) { - console.log("DRY RUN: Would have created or updated an issue."); - return; - } - - // Search for existing issue and Update/Create - try { - const { data: issues } = await github.rest.issues.listForRepo({ - owner: context.repo.owner, - repo: context.repo.repo, - state: 'open', - labels: targetLabels.join(','), - per_page: 100 - }); - - const existingIssue = issues.find(issue => issue.title === issueTitle); - - if (existingIssue) { - console.log(`Updating existing issue #${existingIssue.number}`); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: existingIssue.number, - body: `**Update ${new Date().toISOString()}:** Still finding broken links.\nCheck new run logs: ${runUrl}` - }); - } else { - console.log("Creating a new issue..."); - await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: issueTitle, - body: body, - labels: targetLabels - }); - } - } catch (error) { - console.error('Failed to manage broken link issue:', error); - core.setFailed(`Failed to create or update issue: ${error.message}`); - } diff --git a/.github/workflows/cron-update-spam-list.yml b/.github/workflows/cron-update-spam-list.yml deleted file mode 100644 index cc4f6fbb7..000000000 --- a/.github/workflows/cron-update-spam-list.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Cron Update Spam List - -on: - schedule: - - cron: '0 0 1 * *' # At 00:00 on day-of-month 1 (monthly) - workflow_dispatch: - inputs: - dry_run: - description: 'If true, do not post comments (dry run). Accepts "true" or "false". Default true for manual runs.' - required: false - default: 'true' - -permissions: - contents: read - pull-requests: read - issues: write - -env: - DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -jobs: - update-spam-list: - runs-on: ubuntu-latest - steps: - - name: Harden runner (audit outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Update spam list - id: update-spam-list - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - - with: - script: | - const updateSpamList = require('./.github/scripts/update-spam-list.js'); - await updateSpamList({ github, context, core }); diff --git a/.github/workflows/deps-check.yml b/.github/workflows/deps-check.yml deleted file mode 100644 index c318c1c3b..000000000 --- a/.github/workflows/deps-check.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Dependency Compatibility Check - -on: - push: - paths: - - "pyproject.toml" - pull_request: - paths: - - "pyproject.toml" - workflow_dispatch: - -permissions: - contents: read - -jobs: - min-deps: - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - python-version: ["3.10", "3.14"] - - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: ${{ matrix.python-version }} - cache: "pip" - - - name: Install uv - uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1 - - - name: Create virtual environment - run: uv venv - - - name: Install minimum dependencies and tooling - run: | - uv sync --all-extras --resolution=lowest-direct - - - name: Show resolved core dependency versions - run: | - echo "Resolved core dependency versions:" - PATTERN='^( - protobuf| - grpcio| - cryptography| - requests| - pycryptodome| - eth-abi| - python-dotenv| - eth-keys| - rlp| - grpcio-tools| - ruff| - mypy| - typing-extensions| - pytest - )\s' - uv pip list | grep -E "$(echo "$PATTERN" | tr -d '\n ')" - - - name: Generate Proto Files - run: | - uv run python generate_proto.py - - - name: Run unit tests (min deps) - run: | - uv run pytest tests/unit -v diff --git a/.github/workflows/pr-check-broken-links.yml b/.github/workflows/pr-check-broken-links.yml deleted file mode 100644 index 22a9ea880..000000000 --- a/.github/workflows/pr-check-broken-links.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: PR Check – Broken Markdown Links - -on: - pull_request: - paths: - - '**/*.md' - -permissions: - contents: read - -jobs: - pr-check-broken-links: - runs-on: ubuntu-latest - - steps: - - name: Harden runner (audit outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Check Markdown links - uses: tcort/github-action-markdown-link-check@e7c7a18363c842693fadde5d41a3bd3573a7a225 # v1.1.2 - with: - use-quiet-mode: 'yes' - check-modified-files-only: 'yes' - base-branch: 'main' diff --git a/.github/workflows/pr-check-changelog.yml b/.github/workflows/pr-check-changelog.yml deleted file mode 100644 index 8107c1768..000000000 --- a/.github/workflows/pr-check-changelog.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: 'PR Changelog Check' - -on: - pull_request: - types: [opened, reopened, edited, synchronize] - -permissions: - contents: read - -jobs: - changelog-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - fetch-depth: 0 - - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Run local changelog check - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - chmod +x .github/scripts/pr-check-changelog.sh - bash .github/scripts/pr-check-changelog.sh \ No newline at end of file diff --git a/.github/workflows/pr-check-codecov.yml b/.github/workflows/pr-check-codecov.yml deleted file mode 100644 index 2c9d97979..000000000 --- a/.github/workflows/pr-check-codecov.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Code Coverage - -on: - push: - branches: [main] - pull_request: - -permissions: - contents: read - -jobs: - coverage: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - fetch-depth: 2 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: "3.11" - - - name: Install uv - uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1 - - - name: Install dependencies - run: | - uv sync --all-extras --dev - - - name: Generate Proto Files - run: uv run python generate_proto.py - - - name: Run unit tests and generate coverage report - run: | - uv run pytest tests/unit \ - --cov=src \ - --cov-report=xml \ - --cov-report=term-missing - - - name: Upload coverage to Codecov - if: github.repository_owner == 'hiero-ledger' - uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage.xml - fail_ci_if_error: true diff --git a/.github/workflows/pr-check-examples.yml b/.github/workflows/pr-check-examples.yml deleted file mode 100644 index ac769956e..000000000 --- a/.github/workflows/pr-check-examples.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Run Examples -permissions: - contents: read - -on: - push: - branches: - - "**" - pull_request: - workflow_dispatch: - -jobs: - run-examples: - runs-on: ubuntu-latest - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - with: - fetch-depth: 0 - - - name: Install uv - uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 - - - name: Install dependencies - run: uv sync --all-extras - - - name: Generate Proto Files - run: uv run python generate_proto.py - - - name: Prepare Hiero Solo - id: solo - uses: hiero-ledger/hiero-solo-action@4d42a74e8e644a2753f3bb7a2afa429305375b14 #v0.15.0 - with: - installMirrorNode: true - - name: Run Examples - env: - OPERATOR_ID: ${{ steps.solo.outputs.accountId }} - OPERATOR_KEY: ${{ steps.solo.outputs.privateKey }} - CHAIN_ID: 012A - NETWORK: solo - shell: bash - run: | - set -euo pipefail - export PYTHONPATH="$PWD" - - files=$(find examples -name "*.py" -type f ! -name "__init__.py") - - for file in $files; do - echo -e "\n************ ${file} ************" - - # Convert path to module name - module=$(realpath --relative-to="$PWD" "$file" | sed 's|/|.|g' | sed 's|.py$||') - - if ! output=$(uv run -m "$module" 2>&1); then - echo -e "\n❌ Example failed: ${file}" - echo "************ Error Output ************" - echo "$output" - echo "**************************************" - exit 1 - fi - - echo "$output" - echo "✅ Completed ${file} successfully." - done diff --git a/.github/workflows/pr-check-test-files.yml b/.github/workflows/pr-check-test-files.yml deleted file mode 100644 index f46037642..000000000 --- a/.github/workflows/pr-check-test-files.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Test Files Naming Check - -on: - push: - branches-ignore: - - main - -permissions: - contents: read - -concurrency: - group: pr-checks-${{ github.workflow }}-${{ github.ref || github.run_id }} - cancel-in-progress: true - -jobs: - check-test-files: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - - name: Set up Hiero SDK Upstream - run: | - git remote set-url origin https://github.com/hiero-ledger/hiero-sdk-python.git - - - name: Fetch main branch - run: | - git fetch origin main - - - name: Check added test file names - run: | - chmod +x .github/scripts/pr-check-test-files.sh - .github/scripts/pr-check-test-files.sh diff --git a/.github/workflows/pr-check-test.yml b/.github/workflows/pr-check-test.yml deleted file mode 100644 index 8d17ff0d1..000000000 --- a/.github/workflows/pr-check-test.yml +++ /dev/null @@ -1,168 +0,0 @@ -name: Hiero Solo Integration & Unit Tests - -on: - push: - branches: - - "**" - pull_request: {} - workflow_dispatch: {} - -permissions: - contents: read - actions: write - -jobs: - build-and-test: - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] - - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: ${{ matrix.python-version }} - cache: "pip" - - - name: Install uv - uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1 - - - name: Install setuptools wheel - run: pip install --upgrade pip setuptools wheel - - - name: Install dependencies - run: uv sync --all-extras --dev - - - name: Generate Proto Files - run: uv run python generate_proto.py - - - name: Prepare Hiero Solo - id: solo - uses: hiero-ledger/hiero-solo-action@4d42a74e8e644a2753f3bb7a2afa429305375b14 # v0.15.0 - with: - installMirrorNode: true - - - name: Set environment variables - run: | - echo "OPERATOR_ID=${{ steps.solo.outputs.accountId }}" - echo "OPERATOR_KEY=${{ steps.solo.outputs.privateKey }}" - echo "ADMIN_KEY=${{ steps.solo.outputs.privateKey }}" - echo "PUBLIC_KEY=${{ steps.solo.outputs.publicKey }}" - - - name: Install your package - run: pip install -e . - - ############################################## - # INTEGRATION TESTS - ############################################## - - - name: Run all integration tests - id: integration - continue-on-error: true - shell: bash - env: - OPERATOR_ID: ${{ steps.solo.outputs.accountId }} - OPERATOR_KEY: ${{ steps.solo.outputs.privateKey }} - ADMIN_KEY: ${{ steps.solo.outputs.privateKey }} - PUBLIC_KEY: ${{ steps.solo.outputs.publicKey }} - NETWORK: solo - run: | - set -o pipefail - echo "🚀 Running integration tests..." - uv run pytest tests/integration -v --disable-warnings --continue-on-collection-errors 2>&1 | tee result_integration.log - pytest_exit=${PIPESTATUS[0]} - echo "integration_failed=$pytest_exit" >> $GITHUB_OUTPUT - cat result_integration.log - if [ $pytest_exit -ne 0 ]; then - echo "❌ Some integration tests failed" - echo "Failed tests:" - grep -E 'FAILED ' result_integration.log || true - else - echo "✅ All integration tests passed" - fi - - ############################################## - # UNIT TESTS - ############################################## - - - name: Run all unit tests - id: unit - continue-on-error: true - shell: bash - run: | - set -o pipefail - echo "🚀 Running unit tests..." - uv run pytest tests/unit -v --disable-warnings --continue-on-collection-errors 2>&1 | tee result_unit.log - pytest_exit=${PIPESTATUS[0]} - echo "unit_failed=$pytest_exit" >> $GITHUB_OUTPUT - cat result_unit.log - if [ $pytest_exit -ne 0 ]; then - echo "❌ Some unit tests failed" - echo "Failed tests:" - grep -E 'FAILED ' result_unit.log || true - else - echo "✅ All unit tests passed" - fi - - ############################################## - # SUMMARY & FAIL CONDITIONS - ############################################## - - - name: Fail workflow if any tests failed - shell: bash - run: | - integration_failed="${{ steps.integration.outputs.integration_failed }}" - unit_failed="${{ steps.unit.outputs.unit_failed }}" - - echo "" - echo "==================== TEST SUMMARY ====================" - - any_failed=false - - if [ "$integration_failed" != "0" ]; then - echo "❌ Integration tests FAILED" - echo " → Check the integration test logs above for details." - if [ -f result_integration.log ]; then - grep -E 'FAILED ' result_integration.log || echo " (No FAILED lines found)" - else - echo " (Integration log not found)" - fi - any_failed=true - else - echo "✅ Integration tests passed" - fi - - if [ "$unit_failed" != "0" ]; then - echo "❌ Unit tests FAILED" - echo " → Check the unit test logs above for details." - if [ -f result_unit.log ]; then - grep -E 'FAILED ' result_unit.log || echo " (No FAILED lines found)" - else - echo " (Unit log not found)" - fi - any_failed=true - else - echo "✅ Unit tests passed" - fi - - echo "======================================================" - echo "" - - # Final outcome - if [ "$any_failed" = true ]; then - echo "❌ Some tests failed. Failing workflow." - exit 1 - else - echo "✅ All tests passed!" - fi diff --git a/.github/workflows/pr-check-title.yml b/.github/workflows/pr-check-title.yml deleted file mode 100644 index 4c7ecc891..000000000 --- a/.github/workflows/pr-check-title.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: 'PR Formatting' -on: - workflow_dispatch: - pull_request_target: - types: - - opened - - reopened - - edited - - synchronize - -defaults: - run: - shell: bash - -permissions: - contents: read - checks: write - statuses: write - -concurrency: - group: pr-checks-${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - title-check: - name: Title Check - runs-on: ubuntu-latest - if: ${{ !github.event.pull_request.base.repo.fork }} - permissions: - checks: write - statuses: write - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Check PR Title - uses: step-security/conventional-pr-title-action@cb1c5657ccf4c42f5c0a6c0708cb8251b960d902 # v3.2.5 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index c3c2596e4..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Publish to PyPI - -on: - push: - tags: - - 'v*.*.*' - -permissions: - contents: read - -jobs: - build-and-publish: - runs-on: ubuntu-latest - environment: - name: pypi - url: https://pypi.org/p/hiero-sdk-python - permissions: - id-token: write - steps: - - name: Harden the runner (Audit all outbound calls) - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - - - name: Upgrade pip - run: pip install --upgrade pip - - - name: Install build, pdm-backend, and grpcio-tools - run: pip install build pdm-backend "grpcio-tools==1.68.1" - - - name: Generate Protobuf - run: python generate_proto.py - - - name: Build wheel and sdist - run: python -m build - - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # release/v1 diff --git a/.github/workflows/unassign-on-comment.yml b/.github/workflows/unassign-on-comment.yml deleted file mode 100644 index c6830dcaf..000000000 --- a/.github/workflows/unassign-on-comment.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Unassign on /unassign - -on: - issue_comment: - types: - - created - -permissions: - issues: write - contents: read - -jobs: - unassign: - # Only run on issue comments (not PR comments) - if: github.event.issue.pull_request == null - - runs-on: ubuntu-latest - - concurrency: - group: unassign-${{ github.event.issue.number }} - cancel-in-progress: false - - steps: - - name: Harden runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 - - - name: Run /unassign handler - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd - with: - script: | - const script = require('./.github/scripts/bot-unassign-on-comment.js'); - await script({ github, context }); diff --git a/.github/workflows/working-on-comment.yml b/.github/workflows/working-on-comment.yml deleted file mode 100644 index fd7d04dd6..000000000 --- a/.github/workflows/working-on-comment.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: "Bot: Working On Comment" - -on: - issue_comment: - types: [created] - workflow_dispatch: - inputs: - dry_run: - description: 'Log the run without making any changes' - required: true - default: "true" - type: string - -jobs: - working-command: - if: github.event_name == 'workflow_dispatch' || (github.event_name == 'issue_comment' && contains(github.event.comment.body, '/working')) - runs-on: ubuntu-latest - permissions: - issues: write - contents: read - concurrency: - group: working-command-${{ github.event.issue.number || github.run_id }} - cancel-in-progress: false - steps: - - name: Harden Runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 - with: - egress-policy: audit - - - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Handle /working command - id: working - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - env: - DRY_RUN: ${{ github.event.inputs.dry_run }} - with: - script: | - const handler = require('./.github/scripts/bot-working-on-comment.js') - await handler({github, context}) From 787a3a350000c692bd9cca961323a1383b4feffd Mon Sep 17 00:00:00 2001 From: exploreriii <133720349+exploreriii@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:28:15 +0000 Subject: [PATCH 3/5] chore: this PR solves something Signed-off-by: exploreriii <133720349+exploreriii@users.noreply.github.com> --- tests/integration/transfer_transaction_e2e_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/transfer_transaction_e2e_test.py b/tests/integration/transfer_transaction_e2e_test.py index 41272e3c2..7a881e7f2 100644 --- a/tests/integration/transfer_transaction_e2e_test.py +++ b/tests/integration/transfer_transaction_e2e_test.py @@ -23,7 +23,7 @@ @pytest.mark.integration def test_integration_transfer_transaction_can_transfer_hbar(): - env = IntegrationTestEnv() + env = IntegrationTestEnv() try: new_account_private_key = PrivateKey.generate() From f66261b527a76775b6a40e8164ad47b33899e0cd Mon Sep 17 00:00:00 2001 From: exploreriii <133720349+exploreriii@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:46:50 +0000 Subject: [PATCH 4/5] chore: add some logs Signed-off-by: exploreriii <133720349+exploreriii@users.noreply.github.com> --- .github/scripts/sync-issue-labels.js | 67 +++++++++++++++++++++++-- .github/workflows/sync-issue-labels.yml | 15 +++--- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/.github/scripts/sync-issue-labels.js b/.github/scripts/sync-issue-labels.js index 6d2d4d91e..f1a9b72f1 100644 --- a/.github/scripts/sync-issue-labels.js +++ b/.github/scripts/sync-issue-labels.js @@ -7,6 +7,7 @@ function isBotLogin(login = "") { function extractLinkedIssueNumbers(prBody = "") { const closingReferenceRegex = /\b(?:fix(?:es|ed)?|close(?:s|d)?|resolve(?:s|d)?)\s*:?\s*((?:#\d+)(?:\s*(?:,|and)\s*#\d+)*)/gi; + const numbers = new Set(); let referenceMatch; @@ -94,8 +95,7 @@ async function collectLabelsFromLinkedIssues({ github, owner, repo, linkedIssueN const issueLabelNames = normalizeLabelNames(issueResponse?.data?.labels || []); console.log( - `[sync-issue-labels] Issue #${issueNumber} labels: ${ - issueLabelNames.length ? issueLabelNames.join(", ") : "(none)" + `[sync-issue-labels] Issue #${issueNumber} labels: ${issueLabelNames.length ? issueLabelNames.join(", ") : "(none)" }` ); @@ -133,6 +133,57 @@ async function addLabelsToPullRequest({ github, owner, repo, prNumber, labelsToA console.log(`[sync-issue-labels] Added labels to PR #${prNumber}: ${labelsToAdd.join(", ")}`); } +// Logs context that helps diagnose permission / fork / event issues. +function logExecutionDiagnostics(context, prNumber, owner, repo, isDryRun) { + const pr = context?.payload?.pull_request; + + const baseRepo = pr?.base?.repo?.full_name; + const headRepo = pr?.head?.repo?.full_name; + const isFork = Boolean(pr?.head?.repo?.fork) || (baseRepo && headRepo && baseRepo !== headRepo); + + console.log("[sync-issue-labels] Diagnostics:"); + console.log(` eventName=${context?.eventName || "(unknown)"}`); + console.log(` action=${context?.payload?.action || "(none)"}`); + console.log(` actor=${context?.actor || context?.payload?.sender?.login || "(unknown)"}`); + console.log(` repo=${owner}/${repo}`); + console.log(` prNumber=${prNumber}`); + console.log(` dry_run=${isDryRun}`); + if (pr) { + console.log(` prAuthor=${pr?.user?.login || "(unknown)"}`); + console.log(` baseRepo=${baseRepo || "(unknown)"}`); + console.log(` headRepo=${headRepo || "(unknown)"}`); + console.log(` isFork=${isFork}`); + console.log(` headRef=${pr?.head?.ref || "(unknown)"}`); + console.log(` baseRef=${pr?.base?.ref || "(unknown)"}`); + } else { + console.log(" pull_request payload not present (likely workflow_dispatch or API fetch path)."); + } +} + +// Formats Octokit/GitHub API errors with useful details. +function logOctokitError(prefix, error) { + console.log(prefix); + console.log(` status: ${error?.status ?? "(unknown)"}`); + console.log(` message: ${error?.message ?? "(none)"}`); + + // Octokit typically provides response.data / response.headers on API errors + if (error?.response?.data) { + try { + console.log(` response.data: ${JSON.stringify(error.response.data, null, 2)}`); + } catch { + console.log(" response.data: (unserializable)"); + } + } + + const headers = error?.response?.headers; + if (headers) { + // These are the most useful for “Resource not accessible by integration” cases. + console.log(` x-accepted-github-permissions: ${headers["x-accepted-github-permissions"] || "(missing)"}`); + console.log(` x-github-request-id: ${headers["x-github-request-id"] || "(missing)"}`); + console.log(` github-authentication-token-expiration: ${headers["github-authentication-token-expiration"] || "(missing)"}`); + } +} + // Main entry point: syncs labels from linked issues to the PR. module.exports = async ({ github, context }) => { const { prNumber, isDryRun, owner, repo } = resolveExecutionContext(context); @@ -145,10 +196,14 @@ module.exports = async ({ github, context }) => { `[sync-issue-labels] Processing PR #${prNumber} in ${owner}/${repo} (dry_run=${isDryRun}).` ); + // Added diagnostics early, before any API writes. + logExecutionDiagnostics(context, prNumber, owner, repo, isDryRun); + let prData; try { prData = await getPullRequestData({ github, context, prNumber }); } catch (error) { + logOctokitError(`[sync-issue-labels] Failed to fetch PR #${prNumber}:`, error); throw new Error(`[sync-issue-labels] Failed to fetch PR #${prNumber}: ${error?.message || error}`); } @@ -180,8 +235,7 @@ module.exports = async ({ github, context }) => { const prLabelNames = new Set(normalizeLabelNames(prData?.labels || [])); console.log( - `[sync-issue-labels] Existing PR labels: ${ - prLabelNames.size ? [...prLabelNames].join(", ") : "(none)" + `[sync-issue-labels] Existing PR labels: ${prLabelNames.size ? [...prLabelNames].join(", ") : "(none)" }` ); console.log( @@ -201,8 +255,11 @@ module.exports = async ({ github, context }) => { try { await addLabelsToPullRequest({ github, owner, repo, prNumber, labelsToAdd }); } catch (error) { + // Added rich error logging for permission debugging. + logOctokitError(`[sync-issue-labels] Failed to add labels to PR #${prNumber}:`, error); + throw new Error( `[sync-issue-labels] Failed to add labels to PR #${prNumber}: ${error?.message || error}` ); } -}; +}; \ No newline at end of file diff --git a/.github/workflows/sync-issue-labels.yml b/.github/workflows/sync-issue-labels.yml index 294485f51..176d47785 100644 --- a/.github/workflows/sync-issue-labels.yml +++ b/.github/workflows/sync-issue-labels.yml @@ -3,6 +3,7 @@ name: Sync Linked Issue Labels to PR on: pull_request_target: types: [opened, edited, reopened, synchronize, ready_for_review] + workflow_dispatch: inputs: pr_number: @@ -16,8 +17,8 @@ on: default: true permissions: - pull-requests: read issues: write + pull-requests: read contents: read jobs: @@ -29,23 +30,23 @@ jobs: cancel-in-progress: true steps: - - name: Harden the runner - uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e # v2.14.2 + - name: Harden runner + uses: step-security/harden-runner@5ef0c079ce82195b2a36a210272d6b661572d83e with: egress-policy: audit - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 with: ref: main - - name: Sync linked issue labels to PR + - name: Sync labels from linked issues + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }} - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: + github-token: ${{ github.token }} script: | const script = require('./.github/scripts/sync-issue-labels.js'); await script({ github, context, core }); From 2da9a32c826a6fc07a069129b1d1a2ebf9f4cc0c Mon Sep 17 00:00:00 2001 From: exploreriii <133720349+exploreriii@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:47:58 +0000 Subject: [PATCH 5/5] chore: blank Signed-off-by: exploreriii <133720349+exploreriii@users.noreply.github.com> --- docs/sdk_developers/training/testing_forks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdk_developers/training/testing_forks.md b/docs/sdk_developers/training/testing_forks.md index e2766741e..ccbb8829b 100644 --- a/docs/sdk_developers/training/testing_forks.md +++ b/docs/sdk_developers/training/testing_forks.md @@ -6,7 +6,7 @@ To test safely, developers should use their personal **fork** of the repository. ## Prerequisites -By default, GitHub Actions are often disabled on forks to save resources. You must enable them manually: +By default, GitHub Actions are often disabled on forks to save resources. You must enable them manually: 1. Go to your fork on GitHub (e.g., `github.com//hiero-sdk-python`). 2. Click on the **Settings** tab.