scaffolder: Add support for granting access on create
This commit is contained in:
@@ -18,10 +18,14 @@ export const mockGithubClient = {
|
||||
repos: {
|
||||
createInOrg: jest.fn(),
|
||||
createForAuthenticatedUser: jest.fn(),
|
||||
addCollaborator: jest.fn(),
|
||||
},
|
||||
users: {
|
||||
getByUsername: jest.fn(),
|
||||
},
|
||||
teams: {
|
||||
addOrUpdateRepoPermissionsInOrg: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
export class Octokit {
|
||||
|
||||
@@ -30,6 +30,7 @@ const { mockGithubClient } = require('@octokit/rest') as {
|
||||
mockGithubClient: {
|
||||
repos: jest.Mocked<Octokit['repos']>;
|
||||
users: jest.Mocked<Octokit['users']>;
|
||||
teams: jest.Mocked<Octokit['teams']>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -76,6 +77,7 @@ describe('GitHub Publisher', () => {
|
||||
values: {
|
||||
storePath: 'blam/test',
|
||||
owner: 'bob',
|
||||
access: 'blam/team',
|
||||
},
|
||||
directory: '/tmp/test',
|
||||
});
|
||||
@@ -84,6 +86,15 @@ describe('GitHub Publisher', () => {
|
||||
org: 'blam',
|
||||
name: 'test',
|
||||
});
|
||||
expect(
|
||||
mockGithubClient.teams.addOrUpdateRepoPermissionsInOrg,
|
||||
).toHaveBeenCalledWith({
|
||||
org: 'blam',
|
||||
team_slug: 'team',
|
||||
owner: 'blam',
|
||||
repo: 'test',
|
||||
permission: 'admin',
|
||||
});
|
||||
});
|
||||
|
||||
it('should use octokit to create a repo in the authed user if the organisation property is not set', async () => {
|
||||
@@ -102,6 +113,7 @@ describe('GitHub Publisher', () => {
|
||||
values: {
|
||||
storePath: 'blam/test',
|
||||
owner: 'bob',
|
||||
access: 'blam',
|
||||
},
|
||||
directory: '/tmp/test',
|
||||
});
|
||||
@@ -111,14 +123,49 @@ describe('GitHub Publisher', () => {
|
||||
).toHaveBeenCalledWith({
|
||||
name: 'test',
|
||||
});
|
||||
expect(mockGithubClient.repos.addCollaborator).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should invite other user in the authed user', async () => {
|
||||
mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({
|
||||
data: {
|
||||
clone_url: 'mockclone',
|
||||
},
|
||||
} as OctokitResponse<ReposCreateInOrgResponseData>);
|
||||
mockGithubClient.users.getByUsername.mockResolvedValue({
|
||||
data: {
|
||||
type: 'User',
|
||||
},
|
||||
} as OctokitResponse<UsersGetByUsernameResponseData>);
|
||||
|
||||
await publisher.publish({
|
||||
values: {
|
||||
storePath: 'blam/test',
|
||||
owner: 'bob',
|
||||
access: 'bob',
|
||||
},
|
||||
directory: '/tmp/test',
|
||||
});
|
||||
|
||||
expect(
|
||||
mockGithubClient.repos.createForAuthenticatedUser,
|
||||
).toHaveBeenCalledWith({
|
||||
name: 'test',
|
||||
});
|
||||
expect(mockGithubClient.repos.addCollaborator).toHaveBeenCalledWith({
|
||||
owner: 'blam',
|
||||
repo: 'test',
|
||||
username: 'bob',
|
||||
permission: 'admin',
|
||||
});
|
||||
});
|
||||
|
||||
describe('publish: createGitDirectory', () => {
|
||||
const values = {
|
||||
isOrg: true,
|
||||
storePath: 'blam/test',
|
||||
owner: 'lols',
|
||||
access: 'lols',
|
||||
};
|
||||
|
||||
const mockDir = '/tmp/test/dir';
|
||||
|
||||
@@ -44,6 +44,7 @@ export class GithubPublisher implements PublisherBase {
|
||||
values: RequiredTemplateValues & Record<string, JsonValue>,
|
||||
) {
|
||||
const [owner, name] = values.storePath.split('/');
|
||||
const access = values.access as string;
|
||||
|
||||
const user = await this.client.users.getByUsername({ username: owner });
|
||||
|
||||
@@ -54,6 +55,27 @@ export class GithubPublisher implements PublisherBase {
|
||||
|
||||
const { data } = await repoCreationPromise;
|
||||
|
||||
if (access.match(new RegExp(`${owner}/.+`))) {
|
||||
const [, team] = access.split('/');
|
||||
await this.client.teams.addOrUpdateRepoPermissionsInOrg({
|
||||
org: owner,
|
||||
team_slug: team,
|
||||
owner,
|
||||
repo: name,
|
||||
permission: 'admin',
|
||||
});
|
||||
} else {
|
||||
// no need to add access if it's the person who own's the personal account
|
||||
if (access !== owner) {
|
||||
await this.client.repos.addCollaborator({
|
||||
owner,
|
||||
repo: name,
|
||||
username: access,
|
||||
permission: 'admin',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return data?.clone_url;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ const useTemplate = (
|
||||
|
||||
const OWNER_REPO_SCHEMA = {
|
||||
$schema: 'http://json-schema.org/draft-07/schema#' as const,
|
||||
required: ['storePath', 'owner'],
|
||||
required: ['storePath', 'owner', 'access'],
|
||||
properties: {
|
||||
owner: {
|
||||
type: 'string' as const,
|
||||
@@ -67,6 +67,11 @@ const OWNER_REPO_SCHEMA = {
|
||||
title: 'Store path',
|
||||
description: 'GitHub store path in org/repo format',
|
||||
},
|
||||
access: {
|
||||
type: 'string' as const,
|
||||
title: 'Access',
|
||||
description: 'Who should have access, in user or owner/team format',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user