feat: reworking zod integration a little bit to reduce the amount of typing you have to do
Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
@@ -16,12 +16,15 @@ export function createFetchCookiecutterAction(options: {
|
||||
reader: UrlReader;
|
||||
integrations: ScmIntegrations;
|
||||
containerRunner: ContainerRunner;
|
||||
}): TemplateAction<{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
values: JsonObject;
|
||||
copyWithoutRender?: string[] | undefined;
|
||||
extensions?: string[] | undefined;
|
||||
imageName?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction<
|
||||
{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
values: JsonObject;
|
||||
copyWithoutRender?: string[] | undefined;
|
||||
extensions?: string[] | undefined;
|
||||
imageName?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
```
|
||||
|
||||
@@ -15,10 +15,13 @@ export function createFetchRailsAction(options: {
|
||||
integrations: ScmIntegrations;
|
||||
containerRunner: ContainerRunner;
|
||||
allowedImageNames?: string[];
|
||||
}): TemplateAction<{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
values: JsonObject;
|
||||
imageName?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction<
|
||||
{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
values: JsonObject;
|
||||
imageName?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
```
|
||||
|
||||
@@ -9,13 +9,16 @@ import { TemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
// @public
|
||||
export function createSentryCreateProjectAction(options: {
|
||||
config: Config;
|
||||
}): TemplateAction<{
|
||||
organizationSlug: string;
|
||||
teamSlug: string;
|
||||
name: string;
|
||||
slug?: string | undefined;
|
||||
authToken?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction<
|
||||
{
|
||||
organizationSlug: string;
|
||||
teamSlug: string;
|
||||
name: string;
|
||||
slug?: string | undefined;
|
||||
authToken?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -7,9 +7,12 @@ import { JsonObject } from '@backstage/types';
|
||||
import { TemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
|
||||
// @public
|
||||
export function createRunYeomanAction(): TemplateAction<{
|
||||
namespace: string;
|
||||
args?: string[] | undefined;
|
||||
options?: JsonObject | undefined;
|
||||
}>;
|
||||
export function createRunYeomanAction(): TemplateAction<
|
||||
{
|
||||
namespace: string;
|
||||
args?: string[] | undefined;
|
||||
options?: JsonObject | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
```
|
||||
|
||||
@@ -24,6 +24,7 @@ import { Observable } from '@backstage/types';
|
||||
import { Octokit } from 'octokit';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { PluginTaskScheduler } from '@backstage/backend-tasks';
|
||||
import { Schema } from 'jsonschema';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
import { SpawnOptionsWithoutStdio } from 'child_process';
|
||||
@@ -33,6 +34,9 @@ import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common';
|
||||
import { TemplateAction as TemplateAction_2 } from '@backstage/plugin-scaffolder-node';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
import { Writable } from 'stream';
|
||||
import { z } from 'zod';
|
||||
import { ZodType } from 'zod';
|
||||
import { ZodTypeDef } from 'zod';
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export type ActionContext<TInput extends JsonObject> = ActionContext_2<TInput>;
|
||||
@@ -66,39 +70,63 @@ export function createCatalogRegisterAction(options: {
|
||||
repoContentsUrl: string;
|
||||
catalogInfoPath?: string | undefined;
|
||||
optional?: boolean | undefined;
|
||||
}
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "createCatalogWriteAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export function createCatalogWriteAction(): TemplateAction<{
|
||||
filePath?: string | undefined;
|
||||
entity: Entity;
|
||||
}>;
|
||||
|
||||
// @public
|
||||
export function createDebugLogAction(): TemplateAction_2<{
|
||||
message?: string | undefined;
|
||||
listWorkspace?: boolean | undefined;
|
||||
}>;
|
||||
export function createCatalogWriteAction(): TemplateAction_2<
|
||||
unknown,
|
||||
z.ZodObject<
|
||||
{
|
||||
filePath: z.ZodOptional<z.ZodString>;
|
||||
entity: z.ZodOptional<z.ZodObject<{}, 'strip', z.ZodTypeAny, {}, {}>>;
|
||||
},
|
||||
'strip',
|
||||
z.ZodTypeAny,
|
||||
{
|
||||
filePath?: string | undefined;
|
||||
entity?: {} | undefined;
|
||||
},
|
||||
{
|
||||
filePath?: string | undefined;
|
||||
entity?: {} | undefined;
|
||||
}
|
||||
>
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createDebugLogAction(): TemplateAction_2<
|
||||
{
|
||||
message?: string | undefined;
|
||||
listWorkspace?: boolean | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createFetchCatalogEntityAction(options: {
|
||||
catalogClient: CatalogApi;
|
||||
}): TemplateAction_2<{
|
||||
entityRef: string;
|
||||
optional?: boolean | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
entityRef: string;
|
||||
optional?: boolean | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createFetchPlainAction(options: {
|
||||
reader: UrlReader;
|
||||
integrations: ScmIntegrations;
|
||||
}): TemplateAction_2<{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createFetchTemplateAction(options: {
|
||||
@@ -106,57 +134,72 @@ export function createFetchTemplateAction(options: {
|
||||
integrations: ScmIntegrations;
|
||||
additionalTemplateFilters?: Record<string, TemplateFilter>;
|
||||
additionalTemplateGlobals?: Record<string, TemplateGlobal>;
|
||||
}): TemplateAction_2<{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
values: any;
|
||||
templateFileExtension?: string | boolean | undefined;
|
||||
copyWithoutRender?: string[] | undefined;
|
||||
copyWithoutTemplating?: string[] | undefined;
|
||||
cookiecutterCompat?: boolean | undefined;
|
||||
replace?: boolean | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
url: string;
|
||||
targetPath?: string | undefined;
|
||||
values: any;
|
||||
templateFileExtension?: string | boolean | undefined;
|
||||
copyWithoutRender?: string[] | undefined;
|
||||
copyWithoutTemplating?: string[] | undefined;
|
||||
cookiecutterCompat?: boolean | undefined;
|
||||
replace?: boolean | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export const createFilesystemDeleteAction: () => TemplateAction_2<{
|
||||
files: string[];
|
||||
}>;
|
||||
export const createFilesystemDeleteAction: () => TemplateAction_2<
|
||||
{
|
||||
files: string[];
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export const createFilesystemRenameAction: () => TemplateAction_2<{
|
||||
files: Array<{
|
||||
from: string;
|
||||
to: string;
|
||||
overwrite?: boolean;
|
||||
}>;
|
||||
}>;
|
||||
export const createFilesystemRenameAction: () => TemplateAction_2<
|
||||
{
|
||||
files: Array<{
|
||||
from: string;
|
||||
to: string;
|
||||
overwrite?: boolean;
|
||||
}>;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createGithubActionsDispatchAction(options: {
|
||||
integrations: ScmIntegrations;
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
workflowId: string;
|
||||
branchOrTagName: string;
|
||||
workflowInputs?:
|
||||
| {
|
||||
[key: string]: string;
|
||||
}
|
||||
| undefined;
|
||||
token?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
workflowId: string;
|
||||
branchOrTagName: string;
|
||||
workflowInputs?:
|
||||
| {
|
||||
[key: string]: string;
|
||||
}
|
||||
| undefined;
|
||||
token?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createGithubIssuesLabelAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
number: number;
|
||||
labels: string[];
|
||||
token?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
number: number;
|
||||
labels: string[];
|
||||
token?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export interface CreateGithubPullRequestActionOptions {
|
||||
@@ -181,344 +224,386 @@ export type CreateGithubPullRequestClientFactoryInput = {
|
||||
export function createGithubRepoCreateAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
homepage?: string | undefined;
|
||||
access?: string | undefined;
|
||||
deleteBranchOnMerge?: boolean | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
allowRebaseMerge?: boolean | undefined;
|
||||
allowSquashMerge?: boolean | undefined;
|
||||
squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined;
|
||||
squashMergeCommitMessage?:
|
||||
| 'PR_BODY'
|
||||
| 'COMMIT_MESSAGES'
|
||||
| 'BLANK'
|
||||
| undefined;
|
||||
allowMergeCommit?: boolean | undefined;
|
||||
allowAutoMerge?: boolean | undefined;
|
||||
requireCodeOwnerReviews?: boolean | undefined;
|
||||
bypassPullRequestAllowances?:
|
||||
| {
|
||||
users?: string[] | undefined;
|
||||
teams?: string[] | undefined;
|
||||
apps?: string[] | undefined;
|
||||
}
|
||||
| undefined;
|
||||
requiredApprovingReviewCount?: number | undefined;
|
||||
restrictions?:
|
||||
| {
|
||||
users: string[];
|
||||
teams: string[];
|
||||
apps?: string[] | undefined;
|
||||
}
|
||||
| undefined;
|
||||
requiredStatusCheckContexts?: string[] | undefined;
|
||||
requireBranchesToBeUpToDate?: boolean | undefined;
|
||||
requiredConversationResolution?: boolean | undefined;
|
||||
repoVisibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
collaborators?:
|
||||
| (
|
||||
| {
|
||||
user: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
team: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
username: string;
|
||||
access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage';
|
||||
}
|
||||
)[]
|
||||
| undefined;
|
||||
hasProjects?: boolean | undefined;
|
||||
hasWiki?: boolean | undefined;
|
||||
hasIssues?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
topics?: string[] | undefined;
|
||||
requireCommitSigning?: boolean | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
homepage?: string | undefined;
|
||||
access?: string | undefined;
|
||||
deleteBranchOnMerge?: boolean | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
allowRebaseMerge?: boolean | undefined;
|
||||
allowSquashMerge?: boolean | undefined;
|
||||
squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined;
|
||||
squashMergeCommitMessage?:
|
||||
| 'PR_BODY'
|
||||
| 'COMMIT_MESSAGES'
|
||||
| 'BLANK'
|
||||
| undefined;
|
||||
allowMergeCommit?: boolean | undefined;
|
||||
allowAutoMerge?: boolean | undefined;
|
||||
requireCodeOwnerReviews?: boolean | undefined;
|
||||
bypassPullRequestAllowances?:
|
||||
| {
|
||||
users?: string[] | undefined;
|
||||
teams?: string[] | undefined;
|
||||
apps?: string[] | undefined;
|
||||
}
|
||||
| undefined;
|
||||
requiredApprovingReviewCount?: number | undefined;
|
||||
restrictions?:
|
||||
| {
|
||||
users: string[];
|
||||
teams: string[];
|
||||
apps?: string[] | undefined;
|
||||
}
|
||||
| undefined;
|
||||
requiredStatusCheckContexts?: string[] | undefined;
|
||||
requireBranchesToBeUpToDate?: boolean | undefined;
|
||||
requiredConversationResolution?: boolean | undefined;
|
||||
repoVisibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
collaborators?:
|
||||
| (
|
||||
| {
|
||||
user: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
team: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
username: string;
|
||||
access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage';
|
||||
}
|
||||
)[]
|
||||
| undefined;
|
||||
hasProjects?: boolean | undefined;
|
||||
hasWiki?: boolean | undefined;
|
||||
hasIssues?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
topics?: string[] | undefined;
|
||||
requireCommitSigning?: boolean | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createGithubRepoPushAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
protectDefaultBranch?: boolean | undefined;
|
||||
protectEnforceAdmins?: boolean | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
requireCodeOwnerReviews?: boolean | undefined;
|
||||
dismissStaleReviews?: boolean | undefined;
|
||||
bypassPullRequestAllowances?:
|
||||
| {
|
||||
users?: string[];
|
||||
teams?: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requiredApprovingReviewCount?: number | undefined;
|
||||
restrictions?:
|
||||
| {
|
||||
users: string[];
|
||||
teams: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requiredStatusCheckContexts?: string[] | undefined;
|
||||
requireBranchesToBeUpToDate?: boolean | undefined;
|
||||
requiredConversationResolution?: boolean | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
requiredCommitSigning?: boolean | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
protectDefaultBranch?: boolean | undefined;
|
||||
protectEnforceAdmins?: boolean | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
requireCodeOwnerReviews?: boolean | undefined;
|
||||
dismissStaleReviews?: boolean | undefined;
|
||||
bypassPullRequestAllowances?:
|
||||
| {
|
||||
users?: string[];
|
||||
teams?: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requiredApprovingReviewCount?: number | undefined;
|
||||
restrictions?:
|
||||
| {
|
||||
users: string[];
|
||||
teams: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requiredStatusCheckContexts?: string[] | undefined;
|
||||
requireBranchesToBeUpToDate?: boolean | undefined;
|
||||
requiredConversationResolution?: boolean | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
requiredCommitSigning?: boolean | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createGithubWebhookAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
defaultWebhookSecret?: string;
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
webhookUrl: string;
|
||||
webhookSecret?: string | undefined;
|
||||
events?: string[] | undefined;
|
||||
active?: boolean | undefined;
|
||||
contentType?: 'form' | 'json' | undefined;
|
||||
insecureSsl?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
webhookUrl: string;
|
||||
webhookSecret?: string | undefined;
|
||||
events?: string[] | undefined;
|
||||
active?: boolean | undefined;
|
||||
contentType?: 'form' | 'json' | undefined;
|
||||
insecureSsl?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createPublishAzureAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public @deprecated
|
||||
export function createPublishBitbucketAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
enableLFS?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
enableLFS?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createPublishBitbucketCloudAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createPublishBitbucketServerAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
enableLFS?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
enableLFS?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createPublishGerritAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description: string;
|
||||
defaultBranch?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description: string;
|
||||
defaultBranch?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createPublishGerritReviewAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
branch?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
branch?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createPublishGithubAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
githubCredentialsProvider?: GithubCredentialsProvider;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
homepage?: string | undefined;
|
||||
access?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
protectDefaultBranch?: boolean | undefined;
|
||||
protectEnforceAdmins?: boolean | undefined;
|
||||
deleteBranchOnMerge?: boolean | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
allowRebaseMerge?: boolean | undefined;
|
||||
allowSquashMerge?: boolean | undefined;
|
||||
squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined;
|
||||
squashMergeCommitMessage?:
|
||||
| 'PR_BODY'
|
||||
| 'COMMIT_MESSAGES'
|
||||
| 'BLANK'
|
||||
| undefined;
|
||||
allowMergeCommit?: boolean | undefined;
|
||||
allowAutoMerge?: boolean | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
bypassPullRequestAllowances?:
|
||||
| {
|
||||
users?: string[];
|
||||
teams?: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requiredApprovingReviewCount?: number | undefined;
|
||||
restrictions?:
|
||||
| {
|
||||
users: string[];
|
||||
teams: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requireCodeOwnerReviews?: boolean | undefined;
|
||||
dismissStaleReviews?: boolean | undefined;
|
||||
requiredStatusCheckContexts?: string[] | undefined;
|
||||
requireBranchesToBeUpToDate?: boolean | undefined;
|
||||
requiredConversationResolution?: boolean | undefined;
|
||||
repoVisibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
collaborators?:
|
||||
| (
|
||||
| {
|
||||
user: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
team: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
username: string;
|
||||
access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage';
|
||||
}
|
||||
)[]
|
||||
| undefined;
|
||||
hasProjects?: boolean | undefined;
|
||||
hasWiki?: boolean | undefined;
|
||||
hasIssues?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
topics?: string[] | undefined;
|
||||
requiredCommitSigning?: boolean | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
description?: string | undefined;
|
||||
homepage?: string | undefined;
|
||||
access?: string | undefined;
|
||||
defaultBranch?: string | undefined;
|
||||
protectDefaultBranch?: boolean | undefined;
|
||||
protectEnforceAdmins?: boolean | undefined;
|
||||
deleteBranchOnMerge?: boolean | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
allowRebaseMerge?: boolean | undefined;
|
||||
allowSquashMerge?: boolean | undefined;
|
||||
squashMergeCommitTitle?: 'PR_TITLE' | 'COMMIT_OR_PR_TITLE' | undefined;
|
||||
squashMergeCommitMessage?:
|
||||
| 'PR_BODY'
|
||||
| 'COMMIT_MESSAGES'
|
||||
| 'BLANK'
|
||||
| undefined;
|
||||
allowMergeCommit?: boolean | undefined;
|
||||
allowAutoMerge?: boolean | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
bypassPullRequestAllowances?:
|
||||
| {
|
||||
users?: string[];
|
||||
teams?: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requiredApprovingReviewCount?: number | undefined;
|
||||
restrictions?:
|
||||
| {
|
||||
users: string[];
|
||||
teams: string[];
|
||||
apps?: string[];
|
||||
}
|
||||
| undefined;
|
||||
requireCodeOwnerReviews?: boolean | undefined;
|
||||
dismissStaleReviews?: boolean | undefined;
|
||||
requiredStatusCheckContexts?: string[] | undefined;
|
||||
requireBranchesToBeUpToDate?: boolean | undefined;
|
||||
requiredConversationResolution?: boolean | undefined;
|
||||
repoVisibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
collaborators?:
|
||||
| (
|
||||
| {
|
||||
user: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
team: string;
|
||||
access: string;
|
||||
}
|
||||
| {
|
||||
username: string;
|
||||
access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage';
|
||||
}
|
||||
)[]
|
||||
| undefined;
|
||||
hasProjects?: boolean | undefined;
|
||||
hasWiki?: boolean | undefined;
|
||||
hasIssues?: boolean | undefined;
|
||||
token?: string | undefined;
|
||||
topics?: string[] | undefined;
|
||||
requiredCommitSigning?: boolean | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export const createPublishGithubPullRequestAction: ({
|
||||
integrations,
|
||||
githubCredentialsProvider,
|
||||
clientFactory,
|
||||
}: CreateGithubPullRequestActionOptions) => TemplateAction_2<{
|
||||
title: string;
|
||||
branchName: string;
|
||||
description: string;
|
||||
repoUrl: string;
|
||||
draft?: boolean | undefined;
|
||||
targetPath?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
reviewers?: string[] | undefined;
|
||||
teamReviewers?: string[] | undefined;
|
||||
}>;
|
||||
}: CreateGithubPullRequestActionOptions) => TemplateAction_2<
|
||||
{
|
||||
title: string;
|
||||
branchName: string;
|
||||
description: string;
|
||||
repoUrl: string;
|
||||
draft?: boolean | undefined;
|
||||
targetPath?: string | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
reviewers?: string[] | undefined;
|
||||
teamReviewers?: string[] | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createPublishGitlabAction(options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
config: Config;
|
||||
}): TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
setUserAsOwner?: boolean | undefined;
|
||||
topics?: string[] | undefined;
|
||||
}>;
|
||||
}): TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
defaultBranch?: string | undefined;
|
||||
repoVisibility?: 'internal' | 'private' | 'public' | undefined;
|
||||
sourcePath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
gitCommitMessage?: string | undefined;
|
||||
gitAuthorName?: string | undefined;
|
||||
gitAuthorEmail?: string | undefined;
|
||||
setUserAsOwner?: boolean | undefined;
|
||||
topics?: string[] | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export const createPublishGitlabMergeRequestAction: (options: {
|
||||
integrations: ScmIntegrationRegistry;
|
||||
}) => TemplateAction_2<{
|
||||
repoUrl: string;
|
||||
title: string;
|
||||
description: string;
|
||||
branchName: string;
|
||||
sourcePath?: string | undefined;
|
||||
targetPath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
commitAction?: 'update' | 'delete' | 'create' | undefined;
|
||||
projectid?: string | undefined;
|
||||
removeSourceBranch?: boolean | undefined;
|
||||
assignee?: string | undefined;
|
||||
}>;
|
||||
}) => TemplateAction_2<
|
||||
{
|
||||
repoUrl: string;
|
||||
title: string;
|
||||
description: string;
|
||||
branchName: string;
|
||||
sourcePath?: string | undefined;
|
||||
targetPath?: string | undefined;
|
||||
token?: string | undefined;
|
||||
commitAction?: 'update' | 'delete' | 'create' | undefined;
|
||||
projectid?: string | undefined;
|
||||
removeSourceBranch?: boolean | undefined;
|
||||
assignee?: string | undefined;
|
||||
},
|
||||
{}
|
||||
>;
|
||||
|
||||
// @public
|
||||
export function createRouter(options: RouterOptions): Promise<express.Router>;
|
||||
|
||||
// @public @deprecated (undocumented)
|
||||
export const createTemplateAction: <TInput extends JsonObject>(
|
||||
templateAction: TemplateAction_2<TInput>,
|
||||
) => TemplateAction_2<TInput>;
|
||||
export const createTemplateAction: <
|
||||
TParams,
|
||||
TInputSchema extends ZodType<any, ZodTypeDef, any> | Schema = {},
|
||||
>(
|
||||
templateAction: TemplateAction_2<TParams, TInputSchema>,
|
||||
) => TemplateAction_2<TParams, TInputSchema>;
|
||||
|
||||
// @public
|
||||
export type CreateWorkerOptions = {
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
import fs from 'fs-extra';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import * as yaml from 'yaml';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { resolveSafeChildPath } from '@backstage/backend-common';
|
||||
import { z } from 'zod';
|
||||
import { convertZodtoJson } from '../../../tasks';
|
||||
|
||||
const id = 'catalog:write';
|
||||
|
||||
@@ -60,23 +58,24 @@ const examples = [
|
||||
*/
|
||||
|
||||
export function createCatalogWriteAction() {
|
||||
const inputSchema = convertZodtoJson(
|
||||
z.object({
|
||||
filePath: z.string().optional().describe('Defaults to catalog-info.yaml'),
|
||||
entity: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('You can provide the same values used in the Entity schema.'),
|
||||
}),
|
||||
);
|
||||
|
||||
return createTemplateAction<{ filePath?: string; entity: Entity }>({
|
||||
id,
|
||||
return createTemplateAction({
|
||||
id: 'catalog:write',
|
||||
description: 'Writes the catalog-info.yaml for your template',
|
||||
examples,
|
||||
schema: {
|
||||
input: inputSchema,
|
||||
input: z.object({
|
||||
filePath: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Defaults to catalog-info.yaml'),
|
||||
entity: z
|
||||
.object({})
|
||||
.optional()
|
||||
.describe(
|
||||
'You can provide the same values used in the Entity schema.',
|
||||
),
|
||||
}),
|
||||
},
|
||||
examples,
|
||||
supportsDryRun: true,
|
||||
async handler(ctx) {
|
||||
ctx.logStream.write(`Writing catalog-info.yaml`);
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { z } from 'zod';
|
||||
import zodToJsonSchema from 'zod-to-json-schema';
|
||||
import { Schema } from 'jsonschema';
|
||||
|
||||
interface TemplateActionSchema {
|
||||
readonly schema: {
|
||||
input?: Schema;
|
||||
output?: Schema;
|
||||
};
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function convertZodtoJson<
|
||||
TInputSchema extends z.ZodType = z.ZodType<any, any, {}>,
|
||||
TOutputSchema extends z.ZodType = z.ZodType<any, any, {}>,
|
||||
>(
|
||||
zodInputSchema?: TInputSchema,
|
||||
zodOutputSchema?: TOutputSchema,
|
||||
): TemplateActionSchema {
|
||||
return {
|
||||
schema: {
|
||||
input: zodInputSchema ? zodToJsonSchema(zodInputSchema) : undefined,
|
||||
output: zodOutputSchema ? zodToJsonSchema(zodOutputSchema) : undefined,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import { TaskContext } from './types';
|
||||
import { TaskSpec } from '@backstage/plugin-scaffolder-common';
|
||||
import { TaskSecrets } from '@backstage/plugin-scaffolder-node';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import { z } from 'zod';
|
||||
|
||||
// The Stream module is lazy loaded, so make sure it's in the module cache before mocking fs
|
||||
void winston.transports.Stream;
|
||||
@@ -103,6 +104,18 @@ describe('DefaultWorkflowRunner', () => {
|
||||
},
|
||||
});
|
||||
|
||||
actionRegistry.register({
|
||||
id: 'jest-zod-validated-action',
|
||||
description: 'Mock action for testing',
|
||||
supportsDryRun: true,
|
||||
handler: fakeActionHandler,
|
||||
schema: {
|
||||
input: z.object({
|
||||
foo: z.number(),
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
actionRegistry.register({
|
||||
id: 'output-action',
|
||||
description: 'Mock action for testing',
|
||||
@@ -151,6 +164,41 @@ describe('DefaultWorkflowRunner', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if the action has a zod schema and the input does not match', async () => {
|
||||
const task = createMockTaskWithSpec({
|
||||
apiVersion: 'scaffolder.backstage.io/v1beta3',
|
||||
parameters: {},
|
||||
output: {},
|
||||
steps: [
|
||||
{ id: 'test', name: 'name', action: 'jest-zod-validated-action' },
|
||||
],
|
||||
});
|
||||
|
||||
await expect(runner.execute(task)).rejects.toThrow(
|
||||
/Invalid input passed to action jest-validated-action, instance requires property \"foo\"/,
|
||||
);
|
||||
});
|
||||
|
||||
it('should run the action when the zod validation passes', async () => {
|
||||
const task = createMockTaskWithSpec({
|
||||
apiVersion: 'scaffolder.backstage.io/v1beta3',
|
||||
parameters: {},
|
||||
output: {},
|
||||
steps: [
|
||||
{
|
||||
id: 'test',
|
||||
name: 'name',
|
||||
action: 'jest-zod-validated-action',
|
||||
input: { foo: 1 },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await runner.execute(task);
|
||||
|
||||
expect(fakeActionHandler).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should run the action when the validation passes', async () => {
|
||||
const task = createMockTaskWithSpec({
|
||||
apiVersion: 'scaffolder.backstage.io/v1beta3',
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Schema } from 'jsonschema';
|
||||
import { TemplateInfo } from '@backstage/plugin-scaffolder-common';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import { Writable } from 'stream';
|
||||
import { z } from 'zod';
|
||||
|
||||
// @public
|
||||
export type ActionContext<TInput extends JsonObject> = {
|
||||
@@ -32,9 +33,12 @@ export type ActionContext<TInput extends JsonObject> = {
|
||||
};
|
||||
|
||||
// @public
|
||||
export const createTemplateAction: <TInput extends JsonObject>(
|
||||
templateAction: TemplateAction<TInput>,
|
||||
) => TemplateAction<TInput>;
|
||||
export const createTemplateAction: <
|
||||
TParams,
|
||||
TInputSchema extends z.ZodType<any, z.ZodTypeDef, any> | Schema = {},
|
||||
>(
|
||||
templateAction: TemplateAction<TParams, TInputSchema>,
|
||||
) => TemplateAction<TParams, TInputSchema>;
|
||||
|
||||
// @alpha
|
||||
export interface ScaffolderActionsExtensionPoint {
|
||||
@@ -51,7 +55,10 @@ export type TaskSecrets = Record<string, string> & {
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export type TemplateAction<TInput extends JsonObject> = {
|
||||
export type TemplateAction<
|
||||
TParams,
|
||||
TInputSchema extends Schema | z.ZodType = {},
|
||||
> = {
|
||||
id: string;
|
||||
description?: string;
|
||||
examples?: {
|
||||
@@ -60,9 +67,15 @@ export type TemplateAction<TInput extends JsonObject> = {
|
||||
}[];
|
||||
supportsDryRun?: boolean;
|
||||
schema?: {
|
||||
input?: Schema;
|
||||
input?: TInputSchema;
|
||||
output?: Schema;
|
||||
};
|
||||
handler: (ctx: ActionContext<TInput>) => Promise<void>;
|
||||
handler: (
|
||||
ctx: ActionContext<
|
||||
TInputSchema extends z.ZodType<any, any, infer IReturn>
|
||||
? IReturn
|
||||
: TParams
|
||||
>,
|
||||
) => Promise<void>;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
"@backstage/plugin-scaffolder-common": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"jsonschema": "^1.2.6",
|
||||
"winston": "^3.2.1"
|
||||
"winston": "^3.2.1",
|
||||
"zod": "~3.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^"
|
||||
|
||||
@@ -14,17 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { TemplateAction } from './types';
|
||||
import { z } from 'zod';
|
||||
import { Schema } from 'jsonschema';
|
||||
|
||||
/**
|
||||
* This function is used to create new template actions to get type safety.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const createTemplateAction = <TInput extends JsonObject>(
|
||||
templateAction: TemplateAction<TInput>,
|
||||
): TemplateAction<TInput> => {
|
||||
export const createTemplateAction = <
|
||||
TParams,
|
||||
TInputSchema extends Schema | z.ZodType = {},
|
||||
>(
|
||||
templateAction: TemplateAction<TParams, TInputSchema>,
|
||||
): TemplateAction<TParams, TInputSchema> => {
|
||||
// TODO(blam): Can add some more validation here to validate the action later on
|
||||
return templateAction;
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Schema } from 'jsonschema';
|
||||
import { TaskSecrets } from '../tasks/types';
|
||||
import { TemplateInfo } from '@backstage/plugin-scaffolder-common';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
|
||||
import { z } from 'zod';
|
||||
/**
|
||||
* ActionContext is passed into scaffolder actions.
|
||||
* @public
|
||||
@@ -63,14 +63,23 @@ export type ActionContext<TInput extends JsonObject> = {
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type TemplateAction<TInput extends JsonObject> = {
|
||||
export type TemplateAction<
|
||||
TParams,
|
||||
TInputSchema extends Schema | z.ZodType = {},
|
||||
> = {
|
||||
id: string;
|
||||
description?: string;
|
||||
examples?: { description: string; example: string }[];
|
||||
supportsDryRun?: boolean;
|
||||
schema?: {
|
||||
input?: Schema;
|
||||
input?: TInputSchema;
|
||||
output?: Schema;
|
||||
};
|
||||
handler: (ctx: ActionContext<TInput>) => Promise<void>;
|
||||
handler: (
|
||||
ctx: ActionContext<
|
||||
TInputSchema extends z.ZodType<any, any, infer IReturn>
|
||||
? IReturn
|
||||
: TParams
|
||||
>,
|
||||
) => Promise<void>;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user