Skip to content

Commit c32d289

Browse files
committed
Invite Recent Contributors to organization
1 parent 6272f73 commit c32d289

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Invite Recent Contributors to organization
2+
on:
3+
schedule:
4+
- cron: '0 0 * * 0' # Weekly
5+
workflow_dispatch:
6+
inputs:
7+
dry-run:
8+
description: 'Run without actually inviting users'
9+
required: false
10+
default: 'false'
11+
12+
jobs:
13+
check-eligibility:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Collect PR authors from multiple Armbian repositories
17+
id: get-contributors
18+
uses: actions/github-script@v7
19+
with:
20+
github-token: ${{ secrets.GITHUB_TOKEN }}
21+
script: |
22+
const org = 'armbian';
23+
const repos = ['build', 'firmware', 'documentation', 'configng', 'os', 'armbian.github.io','linux-rockchip', 'apa'];
24+
const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(); // last ~6 months
25+
//const since = new Date(Date.now() - 182 * 24 * 60 * 60 * 1000).toISOString(); // last ~6 months
26+
const isBot = (username) => username.endsWith('[bot]');
27+
const contributors = new Set();
28+
29+
for (const repo of repos) {
30+
console.log(`🔍 Searching PRs created since ${since} in ${org}/${repo}`);
31+
let page = 1;
32+
let results;
33+
34+
do {
35+
results = await github.rest.search.issuesAndPullRequests({
36+
q: `is:pr repo:${org}/${repo} created:>=${since}`,
37+
per_page: 100,
38+
page,
39+
});
40+
41+
for (const pr of results.data.items) {
42+
if (pr.user && pr.user.login) {
43+
const username = pr.user.login;
44+
if (!isBot(username)) {
45+
contributors.add(username);
46+
console.log(`✅ ${username} opened a PR in ${repo}`);
47+
} else {
48+
console.log(`🤖 Skipping bot: ${username}`);
49+
}
50+
}
51+
}
52+
53+
page++;
54+
} while (results.data.items.length === 100);
55+
}
56+
57+
const usernames = Array.from(contributors);
58+
console.log("🧾 Unique PR authors from all repos:", usernames);
59+
core.setOutput("usernames", JSON.stringify(usernames));
60+
61+
62+
- name: Check if users are already members of Armbian org (display eligible users)
63+
uses: actions/github-script@v7
64+
with:
65+
github-token: ${{ secrets.ORG_INVITE }}
66+
script: |
67+
const dryRun = '${{ github.event.inputs.dry-run }}' === 'true';
68+
const usernames = JSON.parse('${{ steps.get-contributors.outputs.usernames }}');
69+
const org = 'armbian';
70+
const eligibleUsers = [];
71+
72+
let tableMarkdown = '\n| Username | Full Name |\n|----------|-----------|\n';
73+
74+
for (const username of usernames) {
75+
try {
76+
await github.rest.orgs.getMembershipForUser({ org, username });
77+
console.log(`ℹ️ ${username} is already a member of ${org}`);
78+
} catch (error) {
79+
if (error.status === 404) {
80+
try {
81+
const { data: user } = await github.rest.users.getByUsername({ username });
82+
const name = user.name || '(no name provided)';
83+
eligibleUsers.push({ username, name });
84+
85+
tableMarkdown += `| [${username}](https://github.com/${username}) | ${name} |\n`;
86+
87+
if (dryRun) {
88+
console.log(`🛑 Dry-run: Would invite ${username} to ${org}`);
89+
} else {
90+
await github.rest.orgs.createInvitation({
91+
org,
92+
invitee_id: user.id,
93+
role: 'direct_member',
94+
});
95+
invited = '✅';
96+
console.log(`✅ Invited ${username} to ${org}`);
97+
}
98+
} catch (err) {
99+
console.log(`⚠️ Error fetching details for ${username}: ${err.message}`);
100+
}
101+
} else {
102+
console.log(`⚠️ Error checking membership for ${username}: ${error.message}`);
103+
}
104+
}
105+
}
106+
107+
if (eligibleUsers.length === 0) {
108+
console.log(`No users eligible for invitation.`);
109+
await core.summary
110+
.addHeading('Eligible Users')
111+
.addRaw('No eligible users found.')
112+
.write();
113+
} else {
114+
console.log(`Eligible users to invite: ${eligibleUsers.map(u => u.username).join(', ')}`);
115+
await core.summary
116+
.addHeading('Eligible Users to Invite')
117+
.addRaw(tableMarkdown, true)
118+
.write();
119+
}

0 commit comments

Comments
 (0)