Merge pull request #12362 from matteosilv/master
Adding a new setUserAsOwner flag to publish:gitlab action.
This commit is contained in:
@@ -388,6 +388,7 @@ export function createPublishGitlabAction(options: {
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
setUserAsOwner?: boolean | undefined;
|
||||
}>;
|
||||
|
||||
// @public
|
||||
|
||||
@@ -32,6 +32,9 @@ const mockGitlabClient = {
|
||||
Users: {
|
||||
current: jest.fn(),
|
||||
},
|
||||
ProjectMembers: {
|
||||
add: jest.fn(),
|
||||
},
|
||||
};
|
||||
jest.mock('@gitbeaker/node', () => ({
|
||||
Gitlab: class {
|
||||
@@ -113,6 +116,7 @@ describe('publish:gitlab', () => {
|
||||
});
|
||||
|
||||
it('should work when there is a token provided through ctx.input', async () => {
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
@@ -135,6 +139,7 @@ describe('publish:gitlab', () => {
|
||||
});
|
||||
|
||||
it('should call the correct Gitlab APIs when the owner is an organization', async () => {
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
@@ -168,6 +173,7 @@ describe('publish:gitlab', () => {
|
||||
});
|
||||
|
||||
it('should call initRepoAndPush with the correct values', async () => {
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
@@ -187,6 +193,7 @@ describe('publish:gitlab', () => {
|
||||
});
|
||||
|
||||
it('should call initRepoAndPush with the correct default branch', async () => {
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
@@ -241,6 +248,7 @@ describe('publish:gitlab', () => {
|
||||
config: customAuthorConfig,
|
||||
});
|
||||
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
@@ -286,6 +294,7 @@ describe('publish:gitlab', () => {
|
||||
config: customAuthorConfig,
|
||||
});
|
||||
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
@@ -305,6 +314,7 @@ describe('publish:gitlab', () => {
|
||||
});
|
||||
|
||||
it('should call output with the remoteUrl and repoContentsUrl', async () => {
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
@@ -321,4 +331,54 @@ describe('publish:gitlab', () => {
|
||||
'http://mockurl/-/blob/master',
|
||||
);
|
||||
});
|
||||
|
||||
it('should call the correct Gitlab APIs when setUserAsOwner option is true and integration config has a token', async () => {
|
||||
const customAuthorConfig = new ConfigReader({
|
||||
integrations: {
|
||||
gitlab: [
|
||||
{
|
||||
host: 'gitlab.com',
|
||||
token: 'tokenlols',
|
||||
apiBaseUrl: 'https://api.gitlab.com',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const customAuthorIntegrations =
|
||||
ScmIntegrations.fromConfig(customAuthorConfig);
|
||||
const customAuthorAction = createPublishGitlabAction({
|
||||
integrations: customAuthorIntegrations,
|
||||
config: customAuthorConfig,
|
||||
});
|
||||
|
||||
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
|
||||
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
|
||||
mockGitlabClient.Projects.create.mockResolvedValue({
|
||||
id: 123456,
|
||||
http_url_to_repo: 'http://mockurl.git',
|
||||
});
|
||||
|
||||
await customAuthorAction.handler({
|
||||
...mockContext,
|
||||
input: {
|
||||
repoUrl: 'gitlab.com?repo=repo&owner=owner',
|
||||
token: 'token',
|
||||
setUserAsOwner: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
|
||||
expect(mockGitlabClient.Users.current).toHaveBeenCalled();
|
||||
expect(mockGitlabClient.ProjectMembers.add).toHaveBeenCalledWith(
|
||||
123456,
|
||||
12345,
|
||||
50,
|
||||
);
|
||||
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
|
||||
namespace_id: 1234,
|
||||
name: 'repo',
|
||||
visibility: 'private',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,6 +43,7 @@ export function createPublishGitlabAction(options: {
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
setUserAsOwner?: boolean;
|
||||
}>({
|
||||
id: 'publish:gitlab',
|
||||
description:
|
||||
@@ -92,6 +93,12 @@ export function createPublishGitlabAction(options: {
|
||||
type: 'string',
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
},
|
||||
setUserAsOwner: {
|
||||
title: 'Set User As Owner',
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Set the token user as owner of the newly created repository. Requires a token authorized to do the edit in the integration configuration for the matching host',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -116,6 +123,7 @@ export function createPublishGitlabAction(options: {
|
||||
gitCommitMessage = 'initial commit',
|
||||
gitAuthorName,
|
||||
gitAuthorEmail,
|
||||
setUserAsOwner = false,
|
||||
} = ctx.input;
|
||||
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
||||
|
||||
@@ -149,19 +157,35 @@ export function createPublishGitlabAction(options: {
|
||||
id: number;
|
||||
};
|
||||
|
||||
const { id: userId } = (await client.Users.current()) as {
|
||||
id: number;
|
||||
};
|
||||
|
||||
if (!targetNamespace) {
|
||||
const { id } = (await client.Users.current()) as {
|
||||
id: number;
|
||||
};
|
||||
targetNamespace = id;
|
||||
targetNamespace = userId;
|
||||
}
|
||||
|
||||
const { http_url_to_repo } = await client.Projects.create({
|
||||
const { id: projectId, http_url_to_repo } = await client.Projects.create({
|
||||
namespace_id: targetNamespace,
|
||||
name: repo,
|
||||
visibility: repoVisibility,
|
||||
});
|
||||
|
||||
// When setUserAsOwner is true the input token is expected to come from an unprivileged user GitLab
|
||||
// OAuth flow. In this case GitLab works in a way that allows the unprivileged user to
|
||||
// create the repository, but not to push the default protected branch (e.g. master).
|
||||
// In order to set the user as owner of the newly created repository we need to check that the
|
||||
// GitLab integration configuration for the matching host contains a token and use
|
||||
// such token to bootstrap a new privileged client.
|
||||
if (setUserAsOwner && integrationConfig.config.token) {
|
||||
const adminClient = new Gitlab({
|
||||
host: integrationConfig.config.baseUrl,
|
||||
token: integrationConfig.config.token,
|
||||
});
|
||||
|
||||
await adminClient.ProjectMembers.add(projectId, userId, 50);
|
||||
}
|
||||
|
||||
const remoteUrl = (http_url_to_repo as string).replace(/\.git$/, '');
|
||||
const repoContentsUrl = `${remoteUrl}/-/blob/${defaultBranch}`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user