Skip to content

Commit 9dbeb59

Browse files
Fix getting permissions for the contributors who are a part of the team (#424)
* Fix getActorPermission to handle team-based permissions * Use 'user.permissions' object to return permission * Add RepoPermission type * Make new build
1 parent 1aebff8 commit 9dbeb59

File tree

4 files changed

+82
-42
lines changed

4 files changed

+82
-42
lines changed

dist/index.js

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -293,24 +293,41 @@ class GitHubHelper {
293293
};
294294
}
295295
getActorPermission(repo, actor) {
296+
var _a;
296297
return __awaiter(this, void 0, void 0, function* () {
297-
// https://docs.github.com/en/graphql/reference/enums#repositorypermission
298-
// https://docs.github.com/en/graphql/reference/objects#repositorycollaboratoredge
299-
// Returns 'READ', 'TRIAGE', 'WRITE', 'MAINTAIN', 'ADMIN'
300-
const query = `query CollaboratorPermission($owner: String!, $repo: String!, $collaborator: String) {
301-
repository(owner:$owner, name:$repo) {
302-
collaborators(login: $collaborator) {
303-
edges {
304-
permission
305-
}
306-
}
307-
}
308-
}`;
309-
const collaboratorPermission = yield this.octokit.graphql(query, Object.assign(Object.assign({}, repo), { collaborator: actor }));
310-
core.debug(`CollaboratorPermission: ${(0, util_1.inspect)(collaboratorPermission.repository.collaborators.edges)}`);
311-
return collaboratorPermission.repository.collaborators.edges.length > 0
312-
? collaboratorPermission.repository.collaborators.edges[0].permission.toLowerCase()
313-
: 'none';
298+
// Use the REST API approach which can detect both direct and team-based permissions
299+
// This is more reliable than the GraphQL approach for team permissions and works better with default GITHUB_TOKEN
300+
try {
301+
const { data: collaboratorPermission } = yield this.octokit.rest.repos.getCollaboratorPermissionLevel(Object.assign(Object.assign({}, repo), { username: actor }));
302+
const permissions = (_a = collaboratorPermission.user) === null || _a === void 0 ? void 0 : _a.permissions;
303+
core.debug(`REST API collaborator permission: ${(0, util_1.inspect)(permissions)}`);
304+
// Use the detailed permissions object to get the highest permission level
305+
if (permissions) {
306+
// Check permissions in order of highest to lowest
307+
if (permissions.admin) {
308+
return 'admin';
309+
}
310+
else if (permissions.maintain) {
311+
return 'maintain';
312+
}
313+
else if (permissions.push) {
314+
return 'write';
315+
}
316+
else if (permissions.triage) {
317+
core.debug(`User ${actor} has triage permission via REST API`);
318+
return 'triage';
319+
}
320+
else if (permissions.pull) {
321+
core.debug(`User ${actor} has read permission via REST API`);
322+
return 'read';
323+
}
324+
}
325+
return 'none';
326+
}
327+
catch (error) {
328+
core.debug(`REST API permission check failed: ${utils.getErrorMessage(error)}`);
329+
return 'none';
330+
}
314331
});
315332
}
316333
tryAddReaction(repo, commentId, reaction) {

src/command-helper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export function configIsValid(config: Command[]): string | null {
175175
}
176176

177177
export function actorHasPermission(
178-
actorPermission: string,
178+
actorPermission: utils.RepoPermission,
179179
commandPermission: string
180180
): boolean {
181181
const permissionLevels = Object.freeze({

src/github-helper.ts

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,32 +55,47 @@ export class GitHubHelper {
5555
}
5656
}
5757

58-
async getActorPermission(repo: Repository, actor: string): Promise<string> {
59-
// https://docs.github.com/en/graphql/reference/enums#repositorypermission
60-
// https://docs.github.com/en/graphql/reference/objects#repositorycollaboratoredge
61-
// Returns 'READ', 'TRIAGE', 'WRITE', 'MAINTAIN', 'ADMIN'
62-
const query = `query CollaboratorPermission($owner: String!, $repo: String!, $collaborator: String) {
63-
repository(owner:$owner, name:$repo) {
64-
collaborators(login: $collaborator) {
65-
edges {
66-
permission
67-
}
58+
async getActorPermission(
59+
repo: Repository,
60+
actor: string
61+
): Promise<utils.RepoPermission> {
62+
// Use the REST API approach which can detect both direct and team-based permissions
63+
// This is more reliable than the GraphQL approach for team permissions and works better with default GITHUB_TOKEN
64+
try {
65+
const {data: collaboratorPermission} =
66+
await this.octokit.rest.repos.getCollaboratorPermissionLevel({
67+
...repo,
68+
username: actor
69+
})
70+
71+
const permissions = collaboratorPermission.user?.permissions
72+
core.debug(`REST API collaborator permission: ${inspect(permissions)}`)
73+
74+
// Use the detailed permissions object to get the highest permission level
75+
if (permissions) {
76+
// Check permissions in order of highest to lowest
77+
if (permissions.admin) {
78+
return 'admin'
79+
} else if (permissions.maintain) {
80+
return 'maintain'
81+
} else if (permissions.push) {
82+
return 'write'
83+
} else if (permissions.triage) {
84+
core.debug(`User ${actor} has triage permission via REST API`)
85+
return 'triage'
86+
} else if (permissions.pull) {
87+
core.debug(`User ${actor} has read permission via REST API`)
88+
return 'read'
6889
}
6990
}
70-
}`
71-
const collaboratorPermission =
72-
await this.octokit.graphql<CollaboratorPermission>(query, {
73-
...repo,
74-
collaborator: actor
75-
})
76-
core.debug(
77-
`CollaboratorPermission: ${inspect(
78-
collaboratorPermission.repository.collaborators.edges
79-
)}`
80-
)
81-
return collaboratorPermission.repository.collaborators.edges.length > 0
82-
? collaboratorPermission.repository.collaborators.edges[0].permission.toLowerCase()
83-
: 'none'
91+
92+
return 'none'
93+
} catch (error) {
94+
core.debug(
95+
`REST API permission check failed: ${utils.getErrorMessage(error)}`
96+
)
97+
return 'none'
98+
}
8499
}
85100

86101
async tryAddReaction(

src/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import * as core from '@actions/core'
22

3+
export type RepoPermission =
4+
| 'admin'
5+
| 'maintain'
6+
| 'write'
7+
| 'triage'
8+
| 'read'
9+
| 'none'
10+
311
export function getInputAsArray(
412
name: string,
513
options?: core.InputOptions

0 commit comments

Comments
 (0)