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
7 changes: 7 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# kirti owns everything
* @kirti

# Specific ownership
/.github/workflows/ @kirti
/src/ @kirti
*.md @kirti
226 changes: 226 additions & 0 deletions .github/workflows/pr-automation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
name: PR Automation

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
# Job 1: Auto-label based on files changed
auto-label:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Label based on files changed
uses: actions/github-script@v7
with:
script: |
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});

const labels = new Set();

for (const file of files) {
const path = file.filename;

if (path.includes('.github/workflows/')) {
labels.add('workflows');
}

if (path.startsWith('src/')) {
labels.add('source-code');
}

if (path.includes('.test.') || path.includes('.spec.')) {
labels.add('tests');
}

if (path.endsWith('.md')) {
labels.add('documentation');
}

if (path === 'package.json' || path === 'package-lock.json') {
labels.add('dependencies');
}

if (path.endsWith('.css') || path.endsWith('.scss')) {
labels.add('styles');
}

if (path.includes('components/')) {
labels.add('components');
}
}

if (labels.size > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: Array.from(labels)
});
}

# Job 2: Check PR size and add size label
size-label:
runs-on: ubuntu-latest
permissions:
pull-requests: write

steps:
- name: Check PR size
uses: actions/github-script@v7
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});

const additions = pr.additions;
const deletions = pr.deletions;
const totalChanges = additions + deletions;

let sizeLabel = 'size/XS';

if (totalChanges >= 1000) {
sizeLabel = 'size/XL';
} else if (totalChanges >= 500) {
sizeLabel = 'size/L';
} else if (totalChanges >= 200) {
sizeLabel = 'size/M';
} else if (totalChanges >= 50) {
sizeLabel = 'size/S';
}

const { data: labels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

for (const label of labels) {
if (label.name.startsWith('size/')) {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
name: label.name
}).catch(() => {});
}
}

await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: [sizeLabel]
}).catch(() => {});

# Job 3: Comment with PR statistics
pr-stats:
runs-on: ubuntu-latest
needs: size-label
permissions:
pull-requests: write

steps:
- name: Comment PR with stats
uses: actions/github-script@v7
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});

const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
});

const additions = pr.additions;
const deletions = pr.deletions;
const changedFiles = pr.changed_files;
const totalChanges = additions + deletions;

let size = 'XS';
if (totalChanges >= 1000) {
size = 'XL';
} else if (totalChanges >= 500) {
size = 'L';
} else if (totalChanges >= 200) {
size = 'M';
} else if (totalChanges >= 50) {
size = 'S';
}

const fileTypes = {};
for (const file of files) {
const ext = file.filename.split('.').pop();
fileTypes[ext] = (fileTypes[ext] || 0) + 1;
}

const fileTypesStr = Object.entries(fileTypes)
.sort((a, b) => b[1] - a[1])
.slice(0, 5)
.map(([ext, count]) => `- ${ext}: ${count} files`)
.join('\n');

let recommendation = 'Great! This PR is easy to review.';
if (totalChanges >= 500) {
recommendation = 'Large PR! Consider splitting into smaller PRs for easier review.';
} else if (totalChanges >= 200) {
recommendation = 'Medium-sized PR. Consider breaking it down if possible.';
}

const commentBody = '## PR Statistics - Size: ' + size + '\n\n' +
'**Total Changes:** ' + totalChanges + ' lines\n\n' +
'### Changes\n' +
'- Additions: ' + additions + ' lines\n' +
'- Deletions: ' + deletions + ' lines\n' +
'- Files changed: ' + changedFiles + '\n\n' +
'### File Types\n' +
fileTypesStr + '\n\n' +
'### Review Recommendations\n' +
recommendation + '\n\n' +
'---\n' +
'*Automated by PR Automation*';

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('PR Statistics')
);

if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: commentBody
});
}
2 changes: 1 addition & 1 deletion Simple-Node.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,4 @@ Steps execute sequentially within a job:

If any step fails, subsequent steps are skipped and the workflow fails.

---
---
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
"version": "0.1.0",
"private": true,
"homepage": "https://kirti.github.io/github-actions-practice",
"author": "Kirti",
"repository": {
"type": "git",
"url": "https://github.com/kirti/github-actions-practice.git"
},
"dependencies": {
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
Expand Down
Loading