-
Notifications
You must be signed in to change notification settings - Fork 14
229 lines (210 loc) Β· 11.2 KB
/
update-loosegoose-leaderboard.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
name: Update Loose Goose Leaderboard
on:
schedule:
- cron: '0 * * * *' # Runs every hour at the start of the hour
workflow_dispatch: # Allows manual triggering
permissions:
issues: write
pull-requests: read
jobs:
update-leaderboard:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Update Leaderboard
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const issueNumber = 46; // Change this to match your issue number
const REPOS = [
'block-open-source/goose-plugins', // Update to your repo(s)
];
const calculatePoints = (labels) => {
const labelNames = labels.map(label => label.name.toLowerCase());
const hasLooseGoose = labelNames.includes('loosegoose');
const hasCode = labelNames.includes('code');
return {
points: hasLooseGoose && hasCode ? 15 : (hasLooseGoose ? 10 : 0),
isCodePR: hasCode,
isContentPR: hasLooseGoose && !hasCode
};
};
const fetchRecentPRs = async (repo) => {
try {
console.log(`Fetching recent PRs for ${repo}`);
const [repoOwner, repoName] = repo.split('/');
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
const { data: prs } = await github.rest.pulls.list({
owner: repoOwner,
repo: repoName,
state: 'closed',
sort: 'updated',
direction: 'desc',
per_page: 100
});
console.log(`Fetched ${prs.length} PRs for ${repo}`);
const loosegoosePRs = prs.filter(pr => {
const isMerged = !!pr.merged_at;
const isRecent = new Date(pr.merged_at) > new Date(thirtyDaysAgo);
const isLoosegoose = pr.labels.some(label => label.name.toLowerCase() === 'loosegoose');
return isMerged && isRecent && isLoosegoose;
}).map(pr => {
const pointsData = calculatePoints(pr.labels);
return {
user: pr.user.login,
points: pointsData.points,
isCodePR: pointsData.isCodePR,
isContentPR: pointsData.isContentPR,
repo: repo,
prNumber: pr.number,
prTitle: pr.title,
};
});
return loosegoosePRs;
} catch (error) {
console.error(`Error fetching PRs for ${repo}: ${error.message}`);
return [];
}
};
const generateLeaderboard = async () => {
try {
const allPRs = await Promise.all(REPOS.map(fetchRecentPRs));
const flatPRs = allPRs.flat();
const leaderboard = flatPRs.reduce((acc, pr) => {
if (!acc[pr.user]) {
acc[pr.user] = {
points: 0,
prs: 0,
codePRs: 0,
contentPRs: 0
};
}
acc[pr.user].points += pr.points;
acc[pr.user].prs += 1;
if (pr.isCodePR) {
acc[pr.user].codePRs += 1;
}
if (pr.isContentPR) {
acc[pr.user].contentPRs += 1;
}
return acc;
}, {});
return Object.entries(leaderboard)
.sort(([, a], [, b]) => b.points - a.points)
.map(([username, data], index) => ({
rank: index + 1,
username,
points: data.points,
prs: data.prs,
codePRs: data.codePRs,
contentPRs: data.contentPRs
}));
} catch (error) {
console.error(`Error generating leaderboard: ${error.message}`);
return [];
}
};
const updateIssue = async (leaderboardData) => {
try {
const rows = leaderboardData.map(entry =>
`| ${entry.rank} | @${entry.username} | ${entry.points} | ${entry.prs} | ${entry.codePRs} | ${entry.contentPRs} |`
).join('\n');
const issueBody = [
'# π Loose Goose November 2024 Leaderboard π',
'You thought Hacktoberfest 2024 was over?! The open source party is just getting started..! Wrap up 2024 with a bang (or honk) while enjoying super-fun contributions with Loose Goose November. From Nov 1st to Nov 20th, check our live leaderboard below to see who our top contributors are in real-time. Not only does this recognize everyone\'s efforts, it also brings an amplified competitive vibe with each contribution. π',
'',
'## This event is open to both employees and external contributors! π¦’',
'### π **Current Rankings:**',
'| Rank | Contributor | Points | Total PRs | Code PRs | Content PRs |',
'|------|-------------|--------|-----------|-----------|-------------|',
rows,
'',
'### π How It Works:',
'The top 3 contributors with the most points will earn $$$ gift cards (more on rewards below). Points are awarded based on the following criteria:',
'- 15 points for each merged PR with both `loosegoose` and `code` labels',
'- 10 points for each merged PR with just the `loosegoose` label (Content PR)',
'',
'### π Rewards',
'- Among our **top 3**? Our Top 3 Superstars earn $150 gift cards on Amazon. Stay tuned for the winners!',
'',
'### FAQ',
'- **Frequency of Updates:** The leaderboard will be updated every 1 hour.',
'- **Points System:**',
' - 15 points: Code PRs (PRs with both `loosegoose` and `code` labels)',
' - 10 points: Content PRs (PRs with just the `loosegoose` label)',
'- **Criteria:** Rankings are based on how many points you earn and PRs you close in the goose-plugins repo. To ensure your PRs are successfully merged:',
' - Ensure your contributions are aligned with our [project\'s CoC](https://github.com/block-open-source/goose-plugins/blob/main/CODE_OF_CONDUCT.md).',
' - Refer to our [Contributing Guide](https://github.com/block-open-source/goose-plugins/blob/main/CONTRIBUTING.md).',
'- **Tie-Breaker:** In the event of a tie-breaker, the tie-breaking PR that was submitted soonest will break the tie.',
'',
'### π Get Featured:',
'Want to see your name climbing our ranks? Explore our content issues with the labels `loosegoose` in our Loose Goose Project Hub:',
'- [ ] #32',
'',
'Excited to see everyone\'s hard work. Thank you so much for your invaluable contributions, and let the fun competition begin!',
`Last updated: ${new Date().toUTCString()}`
].join('\n');
await github.rest.issues.update({
owner,
repo,
issue_number: issueNumber,
body: issueBody
});
console.log("Issue updated successfully!");
} catch (error) {
throw new Error(`Failed to update issue: ${error.message}`);
}
};
// Main execution
const leaderboardData = await generateLeaderboard();
if (leaderboardData.length > 0) {
await updateIssue(leaderboardData);
} else {
console.log("No leaderboard data to update.");
const emptyIssueBody = [
'# π Loose Goose November 2024 Leaderboard π',
'You thought Hacktoberfest 2024 was over?! The open source party is just getting started..! Wrap up 2024 with a bang (or honk) while enjoying super-fun contributions with Loose Goose November. From Nov 1st to Nov 20th, check our live leaderboard below to see who our top contributors are in real-time. Not only does this recognize everyone\'s efforts, it also brings an amplified competitive vibe with each contribution. π',
'',
'## This event is open to both employees and external contributors! π¦’',
'### π **Current Rankings:**',
'| Rank | Contributor | Points | Total PRs | Code PRs | Content PRs |',
'|------|-------------|--------|-----------|-----------|-------------|',
'No qualifying PRs found at this time. Check back soon!',
'',
'### π How It Works:',
'The top 3 contributors with the most points will earn $$$ gift cards (more on rewards below). Points are awarded based on the following criteria:',
'- 15 points for each merged PR with both `loosegoose` and `code` labels (Code PR)',
'- 10 points for each merged PR with just the `loosegoose` label (Content PR)',
'',
'### π Rewards',
'- Among our **top 3**? Our Top 3 Superstars earn $150 gift cards on Amazon. Stay tuned for the winners!',
'',
'### FAQ',
'- **Frequency of Updates:** The leaderboard will be updated every 1 hour.',
'- **Points System:**',
' - 15 points: Code PRs (PRs with both `loosegoose` and `code` labels)',
' - 10 points: Content PRs (PRs with just the `loosegoose` label)',
'- **Criteria:** Rankings are based on how many points you earn and PRs you close in the goose-plugins repo. To ensure your PRs are successfully merged:',
' - Ensure your contributions are aligned with our [project\'s CoC](https://github.com/block-open-source/goose-plugins/blob/main/CODE_OF_CONDUCT.md).',
' - Refer to our [Contributing Guide](https://github.com/block-open-source/goose-plugins/blob/main/CONTRIBUTING.md).',
'- **Tie-Breaker:** In the event of a tie-breaker, the tie-breaking PR that was submitted soonest will break the tie.',
'',
'### π Get Featured:',
'Want to see your name climbing our ranks? Explore our content issues with the labels `loosegoose` in our Loose Goose Project Hub:',
'- [ ] #32',
'',
'Excited to see everyone\'s hard work. Thank you so much for your invaluable contributions, and let the fun competition begin!',
`Last updated: ${new Date().toUTCString()}`
].join('\n');
await github.rest.issues.update({
owner,
repo,
issue_number: issueNumber,
body: emptyIssueBody
});
console.log("Updated issue with empty leaderboard message.");
}