scaffolder: Add support for granting access on create

This commit is contained in:
Tim Jacomb
2020-09-12 21:27:26 +01:00
parent 0597211af1
commit fdef955570
4 changed files with 80 additions and 2 deletions
@@ -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',
},
},
};