chore: migrating to new actions format
Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
|
||||
---
|
||||
|
||||
Migrate to new action format
|
||||
@@ -5,7 +5,6 @@
|
||||
```ts
|
||||
import { BackendFeature } from '@backstage/backend-plugin-api';
|
||||
import { Config } from '@backstage/config';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
|
||||
@@ -14,6 +13,7 @@ export const createGitlabGroupEnsureExistsAction: (options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
}) => TemplateAction<
|
||||
{
|
||||
repoUrl: string;
|
||||
path: (
|
||||
| string
|
||||
| {
|
||||
@@ -21,13 +21,12 @@ export const createGitlabGroupEnsureExistsAction: (options: {
|
||||
slug: string;
|
||||
}
|
||||
)[];
|
||||
repoUrl: string;
|
||||
token?: string | undefined;
|
||||
},
|
||||
{
|
||||
groupId?: number | undefined;
|
||||
},
|
||||
'v1'
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -35,29 +34,29 @@ export const createGitlabIssueAction: (options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
}) => TemplateAction<
|
||||
{
|
||||
title: string;
|
||||
repoUrl: string;
|
||||
projectId: number;
|
||||
labels?: string | undefined;
|
||||
description?: string | undefined;
|
||||
weight?: number | undefined;
|
||||
title: string;
|
||||
token?: string | undefined;
|
||||
assignees?: number[] | undefined;
|
||||
createdAt?: string | undefined;
|
||||
confidential?: boolean | undefined;
|
||||
milestoneId?: number | undefined;
|
||||
epicId?: number | undefined;
|
||||
description?: string | undefined;
|
||||
createdAt?: string | undefined;
|
||||
dueDate?: string | undefined;
|
||||
discussionToResolve?: string | undefined;
|
||||
epicId?: number | undefined;
|
||||
labels?: string | undefined;
|
||||
issueType?: IssueType | undefined;
|
||||
mergeRequestToResolveDiscussionsOf?: number | undefined;
|
||||
milestoneId?: number | undefined;
|
||||
weight?: number | undefined;
|
||||
},
|
||||
{
|
||||
issueUrl: string;
|
||||
issueId: number;
|
||||
issueIid: number;
|
||||
},
|
||||
'v1'
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -65,18 +64,18 @@ export const createGitlabProjectAccessTokenAction: (options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
}) => TemplateAction<
|
||||
{
|
||||
repoUrl: string;
|
||||
projectId: string | number;
|
||||
name?: string | undefined;
|
||||
repoUrl: string;
|
||||
token?: string | undefined;
|
||||
name?: string | undefined;
|
||||
accessLevel?: number | undefined;
|
||||
scopes?: string[] | undefined;
|
||||
expiresAt?: string | undefined;
|
||||
accessLevel?: number | undefined;
|
||||
},
|
||||
{
|
||||
access_token: string;
|
||||
},
|
||||
'v1'
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -84,18 +83,18 @@ export const createGitlabProjectDeployTokenAction: (options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
}) => TemplateAction<
|
||||
{
|
||||
name: string;
|
||||
scopes: string[];
|
||||
repoUrl: string;
|
||||
projectId: string | number;
|
||||
username?: string | undefined;
|
||||
name: string;
|
||||
scopes: string[];
|
||||
token?: string | undefined;
|
||||
username?: string | undefined;
|
||||
},
|
||||
{
|
||||
user: string;
|
||||
deploy_token: string;
|
||||
user: string;
|
||||
},
|
||||
'v1'
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -103,19 +102,21 @@ export const createGitlabProjectVariableAction: (options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
}) => TemplateAction<
|
||||
{
|
||||
key: string;
|
||||
value: string;
|
||||
repoUrl: string;
|
||||
projectId: string | number;
|
||||
key: string;
|
||||
value: string;
|
||||
variableType: string;
|
||||
raw?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
masked?: boolean | undefined;
|
||||
environmentScope?: string | undefined;
|
||||
variableProtected?: boolean | undefined;
|
||||
masked?: boolean | undefined;
|
||||
raw?: boolean | undefined;
|
||||
environmentScope?: string | undefined;
|
||||
},
|
||||
any,
|
||||
'v1'
|
||||
{
|
||||
[x: string]: any;
|
||||
},
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -126,13 +127,17 @@ export const createGitlabRepoPushAction: (options: {
|
||||
repoUrl: string;
|
||||
branchName: string;
|
||||
commitMessage: string;
|
||||
sourcePath?: string;
|
||||
targetPath?: string;
|
||||
token?: string;
|
||||
commitAction?: 'create' | 'delete' | 'update';
|
||||
sourcePath?: string | undefined;
|
||||
targetPath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
commitAction?: 'update' | 'delete' | 'create' | undefined;
|
||||
},
|
||||
JsonObject,
|
||||
'v1'
|
||||
{
|
||||
projectid: string;
|
||||
projectPath: string;
|
||||
commitHash: string;
|
||||
},
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -142,49 +147,68 @@ export function createPublishGitlabAction(options: {
|
||||
}): TemplateAction<
|
||||
{
|
||||
repoUrl: string;
|
||||
defaultBranch?: string;
|
||||
repoVisibility?: 'private' | 'internal' | 'public';
|
||||
sourcePath?: string | boolean;
|
||||
skipExisting?: boolean;
|
||||
token?: string;
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
setUserAsOwner?: boolean;
|
||||
topics?: string[];
|
||||
settings?: {
|
||||
path?: string;
|
||||
auto_devops_enabled?: boolean;
|
||||
ci_config_path?: string;
|
||||
description?: string;
|
||||
merge_method?: 'merge' | 'rebase_merge' | 'ff';
|
||||
squash_option?: 'default_off' | 'default_on' | 'never' | 'always';
|
||||
topics?: string[];
|
||||
visibility?: 'private' | 'internal' | 'public';
|
||||
only_allow_merge_if_all_discussions_are_resolved?: boolean;
|
||||
only_allow_merge_if_pipeline_succeeds?: boolean;
|
||||
allow_merge_on_skipped_pipeline?: boolean;
|
||||
};
|
||||
branches?: Array<{
|
||||
name: string;
|
||||
protect?: boolean;
|
||||
create?: boolean;
|
||||
ref?: string;
|
||||
}>;
|
||||
projectVariables?: Array<{
|
||||
key: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
variable_type?: string;
|
||||
protected?: boolean;
|
||||
masked?: boolean;
|
||||
raw?: boolean;
|
||||
environment_scope?: string;
|
||||
}>;
|
||||
repoVisibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
signCommit?: boolean | undefined;
|
||||
sourcePath?: string | boolean | undefined;
|
||||
skipExisting?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
setUserAsOwner?: boolean | undefined;
|
||||
topics?: string[] | undefined;
|
||||
settings?:
|
||||
| {
|
||||
visibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
path?: string | undefined;
|
||||
description?: string | undefined;
|
||||
merge_method?: 'merge' | 'rebase_merge' | 'ff' | undefined;
|
||||
topics?: string[] | undefined;
|
||||
auto_devops_enabled?: boolean | undefined;
|
||||
only_allow_merge_if_pipeline_succeeds?: boolean | undefined;
|
||||
allow_merge_on_skipped_pipeline?: boolean | undefined;
|
||||
only_allow_merge_if_all_discussions_are_resolved?:
|
||||
| boolean
|
||||
| undefined;
|
||||
squash_option?:
|
||||
| 'always'
|
||||
| 'never'
|
||||
| 'default_on'
|
||||
| 'default_off'
|
||||
| undefined;
|
||||
ci_config_path?: string | undefined;
|
||||
}
|
||||
| undefined;
|
||||
branches?:
|
||||
| {
|
||||
name: string;
|
||||
ref?: string | undefined;
|
||||
create?: boolean | undefined;
|
||||
protect?: boolean | undefined;
|
||||
}[]
|
||||
| undefined;
|
||||
projectVariables?:
|
||||
| {
|
||||
key: string;
|
||||
value: string;
|
||||
raw?: boolean | undefined;
|
||||
description?: string | undefined;
|
||||
protected?: boolean | undefined;
|
||||
variable_type?: 'file' | 'env_var' | undefined;
|
||||
masked?: boolean | undefined;
|
||||
environment_scope?: string | undefined;
|
||||
}[]
|
||||
| undefined;
|
||||
},
|
||||
JsonObject,
|
||||
'v1'
|
||||
{
|
||||
remoteUrl: string;
|
||||
repoContentsUrl: string;
|
||||
projectId: number;
|
||||
commitHash: string;
|
||||
created: boolean;
|
||||
},
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -222,17 +246,17 @@ export const createTriggerGitlabPipelineAction: (options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
}) => TemplateAction<
|
||||
{
|
||||
branch: string;
|
||||
repoUrl: string;
|
||||
projectId: number;
|
||||
tokenDescription: string;
|
||||
branch: string;
|
||||
token?: string | undefined;
|
||||
variables?: Record<string, string> | undefined;
|
||||
},
|
||||
{
|
||||
pipelineUrl: string;
|
||||
},
|
||||
'v1'
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
@@ -243,33 +267,33 @@ export const editGitlabIssueAction: (options: {
|
||||
repoUrl: string;
|
||||
projectId: number;
|
||||
issueIid: number;
|
||||
title?: string | undefined;
|
||||
labels?: string | undefined;
|
||||
description?: string | undefined;
|
||||
weight?: number | undefined;
|
||||
token?: string | undefined;
|
||||
assignees?: number[] | undefined;
|
||||
addLabels?: string | undefined;
|
||||
assignees?: number[] | undefined;
|
||||
confidential?: boolean | undefined;
|
||||
description?: string | undefined;
|
||||
discussionLocked?: boolean | undefined;
|
||||
dueDate?: string | undefined;
|
||||
epicId?: number | undefined;
|
||||
issueType?: IssueType | undefined;
|
||||
labels?: string | undefined;
|
||||
milestoneId?: number | undefined;
|
||||
removeLabels?: string | undefined;
|
||||
stateEvent?: IssueStateEvent | undefined;
|
||||
discussionLocked?: boolean | undefined;
|
||||
epicId?: number | undefined;
|
||||
dueDate?: string | undefined;
|
||||
title?: string | undefined;
|
||||
updatedAt?: string | undefined;
|
||||
issueType?: IssueType | undefined;
|
||||
weight?: number | undefined;
|
||||
},
|
||||
{
|
||||
state: string;
|
||||
title: string;
|
||||
projectId: number;
|
||||
updatedAt: string;
|
||||
issueUrl: string;
|
||||
projectId: number;
|
||||
issueId: number;
|
||||
issueIid: number;
|
||||
state: string;
|
||||
title: string;
|
||||
updatedAt: string;
|
||||
},
|
||||
'v1'
|
||||
'v2'
|
||||
>;
|
||||
|
||||
// @public
|
||||
|
||||
@@ -38,307 +38,201 @@ export function createPublishGitlabAction(options: {
|
||||
}) {
|
||||
const { integrations, config } = options;
|
||||
|
||||
return createTemplateAction<{
|
||||
repoUrl: string;
|
||||
defaultBranch?: string;
|
||||
/** @deprecated in favour of settings.visibility field */
|
||||
repoVisibility?: 'private' | 'internal' | 'public';
|
||||
sourcePath?: string | boolean;
|
||||
skipExisting?: boolean;
|
||||
token?: string;
|
||||
gitCommitMessage?: string;
|
||||
gitAuthorName?: string;
|
||||
gitAuthorEmail?: string;
|
||||
signCommit?: boolean;
|
||||
setUserAsOwner?: boolean;
|
||||
/** @deprecated in favour of settings.topics field */
|
||||
topics?: string[];
|
||||
settings?: {
|
||||
path?: string;
|
||||
auto_devops_enabled?: boolean;
|
||||
ci_config_path?: string;
|
||||
description?: string;
|
||||
merge_method?: 'merge' | 'rebase_merge' | 'ff';
|
||||
squash_option?: 'default_off' | 'default_on' | 'never' | 'always';
|
||||
topics?: string[];
|
||||
visibility?: 'private' | 'internal' | 'public';
|
||||
only_allow_merge_if_all_discussions_are_resolved?: boolean;
|
||||
only_allow_merge_if_pipeline_succeeds?: boolean;
|
||||
allow_merge_on_skipped_pipeline?: boolean;
|
||||
};
|
||||
branches?: Array<{
|
||||
name: string;
|
||||
protect?: boolean;
|
||||
create?: boolean;
|
||||
ref?: string;
|
||||
}>;
|
||||
projectVariables?: Array<{
|
||||
key: string;
|
||||
value: string;
|
||||
description?: string;
|
||||
variable_type?: string;
|
||||
protected?: boolean;
|
||||
masked?: boolean;
|
||||
raw?: boolean;
|
||||
environment_scope?: string;
|
||||
}>;
|
||||
}>({
|
||||
return createTemplateAction({
|
||||
id: 'publish:gitlab',
|
||||
description:
|
||||
'Initializes a git repository of the content in the workspace, and publishes it to GitLab.',
|
||||
examples,
|
||||
schema: {
|
||||
input: {
|
||||
type: 'object',
|
||||
required: ['repoUrl'],
|
||||
properties: {
|
||||
repoUrl: {
|
||||
title: 'Repository Location',
|
||||
type: 'string',
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
},
|
||||
repoVisibility: {
|
||||
title: 'Repository Visibility',
|
||||
description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings.visibility instead)`,
|
||||
type: 'string',
|
||||
enum: ['private', 'public', 'internal'],
|
||||
},
|
||||
defaultBranch: {
|
||||
title: 'Default Branch',
|
||||
type: 'string',
|
||||
description: `Sets the default branch on the repository. The default value is 'master'`,
|
||||
},
|
||||
gitCommitMessage: {
|
||||
title: 'Git Commit Message',
|
||||
type: 'string',
|
||||
description: `Sets the commit message on the repository. The default value is 'initial commit'`,
|
||||
},
|
||||
gitAuthorName: {
|
||||
title: 'Default Author Name',
|
||||
type: 'string',
|
||||
description: `Sets the default author name for the commit. The default value is 'Scaffolder'`,
|
||||
},
|
||||
gitAuthorEmail: {
|
||||
title: 'Default Author Email',
|
||||
type: 'string',
|
||||
description: `Sets the default author email for the commit.`,
|
||||
},
|
||||
signCommit: {
|
||||
title: 'Sign commit',
|
||||
type: 'boolean',
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
},
|
||||
sourcePath: {
|
||||
title: 'Source Path',
|
||||
description:
|
||||
'Path within the workspace that will be used as the repository root. If omitted or set to true, the entire workspace will be published as the repository. If set to false, the created repository will be empty.',
|
||||
type: ['string', 'boolean'],
|
||||
},
|
||||
skipExisting: {
|
||||
title: 'Skip if repository exists',
|
||||
description:
|
||||
'Do not publish the repository if it already exists. The default value is false.',
|
||||
type: ['boolean'],
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
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',
|
||||
},
|
||||
topics: {
|
||||
title: 'Topic labels',
|
||||
description:
|
||||
'Topic labels to apply on the repository. (deprecated, use settings.topics instead)',
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
title: 'Project settings',
|
||||
description:
|
||||
'Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes',
|
||||
type: 'object',
|
||||
properties: {
|
||||
path: {
|
||||
title: 'Project path',
|
||||
description:
|
||||
'Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes).',
|
||||
type: 'string',
|
||||
},
|
||||
auto_devops_enabled: {
|
||||
title: 'Auto DevOps enabled',
|
||||
description: 'Enable Auto DevOps for this project',
|
||||
type: 'boolean',
|
||||
},
|
||||
ci_config_path: {
|
||||
title: 'CI config path',
|
||||
description: 'Custom CI config path for this project',
|
||||
type: 'string',
|
||||
},
|
||||
description: {
|
||||
title: 'Project description',
|
||||
description: 'Short project description',
|
||||
type: 'string',
|
||||
},
|
||||
merge_method: {
|
||||
title: 'Merge Method to use',
|
||||
description: 'Merge Methods (merge, rebase_merge, ff)',
|
||||
type: 'string',
|
||||
enum: ['merge', 'rebase_merge', 'ff'],
|
||||
},
|
||||
squash_option: {
|
||||
title: 'Squash option',
|
||||
description:
|
||||
'Set squash option for the project (never, always, default_on, default_off)',
|
||||
type: 'string',
|
||||
enum: ['default_off', 'default_on', 'never', 'always'],
|
||||
},
|
||||
topics: {
|
||||
title: 'Topic labels',
|
||||
description: 'Topic labels to apply on the repository',
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
visibility: {
|
||||
title: 'Project visibility',
|
||||
description:
|
||||
'The visibility of the project. Can be private, internal, or public. The default value is private.',
|
||||
type: 'string',
|
||||
enum: ['private', 'public', 'internal'],
|
||||
},
|
||||
only_allow_merge_if_all_discussions_are_resolved: {
|
||||
title: 'All threads must be resolved',
|
||||
description:
|
||||
'Set whether merge requests can only be merged when all the discussions are resolved.',
|
||||
type: 'boolean',
|
||||
},
|
||||
only_allow_merge_if_pipeline_succeeds: {
|
||||
title: 'Pipelines must succeed',
|
||||
description:
|
||||
'Set whether merge requests can only be merged with successful pipelines. This setting is named Pipelines must succeed in the project settings.',
|
||||
type: 'boolean',
|
||||
},
|
||||
allow_merge_on_skipped_pipeline: {
|
||||
title: 'Skipped pipelines are considered successful',
|
||||
description:
|
||||
'Set whether or not merge requests can be merged with skipped jobs.',
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
},
|
||||
branches: {
|
||||
title: 'Project branches settings',
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['name'],
|
||||
properties: {
|
||||
name: {
|
||||
title: 'Branch name',
|
||||
type: 'string',
|
||||
},
|
||||
protect: {
|
||||
title: 'Should branch be protected',
|
||||
description: `Will mark branch as protected. The default value is 'false'`,
|
||||
type: 'boolean',
|
||||
},
|
||||
create: {
|
||||
title: 'Should branch be created',
|
||||
description: `If branch does not exist, it will be created from provided ref. The default value is 'false'`,
|
||||
type: 'boolean',
|
||||
},
|
||||
ref: {
|
||||
title: 'Branch reference',
|
||||
description: `Branch reference to create branch from. The default value is 'master'`,
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
projectVariables: {
|
||||
title: 'Project variables',
|
||||
description:
|
||||
'Project variables settings based on Gitlab Project Environments API - https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable',
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['key', 'value'],
|
||||
properties: {
|
||||
key: {
|
||||
title: 'Variable key',
|
||||
}),
|
||||
repoVisibility: z =>
|
||||
z
|
||||
.enum(['private', 'public', 'internal'], {
|
||||
description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings.visibility instead)`,
|
||||
})
|
||||
.optional(),
|
||||
defaultBranch: z =>
|
||||
z
|
||||
.string({
|
||||
description: `Sets the default branch on the repository. The default value is 'master'`,
|
||||
})
|
||||
.optional(),
|
||||
gitCommitMessage: z =>
|
||||
z
|
||||
.string({
|
||||
description: `Sets the commit message on the repository. The default value is 'initial commit'`,
|
||||
})
|
||||
.optional(),
|
||||
gitAuthorName: z =>
|
||||
z
|
||||
.string({
|
||||
description: `Sets the default author name for the commit. The default value is 'Scaffolder'`,
|
||||
})
|
||||
.optional(),
|
||||
gitAuthorEmail: z =>
|
||||
z
|
||||
.string({
|
||||
description: `Sets the default author email for the commit.`,
|
||||
})
|
||||
.optional(),
|
||||
signCommit: z =>
|
||||
z
|
||||
.boolean({
|
||||
description: 'Sign commit with configured PGP private key',
|
||||
})
|
||||
.optional(),
|
||||
sourcePath: z =>
|
||||
z
|
||||
.union([z.string(), z.boolean()], {
|
||||
description:
|
||||
'Path within the workspace that will be used as the repository root. If omitted or set to true, the entire workspace will be published as the repository. If set to false, the created repository will be empty.',
|
||||
})
|
||||
.optional(),
|
||||
skipExisting: z =>
|
||||
z
|
||||
.boolean({
|
||||
description:
|
||||
'Do not publish the repository if it already exists. The default value is false.',
|
||||
})
|
||||
.optional(),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
setUserAsOwner: z =>
|
||||
z
|
||||
.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',
|
||||
})
|
||||
.optional(),
|
||||
topics: z =>
|
||||
z
|
||||
.array(z.string(), {
|
||||
description:
|
||||
'Topic labels to apply on the repository. (deprecated, use settings.topics instead)',
|
||||
})
|
||||
.optional(),
|
||||
settings: z =>
|
||||
z
|
||||
.object({
|
||||
path: z
|
||||
.string({
|
||||
description:
|
||||
'The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed',
|
||||
type: 'string',
|
||||
},
|
||||
value: {
|
||||
title: 'Variable value',
|
||||
description: 'The value of a variable',
|
||||
type: 'string',
|
||||
},
|
||||
description: {
|
||||
title: 'Variable description',
|
||||
description: `The description of the variable. The default value is 'null'`,
|
||||
type: 'string',
|
||||
},
|
||||
variable_type: {
|
||||
title: 'Variable type',
|
||||
description: `The type of a variable. The default value is 'env_var'`,
|
||||
type: 'string',
|
||||
enum: ['env_var', 'file'],
|
||||
},
|
||||
protected: {
|
||||
title: 'Variable protection',
|
||||
description: `Whether the variable is protected. The default value is 'false'`,
|
||||
type: 'boolean',
|
||||
},
|
||||
raw: {
|
||||
title: 'Variable raw',
|
||||
description: `Whether the variable is in raw format. The default value is 'false'`,
|
||||
type: 'boolean',
|
||||
},
|
||||
environment_scope: {
|
||||
title: 'Variable environment scope',
|
||||
description: `The environment_scope of the variable. The default value is '*'`,
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes).',
|
||||
})
|
||||
.optional(),
|
||||
auto_devops_enabled: z
|
||||
.boolean({
|
||||
description: 'Enable Auto DevOps for this project',
|
||||
})
|
||||
.optional(),
|
||||
ci_config_path: z
|
||||
.string({
|
||||
description: 'Custom CI config path for this project',
|
||||
})
|
||||
.optional(),
|
||||
description: z
|
||||
.string({
|
||||
description: 'Short project description',
|
||||
})
|
||||
.optional(),
|
||||
merge_method: z
|
||||
.enum(['merge', 'rebase_merge', 'ff'], {
|
||||
description: 'Merge Methods (merge, rebase_merge, ff)',
|
||||
})
|
||||
.optional(),
|
||||
squash_option: z
|
||||
.enum(['default_off', 'default_on', 'never', 'always'], {
|
||||
description:
|
||||
'Set squash option for the project (never, always, default_on, default_off)',
|
||||
})
|
||||
.optional(),
|
||||
topics: z
|
||||
.array(z.string(), {
|
||||
description: 'Topic labels to apply on the repository',
|
||||
})
|
||||
.optional(),
|
||||
visibility: z
|
||||
.enum(['private', 'public', 'internal'], {
|
||||
description:
|
||||
'The visibility of the project. Can be private, internal, or public. The default value is private.',
|
||||
})
|
||||
.optional(),
|
||||
only_allow_merge_if_all_discussions_are_resolved: z
|
||||
.boolean({
|
||||
description:
|
||||
'Set whether merge requests can only be merged when all the discussions are resolved.',
|
||||
})
|
||||
.optional(),
|
||||
only_allow_merge_if_pipeline_succeeds: z
|
||||
.boolean({
|
||||
description:
|
||||
'Set whether merge requests can only be merged with successful pipelines. This setting is named Pipelines must succeed in the project settings.',
|
||||
})
|
||||
.optional(),
|
||||
allow_merge_on_skipped_pipeline: z
|
||||
.boolean({
|
||||
description:
|
||||
'Set whether or not merge requests can be merged with skipped jobs.',
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.optional(),
|
||||
branches: z =>
|
||||
z
|
||||
.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
protect: z.boolean().optional(),
|
||||
create: z.boolean().optional(),
|
||||
ref: z.string().optional(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
projectVariables: z =>
|
||||
z
|
||||
.array(
|
||||
z.object({
|
||||
key: z.string(),
|
||||
value: z.string(),
|
||||
description: z.string().optional(),
|
||||
variable_type: z.enum(['env_var', 'file']).optional(),
|
||||
protected: z.boolean().optional(),
|
||||
masked: z.boolean().optional(),
|
||||
raw: z.boolean().optional(),
|
||||
environment_scope: z.string().optional(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
},
|
||||
output: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
remoteUrl: {
|
||||
title: 'A URL to the repository with the provider',
|
||||
type: 'string',
|
||||
},
|
||||
repoContentsUrl: {
|
||||
title: 'A URL to the root of the repository',
|
||||
type: 'string',
|
||||
},
|
||||
projectId: {
|
||||
title: 'The ID of the project',
|
||||
type: 'number',
|
||||
},
|
||||
commitHash: {
|
||||
title: 'The git commit hash of the initial commit',
|
||||
type: 'string',
|
||||
},
|
||||
created: {
|
||||
title: 'Whether the repository was created or not',
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
remoteUrl: z =>
|
||||
z.string({
|
||||
description: 'A URL to the repository with the provider',
|
||||
}),
|
||||
repoContentsUrl: z =>
|
||||
z.string({
|
||||
description: 'A URL to the root of the repository',
|
||||
}),
|
||||
projectId: z =>
|
||||
z.number({
|
||||
description: 'The ID of the project',
|
||||
}),
|
||||
commitHash: z =>
|
||||
z.string({
|
||||
description: 'The git commit hash of the initial commit',
|
||||
}),
|
||||
created: z =>
|
||||
z.boolean({
|
||||
description: 'Whether the repository was created or not',
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { GroupSchema } from '@gitbeaker/rest';
|
||||
import { z } from 'zod';
|
||||
import commonGitlabConfig from '../commonGitlabConfig';
|
||||
import { getClient, parseRepoUrl } from '../util';
|
||||
import { examples } from './gitlabGroupEnsureExists.examples';
|
||||
|
||||
@@ -38,9 +36,19 @@ export const createGitlabGroupEnsureExistsAction = (options: {
|
||||
supportsDryRun: true,
|
||||
examples,
|
||||
schema: {
|
||||
input: commonGitlabConfig.merge(
|
||||
z.object({
|
||||
path: z
|
||||
input: {
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
}),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
path: z =>
|
||||
z
|
||||
.array(
|
||||
z.string().or(
|
||||
z.object({
|
||||
@@ -54,13 +62,15 @@ export const createGitlabGroupEnsureExistsAction = (options: {
|
||||
},
|
||||
)
|
||||
.min(1),
|
||||
}),
|
||||
),
|
||||
output: z.object({
|
||||
groupId: z
|
||||
.number({ description: 'The id of the innermost sub-group' })
|
||||
.optional(),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
groupId: z =>
|
||||
z
|
||||
.number({
|
||||
description: 'The id of the innermost sub-group',
|
||||
})
|
||||
.optional(),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
if (ctx.isDryRun) {
|
||||
|
||||
@@ -17,84 +17,12 @@
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import commonGitlabConfig, { IssueType } from '../commonGitlabConfig';
|
||||
import { IssueType } from '../commonGitlabConfig';
|
||||
import { examples } from './gitlabIssueCreate.examples';
|
||||
import { z } from 'zod';
|
||||
import { checkEpicScope, convertDate, getClient, parseRepoUrl } from '../util';
|
||||
import { CreateIssueOptions, IssueSchema } from '@gitbeaker/rest';
|
||||
import { getErrorMessage } from './helpers';
|
||||
|
||||
const issueInputProperties = z.object({
|
||||
projectId: z.number().describe('Project Id'),
|
||||
title: z.string({ description: 'Title of the issue' }),
|
||||
assignees: z
|
||||
.array(z.number(), {
|
||||
description: 'IDs of the users to assign the issue to.',
|
||||
})
|
||||
.optional(),
|
||||
confidential: z.boolean({ description: 'Issue Confidentiality' }).optional(),
|
||||
description: z.string().describe('Issue description').max(1048576).optional(),
|
||||
createdAt: z
|
||||
.string()
|
||||
.describe('Creation date/time')
|
||||
.regex(
|
||||
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
||||
'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',
|
||||
)
|
||||
.optional(),
|
||||
dueDate: z
|
||||
.string()
|
||||
.describe('Due date/time')
|
||||
.regex(
|
||||
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
||||
'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',
|
||||
)
|
||||
.optional(),
|
||||
discussionToResolve: z
|
||||
.string({
|
||||
description:
|
||||
'Id of a discussion to resolve. Use in combination with "merge_request_to_resolve_discussions_of"',
|
||||
})
|
||||
.optional(),
|
||||
epicId: z
|
||||
.number({ description: 'Id of the linked Epic' })
|
||||
.min(0, 'Valid values should be equal or greater than zero')
|
||||
.optional(),
|
||||
labels: z.string({ description: 'Labels to apply' }).optional(),
|
||||
issueType: z
|
||||
.nativeEnum(IssueType, {
|
||||
description: 'Type of the issue',
|
||||
})
|
||||
.optional(),
|
||||
mergeRequestToResolveDiscussionsOf: z
|
||||
.number({
|
||||
description: 'IID of a merge request in which to resolve all issues',
|
||||
})
|
||||
.optional(),
|
||||
milestoneId: z
|
||||
.number({ description: 'Global ID of a milestone to assign the issue' })
|
||||
.optional(),
|
||||
weight: z
|
||||
.number({ description: 'The issue weight' })
|
||||
.min(0)
|
||||
.refine(value => {
|
||||
const isValid = value >= 0;
|
||||
if (!isValid) {
|
||||
return {
|
||||
message: 'Valid values should be equal or greater than zero',
|
||||
};
|
||||
}
|
||||
return isValid;
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const issueOutputProperties = z.object({
|
||||
issueUrl: z.string({ description: 'Issue Url' }),
|
||||
issueId: z.number({ description: 'Issue Id' }),
|
||||
issueIid: z.number({ description: 'Issue Iid' }),
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a `gitlab:issues:create` Scaffolder action.
|
||||
*
|
||||
@@ -110,8 +38,133 @@ export const createGitlabIssueAction = (options: {
|
||||
description: 'Creates a Gitlab issue.',
|
||||
examples,
|
||||
schema: {
|
||||
input: commonGitlabConfig.merge(issueInputProperties),
|
||||
output: issueOutputProperties,
|
||||
input: {
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
}),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
projectId: z =>
|
||||
z.number({
|
||||
description: 'Project Id',
|
||||
}),
|
||||
title: z =>
|
||||
z.string({
|
||||
description: 'Title of the issue',
|
||||
}),
|
||||
assignees: z =>
|
||||
z
|
||||
.array(z.number(), {
|
||||
description: 'IDs of the users to assign the issue to.',
|
||||
})
|
||||
.optional(),
|
||||
confidential: z =>
|
||||
z
|
||||
.boolean({
|
||||
description: 'Issue Confidentiality',
|
||||
})
|
||||
.optional(),
|
||||
description: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Issue description',
|
||||
})
|
||||
.max(1048576)
|
||||
.optional(),
|
||||
createdAt: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Creation date/time',
|
||||
})
|
||||
.regex(
|
||||
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
||||
'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',
|
||||
)
|
||||
.optional(),
|
||||
dueDate: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Due date/time',
|
||||
})
|
||||
.regex(
|
||||
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
||||
'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',
|
||||
)
|
||||
.optional(),
|
||||
discussionToResolve: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'Id of a discussion to resolve. Use in combination with "merge_request_to_resolve_discussions_of"',
|
||||
})
|
||||
.optional(),
|
||||
epicId: z =>
|
||||
z
|
||||
.number({
|
||||
description: 'Id of the linked Epic',
|
||||
})
|
||||
.min(0, 'Valid values should be equal or greater than zero')
|
||||
.optional(),
|
||||
labels: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Labels to apply',
|
||||
})
|
||||
.optional(),
|
||||
issueType: z =>
|
||||
z
|
||||
.nativeEnum(IssueType, {
|
||||
description: 'Type of the issue',
|
||||
})
|
||||
.optional(),
|
||||
mergeRequestToResolveDiscussionsOf: z =>
|
||||
z
|
||||
.number({
|
||||
description:
|
||||
'IID of a merge request in which to resolve all issues',
|
||||
})
|
||||
.optional(),
|
||||
milestoneId: z =>
|
||||
z
|
||||
.number({
|
||||
description: 'Global ID of a milestone to assign the issue',
|
||||
})
|
||||
.optional(),
|
||||
weight: z =>
|
||||
z
|
||||
.number({
|
||||
description: 'The issue weight',
|
||||
})
|
||||
.min(0)
|
||||
.refine(
|
||||
value => {
|
||||
return value >= 0;
|
||||
},
|
||||
{
|
||||
message: 'Valid values should be equal or greater than zero',
|
||||
},
|
||||
)
|
||||
.optional(),
|
||||
},
|
||||
output: {
|
||||
issueUrl: z =>
|
||||
z.string({
|
||||
description: 'Issue Url',
|
||||
}),
|
||||
issueId: z =>
|
||||
z.number({
|
||||
description: 'Issue Id',
|
||||
}),
|
||||
issueIid: z =>
|
||||
z.number({
|
||||
description: 'Issue Iid',
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
try {
|
||||
@@ -132,7 +185,7 @@ export const createGitlabIssueAction = (options: {
|
||||
milestoneId,
|
||||
weight,
|
||||
token,
|
||||
} = commonGitlabConfig.merge(issueInputProperties).parse(ctx.input);
|
||||
} = ctx.input;
|
||||
|
||||
const { host } = parseRepoUrl(repoUrl, integrations);
|
||||
const api = getClient({ host, integrations, token });
|
||||
@@ -201,12 +254,6 @@ export const createGitlabIssueAction = (options: {
|
||||
ctx.output('issueUrl', response.web_url);
|
||||
ctx.output('issueIid', response.iid);
|
||||
} catch (error: any) {
|
||||
if (error instanceof z.ZodError) {
|
||||
// Handling Zod validation errors
|
||||
throw new InputError(`Validation error: ${error.message}`, {
|
||||
validationErrors: error.errors,
|
||||
});
|
||||
}
|
||||
// Handling other errors
|
||||
throw new InputError(
|
||||
`Failed to create GitLab issue: ${getErrorMessage(error)}`,
|
||||
|
||||
@@ -17,123 +17,12 @@
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import commonGitlabConfig, {
|
||||
IssueStateEvent,
|
||||
IssueType,
|
||||
} from '../commonGitlabConfig';
|
||||
import { IssueStateEvent, IssueType } from '../commonGitlabConfig';
|
||||
import { examples } from './gitlabIssueEdit.examples';
|
||||
import { z } from 'zod';
|
||||
import { checkEpicScope, convertDate, getClient, parseRepoUrl } from '../util';
|
||||
import { EditIssueOptions, IssueSchema } from '@gitbeaker/rest';
|
||||
import { getErrorMessage } from './helpers';
|
||||
|
||||
const editIssueInputProperties = z.object({
|
||||
projectId: z
|
||||
.number()
|
||||
.describe(
|
||||
'The global ID or URL-encoded path of the project owned by the authenticated user.',
|
||||
),
|
||||
issueIid: z.number().describe("The internal ID of a project's issue"),
|
||||
addLabels: z
|
||||
.string({
|
||||
description:
|
||||
'Comma-separated label names to add to an issue. If a label does not already exist, this creates a new project label and assigns it to the issue.',
|
||||
})
|
||||
.optional(),
|
||||
assignees: z
|
||||
.array(z.number(), {
|
||||
description: 'IDs of the users to assign the issue to.',
|
||||
})
|
||||
.optional(),
|
||||
confidential: z
|
||||
.boolean({ description: 'Updates an issue to be confidential.' })
|
||||
.optional(),
|
||||
description: z
|
||||
.string()
|
||||
.describe('The description of an issue. Limited to 1,048,576 characters.')
|
||||
.max(1048576)
|
||||
.optional(),
|
||||
discussionLocked: z
|
||||
.boolean({
|
||||
description:
|
||||
'Flag indicating if the issue’s discussion is locked. If the discussion is locked only project members can add or edit comments.',
|
||||
})
|
||||
.optional(),
|
||||
dueDate: z
|
||||
.string()
|
||||
.describe(
|
||||
'The due date. Date time string in the format YYYY-MM-DD, for example 2016-03-11.',
|
||||
)
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Invalid date format. Use YYYY-MM-DD')
|
||||
.optional(),
|
||||
epicId: z
|
||||
.number({
|
||||
description:
|
||||
'ID of the epic to add the issue to. Valid values are greater than or equal to 0.',
|
||||
})
|
||||
.min(0, 'Valid values should be equal or greater than zero')
|
||||
.optional(),
|
||||
issueType: z
|
||||
.nativeEnum(IssueType, {
|
||||
description:
|
||||
'Updates the type of issue. One of issue, incident, test_case or task.',
|
||||
})
|
||||
.optional(),
|
||||
labels: z
|
||||
.string({
|
||||
description:
|
||||
'Comma-separated label names for an issue. Set to an empty string to unassign all labels. If a label does not already exist, this creates a new project label and assigns it to the issue.',
|
||||
})
|
||||
.optional(),
|
||||
milestoneId: z
|
||||
.number({
|
||||
description:
|
||||
'The global ID of a milestone to assign the issue to. Set to 0 or provide an empty value to unassign a milestone',
|
||||
})
|
||||
.optional(),
|
||||
removeLabels: z
|
||||
.string({
|
||||
description: 'Comma-separated label names to remove from an issue.',
|
||||
})
|
||||
.optional(),
|
||||
stateEvent: z
|
||||
.nativeEnum(IssueStateEvent, {
|
||||
description:
|
||||
'The state event of an issue. To close the issue, use close, and to reopen it, use reopen.',
|
||||
})
|
||||
.optional(),
|
||||
title: z.string().describe('The title of an issue.').optional(),
|
||||
updatedAt: z
|
||||
.string()
|
||||
.describe(
|
||||
'When the issue was updated. Date time string, ISO 8601 formatted',
|
||||
)
|
||||
.regex(
|
||||
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
||||
'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',
|
||||
)
|
||||
.optional(),
|
||||
weight: z
|
||||
.number({ description: 'The issue weight' })
|
||||
.min(0, 'Valid values should be equal or greater than zero')
|
||||
.max(10, 'Valid values should be equal or less than 10')
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const editIssueOutputProperties = z.object({
|
||||
issueUrl: z.string({ description: 'Issue WebUrl' }),
|
||||
projectId: z.number({
|
||||
description: 'The project id the issue belongs to WebUrl',
|
||||
}),
|
||||
issueId: z.number({ description: 'The issues Id' }),
|
||||
issueIid: z.number({
|
||||
description: "The issues internal ID of a project's issue",
|
||||
}),
|
||||
state: z.string({ description: 'The state event of an issue' }),
|
||||
title: z.string({ description: 'The title of an issue.' }),
|
||||
updatedAt: z.string({ description: 'The last updated time of the issue.' }),
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a `gitlab:issue:edit` Scaffolder action.
|
||||
*
|
||||
@@ -149,8 +38,167 @@ export const editGitlabIssueAction = (options: {
|
||||
description: 'Edit a Gitlab issue.',
|
||||
examples,
|
||||
schema: {
|
||||
input: commonGitlabConfig.merge(editIssueInputProperties),
|
||||
output: editIssueOutputProperties,
|
||||
input: {
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
}),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
projectId: z =>
|
||||
z.number({
|
||||
description:
|
||||
'The global ID or URL-encoded path of the project owned by the authenticated user.',
|
||||
}),
|
||||
issueIid: z =>
|
||||
z.number({
|
||||
description: "The internal ID of a project's issue",
|
||||
}),
|
||||
addLabels: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'Comma-separated label names to add to an issue. If a label does not already exist, this creates a new project label and assigns it to the issue.',
|
||||
})
|
||||
.optional(),
|
||||
assignees: z =>
|
||||
z
|
||||
.array(z.number(), {
|
||||
description: 'IDs of the users to assign the issue to.',
|
||||
})
|
||||
.optional(),
|
||||
confidential: z =>
|
||||
z
|
||||
.boolean({
|
||||
description: 'Updates an issue to be confidential.',
|
||||
})
|
||||
.optional(),
|
||||
description: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'The description of an issue. Limited to 1,048,576 characters.',
|
||||
})
|
||||
.max(1048576)
|
||||
.optional(),
|
||||
discussionLocked: z =>
|
||||
z
|
||||
.boolean({
|
||||
description:
|
||||
'Flag indicating if the issue discussion is locked. If the discussion is locked only project members can add or edit comments.',
|
||||
})
|
||||
.optional(),
|
||||
dueDate: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'The due date. Date time string in the format YYYY-MM-DD, for example 2016-03-11.',
|
||||
})
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Invalid date format. Use YYYY-MM-DD')
|
||||
.optional(),
|
||||
epicId: z =>
|
||||
z
|
||||
.number({
|
||||
description:
|
||||
'ID of the epic to add the issue to. Valid values are greater than or equal to 0.',
|
||||
})
|
||||
.min(0, 'Valid values should be equal or greater than zero')
|
||||
.optional(),
|
||||
issueType: z =>
|
||||
z
|
||||
.nativeEnum(IssueType, {
|
||||
description:
|
||||
'Updates the type of issue. One of issue, incident, test_case or task.',
|
||||
})
|
||||
.optional(),
|
||||
labels: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'Comma-separated label names for an issue. Set to an empty string to unassign all labels. If a label does not already exist, this creates a new project label and assigns it to the issue.',
|
||||
})
|
||||
.optional(),
|
||||
milestoneId: z =>
|
||||
z
|
||||
.number({
|
||||
description:
|
||||
'The global ID of a milestone to assign the issue to. Set to 0 or provide an empty value to unassign a milestone',
|
||||
})
|
||||
.optional(),
|
||||
removeLabels: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'Comma-separated label names to remove from an issue.',
|
||||
})
|
||||
.optional(),
|
||||
stateEvent: z =>
|
||||
z
|
||||
.nativeEnum(IssueStateEvent, {
|
||||
description:
|
||||
'The state event of an issue. To close the issue, use close, and to reopen it, use reopen.',
|
||||
})
|
||||
.optional(),
|
||||
title: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The title of an issue.',
|
||||
})
|
||||
.optional(),
|
||||
updatedAt: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'When the issue was updated. Date time string, ISO 8601 formatted',
|
||||
})
|
||||
.regex(
|
||||
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/,
|
||||
'Invalid date format. Use YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss.SSSZ',
|
||||
)
|
||||
.optional(),
|
||||
weight: z =>
|
||||
z
|
||||
.number({
|
||||
description: 'The issue weight',
|
||||
})
|
||||
.min(0, 'Valid values should be equal or greater than zero')
|
||||
.max(10, 'Valid values should be equal or less than 10')
|
||||
.optional(),
|
||||
},
|
||||
output: {
|
||||
issueUrl: z =>
|
||||
z.string({
|
||||
description: 'Issue WebUrl',
|
||||
}),
|
||||
projectId: z =>
|
||||
z.number({
|
||||
description: 'The project id the issue belongs to WebUrl',
|
||||
}),
|
||||
issueId: z =>
|
||||
z.number({
|
||||
description: 'The issues Id',
|
||||
}),
|
||||
issueIid: z =>
|
||||
z.number({
|
||||
description: "The issues internal ID of a project's issue",
|
||||
}),
|
||||
state: z =>
|
||||
z.string({
|
||||
description: 'The state event of an issue',
|
||||
}),
|
||||
title: z =>
|
||||
z.string({
|
||||
description: 'The title of an issue.',
|
||||
}),
|
||||
updatedAt: z =>
|
||||
z.string({
|
||||
description: 'The last updated time of the issue.',
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
try {
|
||||
@@ -174,7 +222,7 @@ export const editGitlabIssueAction = (options: {
|
||||
stateEvent,
|
||||
weight,
|
||||
token,
|
||||
} = commonGitlabConfig.merge(editIssueInputProperties).parse(ctx.input);
|
||||
} = ctx.input;
|
||||
|
||||
const { host } = parseRepoUrl(repoUrl, integrations);
|
||||
const api = getClient({ host, integrations, token });
|
||||
@@ -252,12 +300,6 @@ export const editGitlabIssueAction = (options: {
|
||||
ctx.output('state', editedIssue.state);
|
||||
ctx.output('updatedAt', editedIssue.updatedAt);
|
||||
} catch (error: any) {
|
||||
if (error instanceof z.ZodError) {
|
||||
// Handling Zod validation errors
|
||||
throw new InputError(`Validation error: ${error.message}`, {
|
||||
validationErrors: error.errors,
|
||||
});
|
||||
}
|
||||
// Handling other errors
|
||||
throw new InputError(
|
||||
`Failed to edit/modify GitLab issue: ${getErrorMessage(error)}`,
|
||||
|
||||
@@ -21,28 +21,10 @@ import {
|
||||
ExpandedPipelineSchema,
|
||||
PipelineTriggerTokenSchema,
|
||||
} from '@gitbeaker/rest';
|
||||
import { z } from 'zod';
|
||||
import commonGitlabConfig from '../commonGitlabConfig';
|
||||
import { getClient, parseRepoUrl } from '../util';
|
||||
import { examples } from './gitlabPipelineTrigger.examples';
|
||||
import { getErrorMessage } from './helpers';
|
||||
|
||||
const pipelineInputProperties = z.object({
|
||||
projectId: z.number().describe('Project Id'),
|
||||
tokenDescription: z.string().describe('Pipeline token description'),
|
||||
branch: z.string().describe('Project branch'),
|
||||
variables: z
|
||||
.record(z.string(), z.string())
|
||||
.optional()
|
||||
.describe(
|
||||
'A object/record of key-valued strings containing the pipeline variables.',
|
||||
),
|
||||
});
|
||||
|
||||
const pipelineOutputProperties = z.object({
|
||||
pipelineUrl: z.string({ description: 'Pipeline Url' }),
|
||||
});
|
||||
|
||||
/**
|
||||
* Creates a `gitlab:pipeline:trigger` Scaffolder action.
|
||||
*
|
||||
@@ -58,15 +40,50 @@ export const createTriggerGitlabPipelineAction = (options: {
|
||||
description: 'Triggers a GitLab Pipeline.',
|
||||
examples,
|
||||
schema: {
|
||||
input: commonGitlabConfig.merge(pipelineInputProperties),
|
||||
output: pipelineOutputProperties,
|
||||
input: {
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
}),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
projectId: z =>
|
||||
z.number({
|
||||
description: 'Project Id',
|
||||
}),
|
||||
tokenDescription: z =>
|
||||
z.string({
|
||||
description: 'Pipeline token description',
|
||||
}),
|
||||
branch: z =>
|
||||
z.string({
|
||||
description: 'Project branch',
|
||||
}),
|
||||
variables: z =>
|
||||
z
|
||||
.record(z.string(), z.string(), {
|
||||
description:
|
||||
'A object/record of key-valued strings containing the pipeline variables.',
|
||||
})
|
||||
.optional(),
|
||||
},
|
||||
output: {
|
||||
pipelineUrl: z =>
|
||||
z.string({
|
||||
description: 'Pipeline Url',
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
let pipelineTriggerToken: string | undefined = undefined;
|
||||
let pipelineTriggerId: number | undefined = undefined;
|
||||
|
||||
const { repoUrl, projectId, tokenDescription, token, branch, variables } =
|
||||
commonGitlabConfig.merge(pipelineInputProperties).parse(ctx.input);
|
||||
ctx.input;
|
||||
|
||||
const { host } = parseRepoUrl(repoUrl, integrations);
|
||||
const api = getClient({ host, integrations, token });
|
||||
@@ -118,12 +135,6 @@ export const createTriggerGitlabPipelineAction = (options: {
|
||||
|
||||
ctx.output('pipelineUrl', pipelineTriggerResponse.web_url);
|
||||
} catch (error: any) {
|
||||
if (error instanceof z.ZodError) {
|
||||
// Handling Zod validation errors
|
||||
throw new InputError(`Validation error: ${error.message}`, {
|
||||
validationErrors: error.errors,
|
||||
});
|
||||
}
|
||||
// Handling other errors
|
||||
throw new InputError(
|
||||
`Failed to trigger Pipeline: ${getErrorMessage(error)}`,
|
||||
|
||||
+49
-34
@@ -19,7 +19,6 @@ import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { AccessTokenScopes, Gitlab } from '@gitbeaker/rest';
|
||||
import { DateTime } from 'luxon';
|
||||
import { z } from 'zod';
|
||||
import { getToken } from '../util';
|
||||
import { examples } from './gitlabProjectAccessTokenCreate.examples';
|
||||
|
||||
@@ -38,39 +37,55 @@ export const createGitlabProjectAccessTokenAction = (options: {
|
||||
id: 'gitlab:projectAccessToken:create',
|
||||
examples,
|
||||
schema: {
|
||||
input: z.object({
|
||||
projectId: z.union([z.number(), z.string()], {
|
||||
description: 'Project ID/Name(slug) of the Gitlab Project',
|
||||
}),
|
||||
token: z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
name: z.string({ description: 'Name of Access Key' }).optional(),
|
||||
repoUrl: z.string({ description: 'URL to gitlab instance' }),
|
||||
accessLevel: z
|
||||
.number({
|
||||
description:
|
||||
'Access Level of the Token, 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), and 50 (Owner)',
|
||||
})
|
||||
.optional(),
|
||||
scopes: z
|
||||
.string({
|
||||
description: 'Scopes for a project access token',
|
||||
})
|
||||
.array()
|
||||
.optional(),
|
||||
expiresAt: z
|
||||
.string({
|
||||
description:
|
||||
'Expiration date of the access token in ISO format (YYYY-MM-DD). If Empty, it will set to the maximum of 365 days.',
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
output: z.object({
|
||||
access_token: z.string({ description: 'Access Token' }),
|
||||
}),
|
||||
input: {
|
||||
projectId: z =>
|
||||
z.union([z.number(), z.string()], {
|
||||
description: 'Project ID/Name(slug) of the Gitlab Project',
|
||||
}),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
name: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Name of Access Key',
|
||||
})
|
||||
.optional(),
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: 'URL to gitlab instance',
|
||||
}),
|
||||
accessLevel: z =>
|
||||
z
|
||||
.number({
|
||||
description:
|
||||
'Access Level of the Token, 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), and 50 (Owner)',
|
||||
})
|
||||
.optional(),
|
||||
scopes: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Scopes for a project access token',
|
||||
})
|
||||
.array()
|
||||
.optional(),
|
||||
expiresAt: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'Expiration date of the access token in ISO format (YYYY-MM-DD). If Empty, it will set to the maximum of 365 days.',
|
||||
})
|
||||
.optional(),
|
||||
},
|
||||
output: {
|
||||
access_token: z =>
|
||||
z.string({
|
||||
description: 'Access Token',
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
|
||||
|
||||
+37
-15
@@ -18,8 +18,6 @@ import { InputError } from '@backstage/errors';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { DeployTokenScope, Gitlab } from '@gitbeaker/rest';
|
||||
import { z } from 'zod';
|
||||
import commonGitlabConfig from '../commonGitlabConfig';
|
||||
import { getToken } from '../util';
|
||||
import { examples } from './gitlabProjectDeployTokenCreate.examples';
|
||||
|
||||
@@ -37,22 +35,46 @@ export const createGitlabProjectDeployTokenAction = (options: {
|
||||
id: 'gitlab:projectDeployToken:create',
|
||||
examples,
|
||||
schema: {
|
||||
input: commonGitlabConfig.merge(
|
||||
z.object({
|
||||
projectId: z.union([z.number(), z.string()], {
|
||||
input: {
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
}),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
projectId: z =>
|
||||
z.union([z.number(), z.string()], {
|
||||
description: 'Project ID',
|
||||
}),
|
||||
name: z.string({ description: 'Deploy Token Name' }),
|
||||
username: z
|
||||
.string({ description: 'Deploy Token Username' })
|
||||
name: z =>
|
||||
z.string({
|
||||
description: 'Deploy Token Name',
|
||||
}),
|
||||
username: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Deploy Token Username',
|
||||
})
|
||||
.optional(),
|
||||
scopes: z.array(z.string(), { description: 'Scopes' }),
|
||||
}),
|
||||
),
|
||||
output: z.object({
|
||||
deploy_token: z.string({ description: 'Deploy Token' }),
|
||||
user: z.string({ description: 'User' }),
|
||||
}),
|
||||
scopes: z =>
|
||||
z.array(z.string(), {
|
||||
description: 'Scopes',
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
deploy_token: z =>
|
||||
z.string({
|
||||
description: 'Deploy Token',
|
||||
}),
|
||||
user: z =>
|
||||
z.string({
|
||||
description: 'User',
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
ctx.logger.info(`Creating Token for Project "${ctx.input.projectId}"`);
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ jest.mock('@gitbeaker/rest', () => ({
|
||||
}));
|
||||
|
||||
describe('gitlab:group:migrate', () => {
|
||||
let instance: TemplateAction<any>;
|
||||
let instance: TemplateAction<any, any, any>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
@@ -37,7 +37,7 @@ jest.mock('@gitbeaker/rest', () => ({
|
||||
}));
|
||||
|
||||
describe('createGitlabRepoMigrate', () => {
|
||||
let instance: TemplateAction<any>;
|
||||
let instance: TemplateAction<any, any, any>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
@@ -34,66 +34,42 @@ export const createGitlabProjectMigrateAction = (options: {
|
||||
}) => {
|
||||
const { integrations } = options;
|
||||
|
||||
return createTemplateAction<{
|
||||
destinationAccessToken: string;
|
||||
destinationUrl: string;
|
||||
sourceAccessToken: string;
|
||||
sourceFullPath: string;
|
||||
sourceUrl: string;
|
||||
}>({
|
||||
return createTemplateAction({
|
||||
id: 'gitlab:group:migrate',
|
||||
examples,
|
||||
schema: {
|
||||
input: {
|
||||
required: [
|
||||
'destinationAccessToken',
|
||||
'destinationUrl',
|
||||
'sourceAccessToken',
|
||||
'sourceFullPath',
|
||||
'sourceUrl',
|
||||
],
|
||||
type: 'object',
|
||||
properties: {
|
||||
destinationAccessToken: {
|
||||
type: 'string',
|
||||
title: 'Target Repository Access Token',
|
||||
destinationAccessToken: z =>
|
||||
z.string({
|
||||
description: `The token to use for authorization to the target GitLab'`,
|
||||
},
|
||||
destinationUrl: {
|
||||
type: 'string',
|
||||
title: 'Target Project Location',
|
||||
}),
|
||||
destinationUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
},
|
||||
sourceAccessToken: {
|
||||
type: 'string',
|
||||
title: 'Source Group Access Token',
|
||||
}),
|
||||
sourceAccessToken: z =>
|
||||
z.string({
|
||||
description: `The token to use for authorization to the source GitLab'`,
|
||||
},
|
||||
sourceFullPath: {
|
||||
type: 'string',
|
||||
title: 'Group Full Path',
|
||||
}),
|
||||
sourceFullPath: z =>
|
||||
z.string({
|
||||
description:
|
||||
'Full path to the project in the source Gitlab instance',
|
||||
},
|
||||
sourceUrl: {
|
||||
type: 'string',
|
||||
title: 'Source URL Location',
|
||||
}),
|
||||
sourceUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'https://gitlab.com/'`,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
importedRepoUrl: {
|
||||
title: 'URL to the newly imported repo',
|
||||
type: 'string',
|
||||
},
|
||||
migrationId: {
|
||||
title: 'Id of the migration that imports the project',
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
importedRepoUrl: z =>
|
||||
z.string({
|
||||
description: 'URL to the newly imported repo',
|
||||
}),
|
||||
migrationId: z =>
|
||||
z.number({
|
||||
description: 'Id of the migration that imports the project',
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
+42
-18
@@ -17,8 +17,6 @@
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { VariableType } from '@gitbeaker/rest';
|
||||
import { z } from 'zod';
|
||||
import commonGitlabConfig from '../commonGitlabConfig';
|
||||
import { getClient, parseRepoUrl } from '../util';
|
||||
import { examples } from './gitlabProjectVariableCreate.examples';
|
||||
|
||||
@@ -36,39 +34,65 @@ export const createGitlabProjectVariableAction = (options: {
|
||||
id: 'gitlab:projectVariable:create',
|
||||
examples,
|
||||
schema: {
|
||||
input: commonGitlabConfig.merge(
|
||||
z.object({
|
||||
projectId: z.union([z.number(), z.string()], {
|
||||
input: {
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
}),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
projectId: z =>
|
||||
z.union([z.number(), z.string()], {
|
||||
description: 'Project ID',
|
||||
}),
|
||||
key: z
|
||||
key: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed',
|
||||
})
|
||||
.regex(/^[A-Za-z0-9_]{1,255}$/),
|
||||
value: z.string({ description: 'The value of a variable' }),
|
||||
variableType: z.string({
|
||||
value: z =>
|
||||
z.string({
|
||||
description: 'The value of a variable',
|
||||
}),
|
||||
variableType: z =>
|
||||
z.string({
|
||||
description: 'Variable Type (env_var or file)',
|
||||
}),
|
||||
variableProtected: z
|
||||
.boolean({ description: 'Whether the variable is protected' })
|
||||
variableProtected: z =>
|
||||
z
|
||||
.boolean({
|
||||
description: 'Whether the variable is protected',
|
||||
})
|
||||
.default(false)
|
||||
.optional(),
|
||||
masked: z
|
||||
.boolean({ description: 'Whether the variable is masked' })
|
||||
masked: z =>
|
||||
z
|
||||
.boolean({
|
||||
description: 'Whether the variable is masked',
|
||||
})
|
||||
.default(false)
|
||||
.optional(),
|
||||
raw: z
|
||||
.boolean({ description: 'Whether the variable is expandable' })
|
||||
raw: z =>
|
||||
z
|
||||
.boolean({
|
||||
description: 'Whether the variable is expandable',
|
||||
})
|
||||
.default(false)
|
||||
.optional(),
|
||||
environmentScope: z
|
||||
.string({ description: 'The environment_scope of the variable' })
|
||||
environmentScope: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The environment_scope of the variable',
|
||||
})
|
||||
.default('*')
|
||||
.optional(),
|
||||
}),
|
||||
),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
const {
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ jest.mock('@gitbeaker/rest', () => ({
|
||||
}));
|
||||
|
||||
describe('gitlab:repo:push', () => {
|
||||
let instance: TemplateAction<any>;
|
||||
let instance: TemplateAction<any, any, any>;
|
||||
|
||||
const mockDir = createMockDirectory();
|
||||
const workspacePath = mockDir.resolve('workspace');
|
||||
|
||||
@@ -50,7 +50,7 @@ jest.mock('@gitbeaker/rest', () => ({
|
||||
}));
|
||||
|
||||
describe('createGitLabCommit', () => {
|
||||
let instance: TemplateAction<any>;
|
||||
let instance: TemplateAction<any, any, any>;
|
||||
|
||||
const mockDir = createMockDirectory();
|
||||
const workspacePath = mockDir.resolve('workspace');
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { resolveSafeChildPath } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
createTemplateAction,
|
||||
parseRepoUrl,
|
||||
serializeDirectoryContents,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
import { CommitAction } from '@gitbeaker/rest';
|
||||
import path from 'path';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { resolveSafeChildPath } from '@backstage/backend-plugin-api';
|
||||
import { createGitlabApi, getErrorMessage } from './helpers';
|
||||
import { examples } from './gitlabRepoPush.examples';
|
||||
|
||||
@@ -37,78 +37,63 @@ export const createGitlabRepoPushAction = (options: {
|
||||
}) => {
|
||||
const { integrations } = options;
|
||||
|
||||
return createTemplateAction<{
|
||||
repoUrl: string;
|
||||
branchName: string;
|
||||
commitMessage: string;
|
||||
sourcePath?: string;
|
||||
targetPath?: string;
|
||||
token?: string;
|
||||
commitAction?: 'create' | 'delete' | 'update';
|
||||
}>({
|
||||
return createTemplateAction({
|
||||
id: 'gitlab:repo:push',
|
||||
examples,
|
||||
schema: {
|
||||
input: {
|
||||
required: ['repoUrl', 'branchName', 'commitMessage'],
|
||||
type: 'object',
|
||||
properties: {
|
||||
repoUrl: {
|
||||
type: 'string',
|
||||
title: 'Repository Location',
|
||||
repoUrl: z =>
|
||||
z.string({
|
||||
description: `Accepts the format 'gitlab.com?repo=project_name&owner=group_name' where 'project_name' is the repository name and 'group_name' is a group or username`,
|
||||
},
|
||||
branchName: {
|
||||
type: 'string',
|
||||
title: 'Source Branch Name',
|
||||
}),
|
||||
branchName: z =>
|
||||
z.string({
|
||||
description: 'The branch name for the commit',
|
||||
},
|
||||
commitMessage: {
|
||||
type: 'string',
|
||||
title: 'Commit Message',
|
||||
}),
|
||||
commitMessage: z =>
|
||||
z.string({
|
||||
description: `The commit message`,
|
||||
},
|
||||
sourcePath: {
|
||||
type: 'string',
|
||||
title: 'Working Subdirectory',
|
||||
description:
|
||||
'Subdirectory of working directory to copy changes from',
|
||||
},
|
||||
targetPath: {
|
||||
type: 'string',
|
||||
title: 'Repository Subdirectory',
|
||||
description: 'Subdirectory of repository to apply changes to',
|
||||
},
|
||||
token: {
|
||||
title: 'Authentication Token',
|
||||
type: 'string',
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
},
|
||||
commitAction: {
|
||||
title: 'Commit action',
|
||||
type: 'string',
|
||||
enum: ['create', 'update', 'delete'],
|
||||
description:
|
||||
'The action to be used for git commit. Defaults to create, but can be set to update or delete',
|
||||
},
|
||||
},
|
||||
}),
|
||||
sourcePath: z =>
|
||||
z
|
||||
.string({
|
||||
description:
|
||||
'Subdirectory of working directory to copy changes from',
|
||||
})
|
||||
.optional(),
|
||||
targetPath: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'Subdirectory of repository to apply changes to',
|
||||
})
|
||||
.optional(),
|
||||
token: z =>
|
||||
z
|
||||
.string({
|
||||
description: 'The token to use for authorization to GitLab',
|
||||
})
|
||||
.optional(),
|
||||
commitAction: z =>
|
||||
z
|
||||
.enum(['create', 'update', 'delete'], {
|
||||
description:
|
||||
'The action to be used for git commit. Defaults to create, but can be set to update or delete',
|
||||
})
|
||||
.optional(),
|
||||
},
|
||||
output: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
projectid: {
|
||||
title: 'Gitlab Project id/Name(slug)',
|
||||
type: 'string',
|
||||
},
|
||||
projectPath: {
|
||||
title: 'Gitlab Project path',
|
||||
type: 'string',
|
||||
},
|
||||
commitHash: {
|
||||
title: 'The git commit hash of the commit',
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
projectid: z =>
|
||||
z.string({
|
||||
description: 'Gitlab Project id/Name(slug)',
|
||||
}),
|
||||
projectPath: z =>
|
||||
z.string({
|
||||
description: 'Gitlab Project path',
|
||||
}),
|
||||
commitHash: z =>
|
||||
z.string({
|
||||
description: 'The git commit hash of the commit',
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
|
||||
Reference in New Issue
Block a user