Skip to content

feat: Add enhanced UI indicators (badges, avatars, progress) #7780 #3722

feat: Add enhanced UI indicators (badges, avatars, progress) #7780

feat: Add enhanced UI indicators (badges, avatars, progress) #7780 #3722

Workflow file for this run

name: Contribution Rate Limiter
on:
pull_request_target:
types: [opened]
permissions:
pull-requests: write
issues: write
jobs:
check-rate-limit:
name: Check Daily PR Rate Limit
runs-on: ubuntu-latest
steps:
- name: Check Contributor PR Count
uses: actions/github-script@v7
with:
script: |
const prNumber = context.payload.pull_request.number;
const prAuthor = context.payload.pull_request.user.login;
const owner = context.repo.owner;
const repo = context.repo.repo;
const DAILY_LIMIT = 30;
console.log(`Checking PR count for author "${prAuthor}"...`);
// Exclude the repository owner from rate limiting
if (prAuthor === owner) {
console.log("Author is the repository owner. Skipping rate limit check.");
return;
}
// Calculate date 24 hours ago in ISO format
const limitDate = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('.')[0] + 'Z';
// Search query: is:pr repo:owner/repo author:username created:>=limitDate
const q = `repo:${owner}/${repo} is:pr author:${prAuthor} created:>=${limitDate}`;
console.log(`Searching PRs with query: ${q}`);
let totalCount = 0;
try {
const searchResult = await github.rest.search.issuesAndPullRequests({ q });
totalCount = searchResult.data.total_count;
console.log(`Found ${totalCount} PRs submitted by @${prAuthor} in the last 24 hours.`);
} catch (err) {
console.log(`Error calling search API: ${err.message}`);
// Fallback: list pulls and filter
const pulls = await github.rest.pulls.list({ owner, repo, state: 'all', per_page: 100 });
const limitMs = Date.now() - 24 * 60 * 60 * 1000;
const matchingPulls = pulls.data.filter(p => p.user.login === prAuthor && new Date(p.created_at).getTime() >= limitMs);
totalCount = matchingPulls.length;
console.log(`Fallback: Found ${totalCount} PRs in last 100 items.`);
}
if (totalCount > DAILY_LIMIT) {
console.log(`User @${prAuthor} has opened ${totalCount} PRs in the last 24 hours. Exceeds limit of ${DAILY_LIMIT}.`);
const commentBody = `### 🛑 Contribution Rate Limit Exceeded\n\n` +
`Hi @${prAuthor}! 👋\n\n` +
`To maintain repository stability, review quality, and a fair contribution distribution, EaseMotion CSS enforces a soft contribution limit of up to **30 PRs per day** per contributor.\n\n` +
`It looks like you have submitted **${totalCount} pull requests** in the last 24 hours (including this one), which exceeds this limit.\n\n` +
`To ensure focus on quality, originality, and proper testing, we have automatically closed this pull request for now. Please wait until tomorrow or close some of your other active PRs before submitting new ones.\n\n` +
`Thank you for your understanding and cooperation! 🚀`;
// Post comment
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: commentBody
});
// Add rate-limited label
try {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: ['rate-limited']
});
} catch (labelErr) {
console.log(`Could not add rate-limited label: ${labelErr.message}`);
}
// Close PR
await github.rest.pulls.update({
owner,
repo,
pull_number: prNumber,
state: 'closed'
});
console.log(`PR #${prNumber} closed successfully.`);
} else {
console.log(`User @${prAuthor} is within limit (${totalCount}/${DAILY_LIMIT}).`);
}