From ce10e0e0461e0ad8ad2cdec780baa4092b96ba8d Mon Sep 17 00:00:00 2001 From: Eeshu-Yadav Date: Sun, 8 Mar 2026 23:30:14 +0530 Subject: [PATCH 1/3] [feature] Add issue autoassignment bots #1265 Added GitHub Actions workflows to auto-assign issues, manage PR-issue linking, handle PR reopening reassignment, and manage stale PRs. Closes #1265 --- .github/workflows/bot-autoassign-issue.yml | 49 +++++++++++ .../bot-autoassign-pr-issue-link.yml | 49 +++++++++++ .../workflows/bot-autoassign-pr-reopen.yml | 87 +++++++++++++++++++ .github/workflows/bot-autoassign-stale-pr.yml | 49 +++++++++++ 4 files changed, 234 insertions(+) create mode 100644 .github/workflows/bot-autoassign-issue.yml create mode 100644 .github/workflows/bot-autoassign-pr-issue-link.yml create mode 100644 .github/workflows/bot-autoassign-pr-reopen.yml create mode 100644 .github/workflows/bot-autoassign-stale-pr.yml diff --git a/.github/workflows/bot-autoassign-issue.yml b/.github/workflows/bot-autoassign-issue.yml new file mode 100644 index 000000000..2943c7b5f --- /dev/null +++ b/.github/workflows/bot-autoassign-issue.yml @@ -0,0 +1,49 @@ +name: Issue Assignment Bot + +on: + issue_comment: + types: [created] + +permissions: + contents: read + issues: write + +concurrency: + group: bot-autoassign-issue-${{ github.repository }}-${{ github.event.issue.number }} + cancel-in-progress: true + +jobs: + respond-to-assign-request: + runs-on: ubuntu-latest + if: github.event.issue.pull_request == null + steps: + - name: Generate GitHub App token + id: generate-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} + private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} + + - name: Checkout openwisp-utils + uses: actions/checkout@v6 + with: + repository: openwisp/openwisp-utils + ref: master + path: openwisp-utils + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install dependencies + run: pip install -e openwisp-utils/.[github_actions] + + - name: Run issue assignment bot + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + REPOSITORY: ${{ github.repository }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + run: > + python openwisp-utils/.github/actions/bot-autoassign/__main__.py + issue_assignment "$GITHUB_EVENT_PATH" diff --git a/.github/workflows/bot-autoassign-pr-issue-link.yml b/.github/workflows/bot-autoassign-pr-issue-link.yml new file mode 100644 index 000000000..b73948df8 --- /dev/null +++ b/.github/workflows/bot-autoassign-pr-issue-link.yml @@ -0,0 +1,49 @@ +name: PR Issue Auto-Assignment + +on: + pull_request_target: + types: [opened, reopened, closed] + +permissions: + contents: read + issues: write + pull-requests: read + +concurrency: + group: bot-autoassign-pr-link-${{ github.repository }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + auto-assign-issue: + runs-on: ubuntu-latest + steps: + - name: Generate GitHub App token + id: generate-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} + private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} + + - name: Checkout openwisp-utils + uses: actions/checkout@v6 + with: + repository: openwisp/openwisp-utils + ref: master + path: openwisp-utils + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install dependencies + run: pip install -e openwisp-utils/.[github_actions] + + - name: Run issue assignment bot + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + REPOSITORY: ${{ github.repository }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + run: > + python openwisp-utils/.github/actions/bot-autoassign/__main__.py + issue_assignment "$GITHUB_EVENT_PATH" diff --git a/.github/workflows/bot-autoassign-pr-reopen.yml b/.github/workflows/bot-autoassign-pr-reopen.yml new file mode 100644 index 000000000..11b325c15 --- /dev/null +++ b/.github/workflows/bot-autoassign-pr-reopen.yml @@ -0,0 +1,87 @@ +name: PR Reopen Reassignment + +on: + pull_request_target: + types: [reopened] + issue_comment: + types: [created] + +permissions: + contents: read + issues: write + pull-requests: read + +concurrency: + group: bot-autoassign-pr-reopen-${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number }} + cancel-in-progress: true + +jobs: + reassign-on-reopen: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request_target' && github.event.action == 'reopened' + steps: + - name: Generate GitHub App token + id: generate-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} + private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} + + - name: Checkout openwisp-utils + uses: actions/checkout@v6 + with: + repository: openwisp/openwisp-utils + ref: master + path: openwisp-utils + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install dependencies + run: pip install -e openwisp-utils/.[github_actions] + + - name: Reassign issues on PR reopen + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + REPOSITORY: ${{ github.repository }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + run: > + python openwisp-utils/.github/actions/bot-autoassign/__main__.py + pr_reopen "$GITHUB_EVENT_PATH" + + handle-pr-activity: + runs-on: ubuntu-latest + if: github.event_name == 'issue_comment' && github.event.issue.pull_request + steps: + - name: Generate GitHub App token + id: generate-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} + private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} + + - name: Checkout openwisp-utils + uses: actions/checkout@v6 + with: + repository: openwisp/openwisp-utils + ref: master + path: openwisp-utils + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install dependencies + run: pip install -e openwisp-utils/.[github_actions] + + - name: Handle PR activity + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + REPOSITORY: ${{ github.repository }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + run: > + python openwisp-utils/.github/actions/bot-autoassign/__main__.py + pr_reopen "$GITHUB_EVENT_PATH" diff --git a/.github/workflows/bot-autoassign-stale-pr.yml b/.github/workflows/bot-autoassign-stale-pr.yml new file mode 100644 index 000000000..4584b9963 --- /dev/null +++ b/.github/workflows/bot-autoassign-stale-pr.yml @@ -0,0 +1,49 @@ +name: Stale PR Management + +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +permissions: + contents: read + issues: write + pull-requests: write + +concurrency: + group: bot-autoassign-stale-pr-${{ github.repository }} + cancel-in-progress: false + +jobs: + manage-stale-prs-python: + runs-on: ubuntu-latest + steps: + - name: Generate GitHub App token + id: generate-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} + private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} + + - name: Checkout openwisp-utils + uses: actions/checkout@v6 + with: + repository: openwisp/openwisp-utils + ref: master + path: openwisp-utils + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.13" + + - name: Install dependencies + run: pip install -e openwisp-utils/.[github_actions] + + - name: Run stale PR bot + env: + GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + REPOSITORY: ${{ github.repository }} + run: > + python openwisp-utils/.github/actions/bot-autoassign/__main__.py + stale_pr From 8177cd0b4add2faa6e6380104fa5de084346f768 Mon Sep 17 00:00:00 2001 From: Eeshu Yadav <153345870+Eeshu-Yadav@users.noreply.github.com> Date: Mon, 16 Mar 2026 00:27:03 +0530 Subject: [PATCH 2/3] [ci:fix] Use updated reusable bot-autoassign workflows Refines the caller workflows to use the updated `reusable-bot-autoassign.yml` from openwisp-utils. Reduces boilerplate, removes custom installations, and fixes bugs like the bot running on merged PRs. --- .github/workflows/bot-autoassign-issue.yml | 42 ++------- .../bot-autoassign-pr-issue-link.yml | 43 ++-------- .../workflows/bot-autoassign-pr-reopen.yml | 85 +++---------------- .github/workflows/bot-autoassign-stale-pr.yml | 41 ++------- 4 files changed, 33 insertions(+), 178 deletions(-) diff --git a/.github/workflows/bot-autoassign-issue.yml b/.github/workflows/bot-autoassign-issue.yml index 2943c7b5f..754e35196 100644 --- a/.github/workflows/bot-autoassign-issue.yml +++ b/.github/workflows/bot-autoassign-issue.yml @@ -1,49 +1,19 @@ name: Issue Assignment Bot - on: issue_comment: types: [created] - permissions: contents: read issues: write - concurrency: group: bot-autoassign-issue-${{ github.repository }}-${{ github.event.issue.number }} cancel-in-progress: true - jobs: respond-to-assign-request: - runs-on: ubuntu-latest if: github.event.issue.pull_request == null - steps: - - name: Generate GitHub App token - id: generate-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} - private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} - - - name: Checkout openwisp-utils - uses: actions/checkout@v6 - with: - repository: openwisp/openwisp-utils - ref: master - path: openwisp-utils - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.13" - - - name: Install dependencies - run: pip install -e openwisp-utils/.[github_actions] - - - name: Run issue assignment bot - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - REPOSITORY: ${{ github.repository }} - GITHUB_EVENT_NAME: ${{ github.event_name }} - run: > - python openwisp-utils/.github/actions/bot-autoassign/__main__.py - issue_assignment "$GITHUB_EVENT_PATH" + uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + with: + bot_command: issue_assignment + secrets: + OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }} + OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} diff --git a/.github/workflows/bot-autoassign-pr-issue-link.yml b/.github/workflows/bot-autoassign-pr-issue-link.yml index b73948df8..20215125d 100644 --- a/.github/workflows/bot-autoassign-pr-issue-link.yml +++ b/.github/workflows/bot-autoassign-pr-issue-link.yml @@ -1,49 +1,20 @@ name: PR Issue Auto-Assignment - on: pull_request_target: types: [opened, reopened, closed] - permissions: contents: read issues: write pull-requests: read - concurrency: group: bot-autoassign-pr-link-${{ github.repository }}-${{ github.event.pull_request.number }} cancel-in-progress: true - jobs: auto-assign-issue: - runs-on: ubuntu-latest - steps: - - name: Generate GitHub App token - id: generate-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} - private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} - - - name: Checkout openwisp-utils - uses: actions/checkout@v6 - with: - repository: openwisp/openwisp-utils - ref: master - path: openwisp-utils - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.13" - - - name: Install dependencies - run: pip install -e openwisp-utils/.[github_actions] - - - name: Run issue assignment bot - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - REPOSITORY: ${{ github.repository }} - GITHUB_EVENT_NAME: ${{ github.event_name }} - run: > - python openwisp-utils/.github/actions/bot-autoassign/__main__.py - issue_assignment "$GITHUB_EVENT_PATH" + if: github.event.action != 'closed' || github.event.pull_request.merged == false + uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + with: + bot_command: issue_assignment + secrets: + OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }} + OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} diff --git a/.github/workflows/bot-autoassign-pr-reopen.yml b/.github/workflows/bot-autoassign-pr-reopen.yml index 11b325c15..4ee943020 100644 --- a/.github/workflows/bot-autoassign-pr-reopen.yml +++ b/.github/workflows/bot-autoassign-pr-reopen.yml @@ -1,87 +1,30 @@ name: PR Reopen Reassignment - on: pull_request_target: types: [reopened] issue_comment: types: [created] - permissions: contents: read issues: write - pull-requests: read - + pull-requests: write concurrency: group: bot-autoassign-pr-reopen-${{ github.repository }}-${{ github.event.pull_request.number || github.event.issue.number }} cancel-in-progress: true - jobs: reassign-on-reopen: - runs-on: ubuntu-latest if: github.event_name == 'pull_request_target' && github.event.action == 'reopened' - steps: - - name: Generate GitHub App token - id: generate-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} - private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} - - - name: Checkout openwisp-utils - uses: actions/checkout@v6 - with: - repository: openwisp/openwisp-utils - ref: master - path: openwisp-utils - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.13" - - - name: Install dependencies - run: pip install -e openwisp-utils/.[github_actions] - - - name: Reassign issues on PR reopen - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - REPOSITORY: ${{ github.repository }} - GITHUB_EVENT_NAME: ${{ github.event_name }} - run: > - python openwisp-utils/.github/actions/bot-autoassign/__main__.py - pr_reopen "$GITHUB_EVENT_PATH" - + uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + with: + bot_command: pr_reopen + secrets: + OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }} + OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} handle-pr-activity: - runs-on: ubuntu-latest - if: github.event_name == 'issue_comment' && github.event.issue.pull_request - steps: - - name: Generate GitHub App token - id: generate-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} - private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} - - - name: Checkout openwisp-utils - uses: actions/checkout@v6 - with: - repository: openwisp/openwisp-utils - ref: master - path: openwisp-utils - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.13" - - - name: Install dependencies - run: pip install -e openwisp-utils/.[github_actions] - - - name: Handle PR activity - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - REPOSITORY: ${{ github.repository }} - GITHUB_EVENT_NAME: ${{ github.event_name }} - run: > - python openwisp-utils/.github/actions/bot-autoassign/__main__.py - pr_reopen "$GITHUB_EVENT_PATH" + if: github.event_name == 'issue_comment' && github.event.issue.pull_request && github.event.issue.user.login == github.event.comment.user.login + uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + with: + bot_command: pr_reopen + secrets: + OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }} + OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} diff --git a/.github/workflows/bot-autoassign-stale-pr.yml b/.github/workflows/bot-autoassign-stale-pr.yml index 4584b9963..80e420484 100644 --- a/.github/workflows/bot-autoassign-stale-pr.yml +++ b/.github/workflows/bot-autoassign-stale-pr.yml @@ -1,49 +1,20 @@ name: Stale PR Management - on: schedule: - cron: "0 0 * * *" workflow_dispatch: - permissions: contents: read issues: write pull-requests: write - concurrency: group: bot-autoassign-stale-pr-${{ github.repository }} cancel-in-progress: false - jobs: manage-stale-prs-python: - runs-on: ubuntu-latest - steps: - - name: Generate GitHub App token - id: generate-token - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ secrets.OPENWISP_BOT_APP_ID }} - private-key: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} - - - name: Checkout openwisp-utils - uses: actions/checkout@v6 - with: - repository: openwisp/openwisp-utils - ref: master - path: openwisp-utils - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: "3.13" - - - name: Install dependencies - run: pip install -e openwisp-utils/.[github_actions] - - - name: Run stale PR bot - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - REPOSITORY: ${{ github.repository }} - run: > - python openwisp-utils/.github/actions/bot-autoassign/__main__.py - stale_pr + uses: openwisp/openwisp-utils/.github/workflows/reusable-bot-autoassign.yml@master + with: + bot_command: stale_pr + secrets: + OPENWISP_BOT_APP_ID: ${{ secrets.OPENWISP_BOT_APP_ID }} + OPENWISP_BOT_PRIVATE_KEY: ${{ secrets.OPENWISP_BOT_PRIVATE_KEY }} From 1eaab274892f085aadcb7304d11177b48782b5d9 Mon Sep 17 00:00:00 2001 From: Eeshu Yadav <153345870+Eeshu-Yadav@users.noreply.github.com> Date: Mon, 16 Mar 2026 00:51:22 +0530 Subject: [PATCH 3/3] [fix] Fix duplicate reopen trigger Removes 'reopened' from the types on `bot-autoassign-pr-issue-link.yml`. The `bot-autoassign-pr-reopen.yml` already properly handles PR reopens, meaning this additional trigger was causing bot spam and race conditions. --- .github/workflows/bot-autoassign-pr-issue-link.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bot-autoassign-pr-issue-link.yml b/.github/workflows/bot-autoassign-pr-issue-link.yml index 20215125d..9908fc02e 100644 --- a/.github/workflows/bot-autoassign-pr-issue-link.yml +++ b/.github/workflows/bot-autoassign-pr-issue-link.yml @@ -1,7 +1,7 @@ name: PR Issue Auto-Assignment on: pull_request_target: - types: [opened, reopened, closed] + types: [opened, closed] permissions: contents: read issues: write