chore(scaffolder-backend-module-gitlab): Upgrade to gitbeaker ^41.2.0

Signed-off-by: mpsanchis <miguelpsanchis@gmail.com>
This commit is contained in:
mpsanchis
2024-10-24 14:32:31 +02:00
parent 50e5d95e49
commit 32459d0a57
23 changed files with 211 additions and 176 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-gitlab': minor
---
Upgraded gitbeaker to ^41.2.0
@@ -51,9 +51,7 @@
"@backstage/errors": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"@gitbeaker/core": "^35.8.0",
"@gitbeaker/node": "^35.8.0",
"@gitbeaker/rest": "^39.25.0",
"@gitbeaker/rest": "^41.2.0",
"luxon": "^3.0.0",
"winston": "^3.2.1",
"yaml": "^2.0.0",
@@ -76,11 +76,11 @@ export const createGitlabProjectDeployTokenAction: (options: {
}) => TemplateAction<
{
name: string;
scopes: string[];
repoUrl: string;
projectId: string | number;
username?: string | undefined;
token?: string | undefined;
scopes?: string[] | undefined;
},
{
user: string;
@@ -42,13 +42,13 @@ const mockGitlabClient = {
create: jest.fn(),
},
Users: {
current: jest.fn(),
showCurrentUser: jest.fn(),
},
ProjectMembers: {
add: jest.fn(),
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -86,7 +86,7 @@ describe('publish:gitlab', () => {
});
it('should call initRepoAndPush with the correct values', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -40,7 +40,7 @@ const mockGitlabClient = {
create: jest.fn(),
},
Users: {
current: jest.fn(),
showCurrentUser: jest.fn(),
},
ProjectMembers: {
add: jest.fn(),
@@ -55,7 +55,7 @@ const mockGitlabClient = {
create: jest.fn(),
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -183,7 +183,7 @@ describe('publish:gitlab', () => {
});
it('should work when there is a token provided through ctx.input', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -199,7 +199,7 @@ describe('publish:gitlab', () => {
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 1234,
namespaceId: 1234,
name: 'bob',
visibility: 'private',
});
@@ -208,7 +208,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.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -218,7 +218,7 @@ describe('publish:gitlab', () => {
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 1234,
namespaceId: 1234,
name: 'repo',
visibility: 'private',
ci_config_path: '.gitlab-ci.yml',
@@ -229,7 +229,7 @@ describe('publish:gitlab', () => {
it('should call the correct Gitlab APIs when the owner is not an organization', async () => {
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: null });
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
});
@@ -238,7 +238,7 @@ describe('publish:gitlab', () => {
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 12345,
namespaceId: 12345,
name: 'repo',
visibility: 'private',
ci_config_path: '.gitlab-ci.yml',
@@ -248,7 +248,7 @@ describe('publish:gitlab', () => {
});
it('should call the correct Gitlab APIs when using project settings with override of visibility and topics', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -258,7 +258,7 @@ describe('publish:gitlab', () => {
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 1234,
namespaceId: 1234,
name: 'repo',
visibility: 'internal',
topics: ['topic1', 'topic2'],
@@ -269,7 +269,7 @@ describe('publish:gitlab', () => {
});
it('should call the correct Gitlab APIs for branches and protectd branches when branch settings provided', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
id: 123456,
@@ -280,7 +280,7 @@ describe('publish:gitlab', () => {
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 1234,
namespaceId: 1234,
name: 'repo',
visibility: 'private',
});
@@ -309,7 +309,7 @@ describe('publish:gitlab', () => {
});
it('should call the correct Gitlab APIs for variables when their configuration is provided', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
id: 123456,
@@ -320,28 +320,28 @@ describe('publish:gitlab', () => {
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 1234,
namespaceId: 1234,
name: 'repo',
visibility: 'private',
});
expect(mockGitlabClient.ProjectVariables.create).toHaveBeenCalledWith(
123456,
'key',
'value',
{
key: 'key',
value: 'value',
description: 'description',
variable_type: 'env_var',
variableType: 'env_var',
protected: true,
masked: true,
raw: false,
environment_scope: '*',
environmentScope: '*',
},
);
});
it('should call initRepoAndPush with the correct values', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -361,7 +361,7 @@ describe('publish:gitlab', () => {
});
it('should call initRepoAndPush with the correct default branch', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -416,7 +416,7 @@ describe('publish:gitlab', () => {
config: customAuthorConfig,
});
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -462,7 +462,7 @@ describe('publish:gitlab', () => {
config: customAuthorConfig,
});
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -482,7 +482,7 @@ describe('publish:gitlab', () => {
});
it('should call output with the remoteUrl and repoContentsUrl and projectId', async () => {
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -523,7 +523,7 @@ describe('publish:gitlab', () => {
});
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Users.showCurrentUser.mockResolvedValue({ id: 12345 });
mockGitlabClient.Projects.create.mockResolvedValue({
id: 123456,
http_url_to_repo: 'http://mockurl.git',
@@ -539,14 +539,14 @@ describe('publish:gitlab', () => {
});
expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
expect(mockGitlabClient.Users.current).toHaveBeenCalled();
expect(mockGitlabClient.Users.showCurrentUser).toHaveBeenCalled();
expect(mockGitlabClient.ProjectMembers.add).toHaveBeenCalledWith(
123456,
12345,
50,
);
expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
namespace_id: 1234,
namespaceId: 1234,
name: 'repo',
visibility: 'private',
});
@@ -17,7 +17,7 @@
import { InputError } from '@backstage/errors';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import { Gitlab } from '@gitbeaker/node';
import { Gitlab, VariableType } from '@gitbeaker/rest';
import {
initRepoAndPush,
getRepoSourceDirectory,
@@ -383,7 +383,7 @@ export function createPublishGitlabAction(options: {
throw e;
}
const { id: userId } = (await client.Users.current()) as {
const { id: userId } = (await client.Users.showCurrentUser()) as {
id: number;
};
@@ -392,7 +392,7 @@ export function createPublishGitlabAction(options: {
}
const { id: projectId, http_url_to_repo } = await client.Projects.create({
namespace_id: targetNamespaceId,
namespaceId: targetNamespaceId,
name: repo,
visibility: repoVisibility,
...(topics.length ? { topics } : {}),
@@ -478,7 +478,8 @@ export function createPublishGitlabAction(options: {
if (projectVariables) {
for (const variable of projectVariables) {
const variableWithDefaults = Object.assign(variable, {
variable_type: variable.variable_type ?? 'env_var',
variable_type: (variable.variable_type ??
'env_var') as VariableType,
protected: variable.protected ?? false,
masked: variable.masked ?? false,
raw: variable.raw ?? false,
@@ -488,7 +489,16 @@ export function createPublishGitlabAction(options: {
try {
await client.ProjectVariables.create(
projectId,
variableWithDefaults,
variableWithDefaults.key,
variableWithDefaults.value,
{
variableType: variableWithDefaults.variable_type,
protected: variableWithDefaults.protected,
masked: variableWithDefaults.masked,
environmentScope: variableWithDefaults.environment_scope,
description: variableWithDefaults.description,
raw: variableWithDefaults.raw,
},
);
} catch (e) {
throw new InputError(
@@ -16,7 +16,7 @@
import { ScmIntegrationRegistry } from '@backstage/integration';
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import { GroupSchema } from '@gitbeaker/core/dist/types/resources/Groups';
import { GroupSchema } from '@gitbeaker/rest';
import { z } from 'zod';
import commonGitlabConfig from '../commonGitlabConfig';
import { getClient, parseRepoUrl } from '../util';
@@ -53,9 +53,10 @@ const mockGitlabClient = {
},
Users: {
current: jest.fn(),
username: jest.fn(async (user: string) => {
all: jest.fn(async (userOptions: { username: string }) => {
const users: string[] = ['John Smith', 'my-assignee'];
if (!users.includes(user)) throw new Error('user does not exist');
if (!users.includes(userOptions.username))
throw new Error('user does not exist');
else
return [
{
@@ -66,7 +67,7 @@ const mockGitlabClient = {
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -66,19 +66,18 @@ const mockGitlabClient = {
}),
},
Users: {
current: jest.fn(),
username: jest.fn(async (user: string) => {
if (user !== 'John Smith') throw new Error('user does not exist');
else
return [
{
id: 123,
},
];
all: jest.fn(async (userOptions: { username: string }) => {
if (userOptions.username !== 'John Smith')
throw new Error('user does not exist');
return [
{
id: 123,
},
];
}),
},
Repositories: {
tree: jest.fn(
allRepositoryTrees: jest.fn(
async (
repoID: string | number,
options: { ref: string; recursive: boolean; path: string | undefined },
@@ -123,7 +122,7 @@ const mockGitlabClient = {
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -20,7 +20,7 @@ import {
SerializedFile,
serializeDirectoryContents,
} from '@backstage/plugin-scaffolder-node';
import { Gitlab, Types } from '@gitbeaker/core';
import { Gitlab, RepositoryTreeSchema, CommitAction } from '@gitbeaker/rest';
import path from 'path';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { InputError } from '@backstage/errors';
@@ -41,9 +41,9 @@ function computeSha256(file: SerializedFile): string {
async function getFileAction(
fileInfo: { file: SerializedFile; targetPath?: string },
target: { repoID: string; branch: string },
api: Gitlab,
api: InstanceType<typeof Gitlab>,
logger: LoggerService,
remoteFiles: Types.RepositoryTreeSchema[],
remoteFiles: RepositoryTreeSchema[],
defaultCommitAction:
| 'create'
| 'delete'
@@ -231,7 +231,7 @@ which uses additional API calls in order to detect whether to 'create', 'update'
if (assignee !== undefined) {
try {
const assigneeUser = await api.Users.username(assignee);
const assigneeUser = await api.Users.all({ username: assignee });
assigneeId = assigneeUser[0].id;
} catch (e) {
ctx.logger.warn(
@@ -259,15 +259,21 @@ which uses additional API calls in order to detect whether to 'create', 'update'
let targetBranch = targetBranchName;
if (!targetBranch) {
const projects = await api.Projects.show(repoID);
const { default_branch: defaultBranch } = projects;
targetBranch = defaultBranch!;
const defaultBranch = projects.default_branch ?? projects.defaultBranch;
if (typeof defaultBranch !== 'string' || !defaultBranch) {
throw new InputError(
`The branch creation failed. Target branch was not provided, and could not find default branch from project settings. Project: ${JSON.stringify(
project,
)}`,
);
}
targetBranch = defaultBranch;
}
let remoteFiles: Types.RepositoryTreeSchema[] = [];
let remoteFiles: RepositoryTreeSchema[] = [];
if ((ctx.input.commitAction ?? 'auto') === 'auto') {
try {
remoteFiles = await api.Repositories.tree(repoID, {
remoteFiles = await api.Repositories.allRepositoryTrees(repoID, {
ref: targetBranch,
recursive: true,
path: targetPath ?? undefined,
@@ -280,7 +286,7 @@ which uses additional API calls in order to detect whether to 'create', 'update'
);
}
}
const actions: Types.CommitAction[] =
const actions: CommitAction[] =
ctx.input.commitAction === 'skip'
? []
: (
@@ -300,7 +306,7 @@ which uses additional API calls in order to detect whether to 'create', 'update'
)
).filter(o => o.action !== 'skip') as {
file: SerializedFile;
action: Types.CommitAction['action'];
action: CommitAction['action'];
}[]
).map(({ file, action }) => ({
action,
@@ -359,9 +365,7 @@ which uses additional API calls in order to detect whether to 'create', 'update'
removeSourceBranch: removeSourceBranch ? removeSourceBranch : false,
assigneeId,
},
).then((mergeRequest: { web_url: string }) => {
return mergeRequest.web_url;
});
).then(mergeRequest => mergeRequest.web_url ?? mergeRequest.webUrl);
ctx.output('projectid', repoID);
ctx.output('targetBranchName', targetBranch);
ctx.output('projectPath', repoID);
@@ -88,9 +88,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'456',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -113,9 +113,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'789',
'tokenname',
['read_registry', 'write_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -138,9 +138,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'my-custom-token',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -163,9 +163,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
42,
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -188,9 +188,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'123',
'tokenname',
['read_repository'],
'2024-06-25',
{
accessLevel: 40,
expiresAt: '2024-06-25',
},
);
@@ -213,9 +213,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'456',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 30,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -241,9 +241,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'456',
'full-access-token',
['read_repository'],
'2024-12-31',
{
accessLevel: 40,
expiresAt: '2024-12-31',
},
);
@@ -269,9 +269,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -297,9 +297,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'tokenname',
['read_repository', 'read_api'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -325,9 +325,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 10,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -353,9 +353,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -381,9 +381,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 50,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -409,9 +409,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'no-expiry-token',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -437,9 +437,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'101112',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -84,9 +84,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'987',
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -115,9 +115,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'987',
'tokenname',
['read_registry', 'write_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -146,9 +146,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'2110',
'token',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -176,9 +176,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
23,
'tokenname',
['read_repository'],
DateTime.now().plus({ days: 365 }).toISODate()!,
{
accessLevel: 40,
expiresAt: DateTime.now().plus({ days: 365 }).toISODate()!,
},
);
@@ -207,9 +207,9 @@ describe('gitlab:projectAccessToken:create examples', () => {
'123',
'tokenname',
['read_repository'],
'1999-07-14',
{
accessLevel: 40,
expiresAt: '1999-07-14',
},
);
@@ -108,9 +108,8 @@ export const createGitlabProjectAccessTokenAction = (options: {
projectId,
name,
scopes as AccessTokenScopes[],
expiresAt || DateTime.now().plus({ days: 365 }).toISODate()!,
{
expiresAt:
expiresAt || DateTime.now().plus({ days: 365 }).toISODate()!,
accessLevel,
},
);
@@ -22,11 +22,11 @@ import { createGitlabProjectDeployTokenAction } from './gitlabProjectDeployToken
import { examples } from './gitlabProjectDeployTokenCreate.examples';
const mockGitlabClient = {
ProjectDeployTokens: {
add: jest.fn(),
DeployTokens: {
create: jest.fn(),
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -68,7 +68,7 @@ describe('gitlab:create-deploy-token', () => {
});
it(`Should ${examples[0].description}`, async () => {
mockGitlabClient.ProjectDeployTokens.add.mockResolvedValue({
mockGitlabClient.DeployTokens.create.mockResolvedValue({
token: 'TOKEN',
username: 'User',
});
@@ -78,11 +78,13 @@ describe('gitlab:create-deploy-token', () => {
input: yaml.parse(examples[0].example).steps[0].input,
});
expect(mockGitlabClient.ProjectDeployTokens.add).toHaveBeenCalledWith(
'456',
expect(mockGitlabClient.DeployTokens.create).toHaveBeenCalledWith(
'tokenname',
undefined,
{ username: undefined },
['read_registry'],
{
projectId: '456',
username: undefined,
},
);
expect(mockContext.output).toHaveBeenCalledWith('deploy_token', 'TOKEN');
@@ -90,7 +92,7 @@ describe('gitlab:create-deploy-token', () => {
});
it(`Should ${examples[1].description}`, async () => {
mockGitlabClient.ProjectDeployTokens.add.mockResolvedValue({
mockGitlabClient.DeployTokens.create.mockResolvedValue({
token: 'TOKEN',
username: 'User',
});
@@ -100,11 +102,13 @@ describe('gitlab:create-deploy-token', () => {
input: yaml.parse(examples[1].example).steps[0].input,
});
expect(mockGitlabClient.ProjectDeployTokens.add).toHaveBeenCalledWith(
'789',
expect(mockGitlabClient.DeployTokens.create).toHaveBeenCalledWith(
'tokenname',
['read_registry', 'write_repository'],
{ username: undefined },
{
projectId: '789',
username: undefined,
},
);
expect(mockContext.output).toHaveBeenCalledWith('deploy_token', 'TOKEN');
@@ -112,7 +116,7 @@ describe('gitlab:create-deploy-token', () => {
});
it(`Should ${examples[2].description}`, async () => {
mockGitlabClient.ProjectDeployTokens.add.mockResolvedValue({
mockGitlabClient.DeployTokens.create.mockResolvedValue({
token: 'TOKEN',
username: 'User',
});
@@ -122,11 +126,13 @@ describe('gitlab:create-deploy-token', () => {
input: yaml.parse(examples[2].example).steps[0].input,
});
expect(mockGitlabClient.ProjectDeployTokens.add).toHaveBeenCalledWith(
'101112',
expect(mockGitlabClient.DeployTokens.create).toHaveBeenCalledWith(
'my-custom-token',
undefined,
{ username: undefined },
['read_registry'],
{
projectId: '101112',
username: undefined,
},
);
expect(mockContext.output).toHaveBeenCalledWith('deploy_token', 'TOKEN');
@@ -134,7 +140,7 @@ describe('gitlab:create-deploy-token', () => {
});
it(`Should ${examples[3].description}`, async () => {
mockGitlabClient.ProjectDeployTokens.add.mockResolvedValue({
mockGitlabClient.DeployTokens.create.mockResolvedValue({
token: 'TOKEN',
username: 'User',
});
@@ -144,11 +150,13 @@ describe('gitlab:create-deploy-token', () => {
input: yaml.parse(examples[3].example).steps[0].input,
});
expect(mockGitlabClient.ProjectDeployTokens.add).toHaveBeenCalledWith(
42,
expect(mockGitlabClient.DeployTokens.create).toHaveBeenCalledWith(
'tokenname',
undefined,
{ username: undefined },
['read_registry'],
{
projectId: 42,
username: undefined,
},
);
expect(mockContext.output).toHaveBeenCalledWith('deploy_token', 'TOKEN');
@@ -156,7 +164,7 @@ describe('gitlab:create-deploy-token', () => {
});
it(`Should ${examples[4].description}`, async () => {
mockGitlabClient.ProjectDeployTokens.add.mockResolvedValue({
mockGitlabClient.DeployTokens.create.mockResolvedValue({
token: 'TOKEN',
username: 'User',
});
@@ -166,11 +174,13 @@ describe('gitlab:create-deploy-token', () => {
input: yaml.parse(examples[4].example).steps[0].input,
});
expect(mockGitlabClient.ProjectDeployTokens.add).toHaveBeenCalledWith(
42,
expect(mockGitlabClient.DeployTokens.create).toHaveBeenCalledWith(
'tokenname',
undefined,
{ username: 'tokenuser' },
['read_registry'],
{
projectId: 42,
username: 'tokenuser',
},
);
expect(mockContext.output).toHaveBeenCalledWith('deploy_token', 'TOKEN');
@@ -29,13 +29,15 @@ export const examples: TemplateExample[] = [
repoUrl: 'gitlab.com?repo=repo&owner=owner',
projectId: '456',
name: 'tokenname',
scopes: ['read_registry'],
},
},
],
}),
},
{
description: 'Create a GitLab project deploy token with custom scopes.',
description:
'Create a GitLab project deploy token with many custom scopes.',
example: yaml.stringify({
steps: [
{
@@ -64,6 +66,7 @@ export const examples: TemplateExample[] = [
repoUrl: 'gitlab.com?repo=repo&owner=owner',
projectId: '101112',
name: 'my-custom-token',
scopes: ['read_registry'],
},
},
],
@@ -82,6 +85,7 @@ export const examples: TemplateExample[] = [
repoUrl: 'gitlab.com?repo=repo&owner=owner',
projectId: 42,
name: 'tokenname',
scopes: ['read_registry'],
},
},
],
@@ -101,6 +105,7 @@ export const examples: TemplateExample[] = [
projectId: 42,
name: 'tokenname',
username: 'tokenuser',
scopes: ['read_registry'],
},
},
],
@@ -20,11 +20,11 @@ import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-
import { createGitlabProjectDeployTokenAction } from './gitlabProjectDeployTokenCreate';
const mockGitlabClient = {
ProjectDeployTokens: {
add: jest.fn(),
DeployTokens: {
create: jest.fn(),
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -66,7 +66,7 @@ describe('gitlab:create-deploy-token', () => {
});
it('should work when there is a token provided through ctx.input', async () => {
mockGitlabClient.ProjectDeployTokens.add.mockResolvedValue({
mockGitlabClient.DeployTokens.create.mockResolvedValue({
token: 'TOKEN',
username: 'User',
});
@@ -82,11 +82,13 @@ describe('gitlab:create-deploy-token', () => {
},
});
expect(mockGitlabClient.ProjectDeployTokens.add).toHaveBeenCalledWith(
'123',
expect(mockGitlabClient.DeployTokens.create).toHaveBeenCalledWith(
'tokenname',
['read_repository'],
{ username: 'tokenuser' },
{
projectId: '123',
username: 'tokenuser',
},
);
expect(mockContext.output).toHaveBeenCalledWith('deploy_token', 'TOKEN');
@@ -17,8 +17,7 @@
import { InputError } from '@backstage/errors';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import { DeployTokenScope } from '@gitbeaker/core/dist/types/templates/ResourceDeployTokens';
import { Gitlab } from '@gitbeaker/node';
import { DeployTokenScope, Gitlab } from '@gitbeaker/rest';
import { z } from 'zod';
import commonGitlabConfig from '../commonGitlabConfig';
import { getToken } from '../util';
@@ -47,7 +46,7 @@ export const createGitlabProjectDeployTokenAction = (options: {
username: z
.string({ description: 'Deploy Token Username' })
.optional(),
scopes: z.array(z.string(), { description: 'Scopes' }).optional(),
scopes: z.array(z.string(), { description: 'Scopes' }),
}),
),
output: z.object({
@@ -60,17 +59,23 @@ export const createGitlabProjectDeployTokenAction = (options: {
const { projectId, name, username, scopes } = ctx.input;
const { token, integrationConfig } = getToken(ctx.input, integrations);
if (scopes.length === 0) {
throw new InputError(
`Could not create token for project "${ctx.input.projectId}": scopes cannot be empty.`,
);
}
const api = new Gitlab({
host: integrationConfig.config.baseUrl,
token: token,
});
const deployToken = await api.ProjectDeployTokens.add(
projectId,
const deployToken = await api.DeployTokens.create(
name,
scopes as DeployTokenScope[],
{
username: username,
projectId,
username,
},
);
@@ -45,7 +45,7 @@ const mockGitlabClient = {
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -44,7 +44,7 @@ const mockGitlabClient = {
},
};
jest.mock('@gitbeaker/node', () => ({
jest.mock('@gitbeaker/rest', () => ({
Gitlab: class {
constructor() {
return mockGitlabClient;
@@ -19,7 +19,7 @@ import {
parseRepoUrl,
serializeDirectoryContents,
} from '@backstage/plugin-scaffolder-node';
import { Types } from '@gitbeaker/core';
import { CommitAction } from '@gitbeaker/rest';
import path from 'path';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { InputError } from '@backstage/errors';
@@ -141,7 +141,7 @@ export const createGitlabRepoPushAction = (options: {
gitignore: true,
});
const actions: Types.CommitAction[] = fileContents.map(file => ({
const actions: CommitAction[] = fileContents.map(file => ({
action: commitAction ?? 'create',
filePath: targetPath
? path.posix.join(targetPath, file.path)
@@ -15,15 +15,14 @@
*/
import { parseRepoUrl } from '@backstage/plugin-scaffolder-node';
import { ErrorLike, InputError, isError } from '@backstage/errors';
import { Gitlab } from '@gitbeaker/node';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { Resources } from '@gitbeaker/core';
import { Gitlab } from '@gitbeaker/rest';
export function createGitlabApi(options: {
integrations: ScmIntegrationRegistry;
token?: string;
repoUrl: string;
}): Resources.Gitlab {
}): InstanceType<typeof Gitlab> {
const { integrations, token: providedToken, repoUrl } = options;
const { host } = parseRepoUrl(repoUrl, integrations);
@@ -62,7 +62,7 @@ describe('getTopLevelParentGroup', () => {
parent_id: 0,
path: '',
description: '',
visibility: '',
visibility: 'public',
share_with_group_lock: false,
require_two_factor_authentication: false,
two_factor_grace_period: 0,
@@ -83,7 +83,7 @@ describe('getTopLevelParentGroup', () => {
parent_id: 789,
path: '',
description: '',
visibility: '',
visibility: 'public',
share_with_group_lock: false,
require_two_factor_authentication: false,
two_factor_grace_period: 0,
@@ -104,7 +104,7 @@ describe('getTopLevelParentGroup', () => {
parent_id: 456,
path: '',
description: '',
visibility: '',
visibility: 'public',
share_with_group_lock: false,
require_two_factor_authentication: false,
two_factor_grace_period: 0,
@@ -128,7 +128,7 @@ describe('getTopLevelParentGroup', () => {
parent_id: 0,
path: '',
description: '',
visibility: '',
visibility: 'public',
share_with_group_lock: false,
require_two_factor_authentication: false,
two_factor_grace_period: 0,
+34 -36
View File
@@ -7526,9 +7526,7 @@ __metadata:
"@backstage/integration": "workspace:^"
"@backstage/plugin-scaffolder-node": "workspace:^"
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^"
"@gitbeaker/core": ^35.8.0
"@gitbeaker/node": ^35.8.0
"@gitbeaker/rest": ^39.25.0
"@gitbeaker/rest": ^41.2.0
luxon: ^3.0.0
winston: ^3.2.1
yaml: ^2.0.0
@@ -9905,7 +9903,7 @@ __metadata:
languageName: node
linkType: hard
"@gitbeaker/core@npm:^35.8.0, @gitbeaker/core@npm:^35.8.1":
"@gitbeaker/core@npm:^35.8.1":
version: 35.8.1
resolution: "@gitbeaker/core@npm:35.8.1"
dependencies:
@@ -9919,17 +9917,6 @@ __metadata:
languageName: node
linkType: hard
"@gitbeaker/core@npm:^39.34.3":
version: 39.34.3
resolution: "@gitbeaker/core@npm:39.34.3"
dependencies:
"@gitbeaker/requester-utils": ^39.34.3
qs: ^6.11.2
xcase: ^2.0.1
checksum: 2b0ccd6137ee717b6f51c51c8f7063b84beeebfdb044574f2257f282864411c4f0932f2619893385f2a86bb4fa342b75be972fd1868640ab4e260f2280cc52b3
languageName: node
linkType: hard
"@gitbeaker/core@npm:^40.6.0":
version: 40.6.0
resolution: "@gitbeaker/core@npm:40.6.0"
@@ -9941,7 +9928,18 @@ __metadata:
languageName: node
linkType: hard
"@gitbeaker/node@npm:^35.1.0, @gitbeaker/node@npm:^35.8.0":
"@gitbeaker/core@npm:^41.2.0":
version: 41.2.0
resolution: "@gitbeaker/core@npm:41.2.0"
dependencies:
"@gitbeaker/requester-utils": ^41.2.0
qs: ^6.12.2
xcase: ^2.0.1
checksum: a702542061f2881ff5b931bdf713a89429b2d6420e2ed153e8365a93e8584f623ef2af0b3525fed719f3ee6835c8b33d546a34e776527a1777883be32d1ecb43
languageName: node
linkType: hard
"@gitbeaker/node@npm:^35.1.0":
version: 35.8.1
resolution: "@gitbeaker/node@npm:35.8.1"
dependencies:
@@ -9965,18 +9963,6 @@ __metadata:
languageName: node
linkType: hard
"@gitbeaker/requester-utils@npm:^39.34.3":
version: 39.34.3
resolution: "@gitbeaker/requester-utils@npm:39.34.3"
dependencies:
picomatch-browser: ^2.2.6
qs: ^6.11.2
rate-limiter-flexible: ^4.0.0
xcase: ^2.0.1
checksum: 55881864f42e243d9cd73840ea44c9eee13be7974fa13fde241f19bc47915712532d5f7339a598cdd258c32193a37375719984d2630620ab8d962d6d7724cbeb
languageName: node
linkType: hard
"@gitbeaker/requester-utils@npm:^40.6.0":
version: 40.6.0
resolution: "@gitbeaker/requester-utils@npm:40.6.0"
@@ -9989,13 +9975,15 @@ __metadata:
languageName: node
linkType: hard
"@gitbeaker/rest@npm:^39.25.0":
version: 39.34.3
resolution: "@gitbeaker/rest@npm:39.34.3"
"@gitbeaker/requester-utils@npm:^41.2.0":
version: 41.2.0
resolution: "@gitbeaker/requester-utils@npm:41.2.0"
dependencies:
"@gitbeaker/core": ^39.34.3
"@gitbeaker/requester-utils": ^39.34.3
checksum: e2a484891b12c71d4218168ab3884af14d036fb16a710ea023556a3d57dd220b13feaebd1f4aa3f61d0180c9f17b66f283650cd543416bb402d3bed8b6eaa465
picomatch-browser: ^2.2.6
qs: ^6.12.2
rate-limiter-flexible: ^4.0.1
xcase: ^2.0.1
checksum: a50eb054d656b8f1940557919fa1abe06ca3a05b21b59297dcdc976ffcd539654f4349094a878b00749b70c75bd5e3fecc1997acc8d82e98b938a08936ae23f0
languageName: node
linkType: hard
@@ -10009,6 +9997,16 @@ __metadata:
languageName: node
linkType: hard
"@gitbeaker/rest@npm:^41.2.0":
version: 41.2.0
resolution: "@gitbeaker/rest@npm:41.2.0"
dependencies:
"@gitbeaker/core": ^41.2.0
"@gitbeaker/requester-utils": ^41.2.0
checksum: f2c39daa758f82a154ba1af8d946712909daca85b42304ccca7880f2dbd7b8c9efdf5d3ca69bd902f95717aa0cde19417bceef6197495b8f5e897fe79a32ded3
languageName: node
linkType: hard
"@google-cloud/container@npm:^5.0.0":
version: 5.19.0
resolution: "@google-cloud/container@npm:5.19.0"
@@ -38643,7 +38641,7 @@ __metadata:
languageName: node
linkType: hard
"qs@npm:6.13.0, qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.11.2, qs@npm:^6.12.2, qs@npm:^6.9.4":
"qs@npm:6.13.0, qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.12.2, qs@npm:^6.9.4":
version: 6.13.0
resolution: "qs@npm:6.13.0"
dependencies:
@@ -38830,7 +38828,7 @@ __metadata:
languageName: node
linkType: hard
"rate-limiter-flexible@npm:^4.0.0, rate-limiter-flexible@npm:^4.0.1":
"rate-limiter-flexible@npm:^4.0.1":
version: 4.0.1
resolution: "rate-limiter-flexible@npm:4.0.1"
checksum: 88cb4ae4c6a94646eb4987f08ae203896fc340d84038e145958607ab711d9c703e47e55f177a4bf9bab4c637c73ee2254fffe2ec4e289d41389c8502194ca868