Skip to content

Commit 5357666

Browse files
chore(workflows): add a workflow to notify authors with write access to not fork
2 parents ad88956 + 7fb3ae9 commit 5357666

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
name: Check PR author write access
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, reopened, synchronize]
6+
7+
jobs:
8+
check-author-permissions:
9+
runs-on: ubuntu-latest
10+
# Only run this check on PRs from forks
11+
if: github.event.pull_request.head.repo.full_name != github.repository
12+
steps:
13+
- name: Check if PR author has write access
14+
id: check-access
15+
uses: actions/github-script@v7
16+
with:
17+
github-token: ${{ secrets.GITHUB_TOKEN }}
18+
script: |
19+
const owner = context.repo.owner;
20+
const repo = context.repo.repo;
21+
const author = context.payload.pull_request.user.login;
22+
23+
console.log(`Checking if ${author} has write access to ${owner}/${repo}`);
24+
25+
try {
26+
// Check if user has collaborator access
27+
const { data: collaboratorPermission } = await github.rest.repos.getCollaboratorPermissionLevel({
28+
owner,
29+
repo,
30+
username: author
31+
});
32+
33+
console.log(`User ${author} has permission level: ${collaboratorPermission.permission}`);
34+
35+
// Check if permission is write or admin
36+
if (['write', 'admin'].includes(collaboratorPermission.permission)) {
37+
core.setOutput('has-write-access', 'true');
38+
return;
39+
}
40+
} catch (error) {
41+
console.log(`Error checking collaborator status: ${error.message}`);
42+
// If we can't get the permission level, they might not be a direct collaborator
43+
// Continue checking team membership
44+
}
45+
46+
try {
47+
// Get all teams in the organization
48+
const { data: teams } = await github.rest.teams.list({
49+
org: owner
50+
});
51+
52+
// Check each team for the user and their permissions
53+
for (const team of teams) {
54+
try {
55+
// Check if user is in the team
56+
const { data: membership } = await github.rest.teams.getMembershipForUserInOrg({
57+
org: owner,
58+
team_slug: team.slug,
59+
username: author
60+
});
61+
62+
if (membership.state === 'active') {
63+
console.log(`User ${author} is a member of team ${team.name}`);
64+
65+
// Check team's repository permission
66+
const { data: teamPerm } = await github.rest.teams.getRepoPermissionsInOrg({
67+
org: owner,
68+
team_slug: team.slug,
69+
owner,
70+
repo
71+
});
72+
73+
console.log(`Team ${team.name} has permission level: ${teamPerm.permission}`);
74+
75+
if (['write', 'admin', 'maintain'].includes(teamPerm.permission)) {
76+
core.setOutput('has-write-access', 'true');
77+
return;
78+
}
79+
}
80+
} catch (error) {
81+
console.log(`Error checking team membership for ${team.name}: ${error.message}`);
82+
// Continue checking other teams
83+
}
84+
}
85+
} catch (error) {
86+
console.log(`Error listing teams: ${error.message}`);
87+
}
88+
89+
// If we reach here, user does not have write access
90+
core.setOutput('has-write-access', 'false');
91+
92+
- name: Comment on PR if author has write access
93+
if: steps.check-access.outputs.has-write-access == 'true'
94+
uses: actions/github-script@v7
95+
with:
96+
github-token: ${{ secrets.GITHUB_TOKEN }}
97+
script: |
98+
const owner = context.repo.owner;
99+
const repo = context.repo.repo;
100+
const issue_number = context.issue.number;
101+
const author = context.payload.pull_request.user.login;
102+
103+
await github.rest.issues.createComment({
104+
owner,
105+
repo,
106+
issue_number,
107+
body: `@${author} - It appears you have write access to this repository.
108+
109+
Please close this PR and create a new one directly from a branch in the original repository rather than from a fork.
110+
111+
As a repository collaborator with write access, you can push branches directly to the repository, which is the preferred workflow.`
112+
});
113+
114+
core.setFailed('PR author has write access to the repository. PR should be created from the original repository instead of a fork.');

0 commit comments

Comments
 (0)