From 5edd70cd05f2068b048674757e4cca473b57cf42 Mon Sep 17 00:00:00 2001 From: Harshit Date: Tue, 9 Jun 2026 12:58:24 +0530 Subject: [PATCH] feat(workflow): add automated pull request triage --- .github/scripts/triagePr.js | 116 +++++++++++++++++++++++++++++++++ .github/workflows/triagePr.yml | 25 +++++++ 2 files changed, 141 insertions(+) create mode 100644 .github/scripts/triagePr.js create mode 100644 .github/workflows/triagePr.yml diff --git a/.github/scripts/triagePr.js b/.github/scripts/triagePr.js new file mode 100644 index 00000000..62a11ecd --- /dev/null +++ b/.github/scripts/triagePr.js @@ -0,0 +1,116 @@ +module.exports = async ({github, context}) => { + const owner = context.repo.owner; + const repo = context.repo.repo; + const pr = context.payload.pull_request; + const prNumber = pr.number; + const username = pr.user.login; + + const backendFiles = []; + const webFiles = []; + const mobileFiles = []; + const devopsFiles = []; + + const labels = []; + let primaryArea = null; + let reviewer = null; + + try { + const changedFiles = await github.paginate( + github.rest.pulls.listFiles, + { + owner, + repo, + pull_number: prNumber + } + ); + + changedFiles.forEach((file) => { + const fileName = file.filename; + + if(fileName.startsWith('apps/backend/')){ + backendFiles.push(fileName); + }else if(fileName.startsWith('apps/web/')){ + webFiles.push(fileName); + }else if(fileName.startsWith('apps/mobile/')){ + mobileFiles.push(fileName) + }else if(fileName.startsWith('.github/') || fileName.startsWith('infra/') || fileName.startsWith('terraform/')){ + devopsFiles.push(fileName) + } + }) + + + if(backendFiles.length > 0){ + labels.push('backend') + + if(!primaryArea){ + primaryArea = 'backend'; + reviewer = '@Harxhit' + } + } + if(mobileFiles.length > 0){ + labels.push('mobile'); + if(!primaryArea){ + primaryArea = 'mobile'; + reviewer = '@blankirigaya' + } + } + if(webFiles.length > 0){ + labels.push('web'); + if(!primaryArea){ + primaryArea = 'web'; + reviewer = '@ShantKhatri' + } + } + if(devopsFiles.length > 0){ + labels.push('devops') + if(!primaryArea){ + primaryArea = 'devops' + reviewer = '@ShantKhatri' + } + } + + if(labels.length === 0){ + return; + } + + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: prNumber, + labels + }); + const body = `Hi @${username}, + +Thanks for opening this pull request. + +This PR has been automatically classified based on the files modified. + +### Applied Labels + +${labels.map(label => `- ${label}`).join('\n')} + +### Primary Review Area + +* ${primaryArea} + +### Reviewer + +${reviewer} has been identified as the primary reviewer for this pull request. + +If you have any questions regarding the affected area or implementation details, feel free to reach out to the assigned reviewer. + +Thank you for your contribution! `; + + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: body + }); + + } catch (error) { + console.error(error) + } + +} \ No newline at end of file diff --git a/.github/workflows/triagePr.yml b/.github/workflows/triagePr.yml new file mode 100644 index 00000000..d8d9dadc --- /dev/null +++ b/.github/workflows/triagePr.yml @@ -0,0 +1,25 @@ +name: Pull request triage + +on: + pull_request: + types: [opened] + +permissions: + pull-requests: write + issues: write + +jobs: + assignLabel: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2 + + - name: Triage pull request + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 #v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const script = require('./.github/scripts/triagePr.js'); + await script({ github, context }); \ No newline at end of file