Auto-label PRs by source and type #14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Auto-label PRs by source and type | |
on: | |
pull_request: | |
types: [opened] | |
branches: [main] | |
workflow_dispatch: | |
inputs: | |
pr_number: | |
description: 'PR number to label' | |
required: true | |
type: string | |
jobs: | |
auto-label-source-type: | |
runs-on: ubuntu-latest | |
permissions: | |
pull-requests: write | |
contents: read | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Analyze PR and add labels | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
let prToProcess; | |
if (context.eventName === 'pull_request') { | |
prToProcess = context.payload.pull_request; | |
} else if (context.eventName === 'workflow_dispatch') { | |
const prNumber = '${{ inputs.pr_number }}'; | |
console.log(`Manual trigger for PR #${prNumber}`); | |
const { data: pr } = await github.rest.pulls.get({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
pull_number: parseInt(prNumber) | |
}); | |
prToProcess = pr; | |
} | |
const prNumber = prToProcess.number; | |
console.log(`Processing PR #${prNumber}`); | |
const { data: files } = await github.rest.pulls.listFiles({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
pull_number: prNumber | |
}); | |
console.log(`Found ${files.length} files changed`); | |
let touchesCMS = false; | |
let touchesCloud = false; | |
let touchesOther = false; | |
let hasNewFile = false; | |
let totalChanges = 0; | |
for (const file of files) { | |
console.log(`File: ${file.filename}, status: ${file.status}, +${file.additions} -${file.deletions}`); | |
if (file.filename.startsWith('cms/')) { | |
touchesCMS = true; | |
} else if (file.filename.startsWith('cloud/')) { | |
touchesCloud = true; | |
} else { | |
touchesOther = true; | |
} | |
if (file.status === 'added') { | |
hasNewFile = true; | |
} | |
totalChanges += file.additions + file.deletions; | |
} | |
console.log(`Summary: CMS=${touchesCMS}, Cloud=${touchesCloud}, Other=${touchesOther}`); | |
console.log(`Has new file: ${hasNewFile}, Total changes: ${totalChanges}`); | |
let sourceLabel; | |
if ((touchesCMS && !touchesCloud && !touchesOther)) { | |
sourceLabel = 'source: CMS'; | |
} else if ((touchesCloud && !touchesCMS && !touchesOther)) { | |
sourceLabel = 'source: Strapi Cloud'; | |
} else { | |
sourceLabel = 'source: repo'; | |
} | |
let prTypeLabel; | |
if (hasNewFile) { | |
prTypeLabel = 'pr: new content'; | |
} else if (totalChanges > 10) { | |
prTypeLabel = 'pr: updated content'; | |
} else { | |
prTypeLabel = 'pr: chore'; | |
} | |
console.log(`Determined labels: ${sourceLabel}, ${prTypeLabel}`); | |
const existingLabels = prToProcess.labels.map(label => label.name); | |
const hasSourceLabel = existingLabels.some(label => label.startsWith('source:')); | |
const hasPrTypeLabel = existingLabels.some(label => label.startsWith('pr:')); | |
const labelsToAdd = []; | |
if (!hasSourceLabel) { | |
labelsToAdd.push(sourceLabel); | |
} else { | |
console.log(`PR #${prNumber} already has a source label, skipping source label`); | |
} | |
if (!hasPrTypeLabel) { | |
labelsToAdd.push(prTypeLabel); | |
} else { | |
console.log(`PR #${prNumber} already has a pr type label, skipping pr type label`); | |
} | |
if (labelsToAdd.length === 0) { | |
console.log(`No labels to add to PR #${prNumber}`); | |
return; | |
} | |
try { | |
await github.rest.issues.addLabels({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: prNumber, | |
labels: labelsToAdd | |
}); | |
console.log(`Successfully added labels to PR #${prNumber}: ${labelsToAdd.join(', ')}`); | |
} catch (error) { | |
console.error(`Error adding labels to PR #${prNumber}:`, error); | |
core.setFailed(`Failed to add labels to PR #${prNumber}: ${error.message}`); | |
} |