Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 62 additions & 22 deletions .github/scripts/bot-pr-missing-linked-issue.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
module.exports = async ({ github, context }) => {
const body = context.payload.pull_request.body || "";
const regex = /\bFixes\s*:?\s*(#\d+)(\s*,\s*#\d+)*/i;
let prNumber;
try {
const isDryRun = process.env.DRY_RUN === 'true';
prNumber = parseInt(process.env.PR_NUMBER) || context.payload.pull_request.number;

console.log(`Processing PR #${prNumber} (Dry run: ${isDryRun})`);

// For workflow_dispatch, we need to fetch PR details
let prData;
if (context.payload.pull_request) {
prData = context.payload.pull_request;
} else {
// workflow_dispatch case - fetch PR data
const prResponse = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
prData = prResponse.data;
}

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

const alreadyCommented = comments.data.some(comment =>
comment.body.includes("this is LinkBot")
);

if (alreadyCommented) {
return;
}

if (!regex.test(body)) {
await github.rest.issues.createComment({
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: [
`Hi @${context.payload.pull_request.user.login}, this is **LinkBot** 👋`,
issue_number: prNumber,
});

const alreadyCommented = comments.data.some(comment =>
comment.body.includes("this is LinkBot")
);

if (alreadyCommented) {
console.log('LinkBot already commented on this PR');
return;
}

if (!regex.test(body)) {
const commentBody = [
`Hi @${prData.user.login}, this is **LinkBot** 👋`,
``,
`Linking pull requests to issues helps us significantly with reviewing pull requests and keeping the repository healthy.`,
``,
Expand All @@ -38,8 +56,30 @@ module.exports = async ({ github, context }) => {
`[docs/sdk_developers/creating_issues.md](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/docs/sdk_developers/creating_issues.md)`,
``,
`Thanks!`
].join('\n')
});
].join('\n');

if (isDryRun) {
console.log('DRY RUN: Would post the following comment:');
console.log('---');
console.log(commentBody);
console.log('---');
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: commentBody,
});
console.log('LinkBot comment posted successfully');
}
} else {
console.log('PR has linked issue - no comment needed');
}
} catch (error) {
console.error('Error processing PR:', error);
console.error('PR number:', prNumber);
console.error('Repository:', `${context.repo.owner}/${context.repo.repo}`);
throw error;
}
};

23 changes: 21 additions & 2 deletions .github/workflows/bot-pr-missing-linked-issue.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
# 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:
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 }}
group: bot-pr-missing-linked-issue-${{ github.event.pull_request.number || github.event.inputs.pr_number }}
cancel-in-progress: true

steps:
Expand All @@ -24,10 +39,14 @@ jobs:

- 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: |
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
- Workflow does not contain permissions for `pr-check-test-files` and `pr-check-codecov`
- Fixed `cron-check-broken-links.yml` string parsing issue in context input `dry_run` (#1235)
- Flaky tests by disabling TLS in mock Hedera nodes in `mock_server.py`
- Fixed LinkBot permission issue for fork PRs by changing trigger to pull_request_target and adding proper permissions.

### Breaking Change

Expand Down