Merge pull request #27771 from solimant/23819_scaffolder_openapi

Move Scaffolder API to OpenAPI
This commit is contained in:
Ben Lambert
2025-07-29 14:36:47 +02:00
committed by GitHub
147 changed files with 7540 additions and 992 deletions
+9
View File
@@ -0,0 +1,9 @@
---
'@backstage/plugin-scaffolder-react': minor
---
**DEPRECATION**: The following types have been deprecated from this package and moved into `@backstage/plugin-scaffolder-common` and should be imported from there instead.
`Action`, `ListActionsResponse`, `LogEvent`, `ScaffolderApi`, `ScaffolderDryRunOptions`, `ScaffolderDryRunResponse`, `ScaffolderGetIntegrationsListOptions`, `ScaffolderGetIntegrationsListResponse`,
`ScaffolderOutputLink`, `ScaffolderOutputText`, `ScaffolderScaffoldOptions`, `ScaffolderScaffoldResponse`, `ScaffolderStreamLogsOptions`, `ScaffolderTask`, `ScaffolderTaskOutput`, `ScaffolderTaskStatus`,
`ScaffolderUsageExample`, `TemplateFilter`, `TemplateGlobalFunction`, `TemplateGlobalValue`, `TemplateParameterSchema`.
+10
View File
@@ -0,0 +1,10 @@
---
'@backstage/backend-openapi-utils': minor
'@backstage/plugin-scaffolder-backend': minor
'@backstage/plugin-scaffolder-common': minor
'@backstage/plugin-scaffolder-react': minor
'@backstage/plugin-scaffolder-node': minor
'@backstage/plugin-scaffolder': minor
---
Move Scaffolder API to OpenAPI
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/repo-tools': patch
---
Added `stringEnums` to `mustache` templates
+1 -1
View File
@@ -274,7 +274,7 @@ type EndpointMap = Record<
{
query?: object;
body?: object;
response?: object | void;
response?: object | string | void;
path?: object;
}
>;
@@ -21,7 +21,12 @@ import { PathTemplate, ValueOf } from './common';
*/
export type EndpointMap = Record<
string,
{ query?: object; body?: object; response?: object | void; path?: object }
{
query?: object;
body?: object;
response?: object | string | void;
path?: object;
}
>;
// OpenAPI generator doesn't emit regular lowercase 'delete'.
@@ -17,4 +17,4 @@ export enum {{classname}} {
* @public
*/
export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
{{/stringEnums}}
@@ -17,4 +17,4 @@ export enum {{classname}} {
* @public
*/
export type {{classname}} = {{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}} | {{/-last}}{{/enumVars}}{{/allowableValues}};
{{/stringEnums}}
+3 -1
View File
@@ -54,6 +54,7 @@
"build": "backstage-cli package build",
"build:assets": "node scripts/build-nunjucks.js",
"clean": "backstage-cli package clean",
"generate": "backstage-repo-tools package schema openapi generate --server --client-package plugins/scaffolder-common",
"lint": "backstage-cli package lint",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack",
@@ -62,6 +63,7 @@
},
"dependencies": {
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-openapi-utils": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/catalog-model": "workspace:^",
"@backstage/config": "workspace:^",
@@ -89,7 +91,6 @@
"@types/luxon": "^3.0.0",
"concat-stream": "^2.0.0",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"fs-extra": "^11.2.0",
"globby": "^11.0.0",
"isbinaryfile": "^5.0.0",
@@ -119,6 +120,7 @@
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^",
"@backstage/repo-tools": "workspace:^",
"@types/express": "^4.17.6",
"@types/fs-extra": "^11.0.0",
"@types/nunjucks": "^3.1.4",
@@ -737,9 +737,10 @@ describe('scaffolderPlugin', () => {
});
// Retry the task by ID
response = await request(server).post(
`/api/scaffolder/v2/tasks/${taskId}/retry`,
);
response = await request(server)
.post(`/api/scaffolder/v2/tasks/${taskId}/retry`)
.send({});
expect(response.status).toBe(201);
expect(response.body).toMatchObject({ id: taskId });
@@ -22,7 +22,11 @@ import {
import type { UserEntity } from '@backstage/catalog-model';
import { ScmIntegrations } from '@backstage/integration';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
import { TaskSpec, TemplateInfo } from '@backstage/plugin-scaffolder-common';
import {
ScaffolderTaskStatus,
TaskSpec,
TemplateInfo,
} from '@backstage/plugin-scaffolder-common';
import {
createTemplateAction,
deserializeDirectoryContents,
@@ -54,7 +58,13 @@ interface DryRunInput {
}
interface DryRunResult {
log: Array<{ body: JsonObject }>;
log: Array<{
body: {
message: string;
stepId?: string;
status?: ScaffolderTaskStatus;
};
}>;
directoryContents: SerializedFile[];
output: JsonObject;
}
@@ -106,7 +116,13 @@ export function createDryRunner(options: TemplateTesterCreateOptions) {
const contentsPath = path.dirname(basePath);
const dryRunId = uuid();
const log = new Array<{ body: JsonObject }>();
const log = new Array<{
body: {
message: string;
stepId?: string;
status?: ScaffolderTaskStatus;
};
}>();
try {
await deserializeDirectoryContents(contentsPath, input.directoryContents);
@@ -607,7 +607,7 @@ export class DatabaseTaskStore implements TaskStore {
const events = rawEvents.map(event => {
try {
const body = JSON.parse(event.body) as JsonObject;
const body = JSON.parse(event.body) as SerializedTaskEvent['body'];
return {
id: Number(event.id),
isTaskRecoverable,
@@ -28,7 +28,7 @@ export const trimEventsTillLastRecovery = (
if (recoveredEventInd >= 0) {
const ind = events.length - recoveredEventInd - 1;
const { recoverStrategy } = events[ind].body as {
recoverStrategy: TaskRecoverStrategy;
recoverStrategy?: TaskRecoverStrategy;
};
if (recoverStrategy === 'startOver') {
return {
@@ -0,0 +1,887 @@
openapi: 3.0.3
info:
title: scaffolder
version: '1'
description: The Backstage backend plugin that helps you create new things
license:
name: Apache-2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
contact: {}
servers:
- url: /
components:
examples: {}
headers: {}
parameters:
createdBy:
name: createdBy
in: query
description: Created by
required: false
allowReserved: true
schema:
type: array
items:
type: string
eventsAfter:
name: after
in: query
description: Offset event ID to stream events after.
required: false
allowReserved: true
schema:
type: integer
kind:
name: kind
in: path
required: true
allowReserved: true
schema:
type: string
limit:
name: limit
in: query
description: Number of records to return in the response.
required: false
allowReserved: true
schema:
type: integer
minimum: 0
namespace:
name: namespace
in: path
required: true
allowReserved: true
schema:
type: string
name:
name: name
in: path
required: true
allowReserved: true
schema:
type: string
offset:
name: offset
in: query
description: Number of records to skip in the query page.
required: false
allowReserved: true
schema:
type: integer
minimum: 0
order:
name: order
in: query
description: Order
required: false
allowReserved: true
schema:
type: array
items:
type: string
status:
name: status
in: query
description: Status
required: false
allowReserved: true
schema:
type: array
items:
type: string
taskId:
name: taskId
in: path
required: true
allowReserved: true
schema:
type: string
requestBodies: {}
responses:
ErrorResponse:
description: An error response from the backend.
content:
application/json; charset=utf-8:
schema:
$ref: '#/components/schemas/Error'
schemas:
Action:
type: object
properties:
id:
type: string
description:
type: string
"'examples'":
type: array
items:
$ref: '#/components/schemas/ActionExample'
schema:
type: object
properties:
input:
$ref: '#/components/schemas/JsonObject'
output:
$ref: '#/components/schemas/JsonObject'
required:
- id
description: The response shape for a single action in the `listActions` call to the `scaffolder-backend`
ActionExample:
type: object
properties:
description:
type: string
example:
type: string
required:
- description
- example
description: A single action example
DryRunResult:
type: object
properties:
log:
type: array
items:
type: object
properties:
body:
allOf:
- $ref: '#/components/schemas/JsonObject'
- type: object
properties:
message:
type: string
status:
$ref: '#/components/schemas/TaskStatus'
stepId:
type: string
required:
- message
required:
- body
directoryContents:
type: array
items:
$ref: '#/components/schemas/SerializedFile'
output:
$ref: '#/components/schemas/JsonObject'
required:
- log
- directoryContents
- output
Error:
type: object
properties:
error:
type: object
properties:
name:
type: string
message:
type: string
stack:
type: string
code:
type: string
required:
- name
- message
request:
type: object
properties:
method:
type: string
url:
type: string
required:
- method
- url
response:
type: object
properties:
statusCode:
type: number
required:
- statusCode
required:
- error
- response
additionalProperties: {}
JsonArray:
type: array
items:
$ref: '#/components/schemas/JsonValue'
description: A type representing all allowed JSON array values.
JsonObject:
type: object
properties: {}
description: A type representing all allowed JSON object values.
additionalProperties: {}
JsonPrimitive:
oneOf:
- type: boolean
- type: number
- type: string
- type: object
nullable: true
description: A type representing all allowed JSON primitive values.
JsonValue:
oneOf:
- $ref: '#/components/schemas/JsonObject'
- $ref: '#/components/schemas/JsonArray'
- $ref: '#/components/schemas/JsonPrimitive'
description: A type representing all allowed JSON values.
ListActionsResponse:
type: array
items:
$ref: '#/components/schemas/Action'
description: The response shape for the `listActions` call to the `scaffolder-backend`
ListTasksResponse:
type: object
properties:
tasks:
type: array
items:
$ref: '#/components/schemas/SerializedTask'
totalTasks:
type: number
required:
- tasks
description: The response shape for the `listTasks` call to the `scaffolder-backend`
ListTemplatingExtensionsResponse:
type: object
properties:
filters:
type: object
additionalProperties:
$ref: '#/components/schemas/TemplateFilter'
globals:
type: object
properties:
functions:
type: object
additionalProperties:
$ref: '#/components/schemas/TemplateGlobalFunction'
values:
type: object
additionalProperties:
$ref: '#/components/schemas/TemplateGlobalValue'
required:
- functions
- values
required:
- filters
- globals
description: The response shape for the `listTemplatingExtensions` call to the `scaffolder-backend`
ScaffolderScaffoldOptions:
type: object
properties:
templateRef:
type: string
values:
type: object
additionalProperties: {}
secrets:
type: object
additionalProperties:
type: string
required:
- templateRef
- values
description: The input options to the `scaffold` method of the `ScaffolderClient`.
ScaffolderUsageExample:
type: object
properties:
description:
type: string
example:
type: string
notes:
type: string
required:
- example
description: A single scaffolder usage example
SerializedFile:
type: object
properties:
path:
type: string
content:
type: string
executable:
type: boolean
symlink:
type: boolean
required:
- path
- content
SerializedTaskEvent:
type: object
properties:
id:
type: integer
isTaskRecoverable:
type: boolean
taskId:
type: string
body:
allOf:
- $ref: '#/components/schemas/JsonObject'
- type: object
properties:
message:
type: string
status:
$ref: '#/components/schemas/TaskStatus'
stepId:
type: string
required:
- message
type:
$ref: '#/components/schemas/TaskEventType'
createdAt:
type: string
required:
- id
- taskId
- body
- type
- createdAt
description: SerializedTaskEvent
SerializedTask:
type: object
properties:
id:
type: string
spec:
type: object
status:
$ref: '#/components/schemas/TaskStatus'
createdAt:
type: string
lastHeartbeatAt:
type: string
createdBy:
type: string
secrets:
$ref: '#/components/schemas/TaskSecrets'
state:
$ref: '#/components/schemas/JsonObject'
required:
- id
- spec
- status
- createdAt
description: SerializedTask
TaskEventType:
type: string
description: TaskEventType
enum:
- cancelled
- completion
- log
- recovered
TaskSecrets:
allOf:
- type: object
additionalProperties:
type: string
- type: object
properties:
backstageToken:
type: string
description: TaskSecrets
TaskStatus:
type: string
enum:
- cancelled
- completed
- failed
- open
- processing
- skipped
description: The status of each step of the Task
TemplateGlobalFunction:
type: object
properties:
description:
type: string
schema:
type: object
properties:
arguments:
type: array
items:
$ref: '#/components/schemas/JsonObject'
output:
$ref: '#/components/schemas/JsonObject'
"'examples'":
type: array
items:
$ref: '#/components/schemas/ScaffolderUsageExample'
description: The response shape for a single global function in the `listTemplatingExtensions` call to the `scaffolder-backend`
TemplateGlobalValue:
type: object
properties:
description:
type: string
value:
type: object
nullable: true
required:
- value
description: The response shape for a single global value in the `listTemplatingExtensions` call to the `scaffolder-backend`
TemplateFilter:
type: object
properties:
description:
type: string
schema:
type: object
properties:
input:
$ref: '#/components/schemas/JsonObject'
arguments:
type: array
items:
$ref: '#/components/schemas/JsonObject'
output:
$ref: '#/components/schemas/JsonObject'
"'examples'":
type: array
items:
$ref: '#/components/schemas/ScaffolderUsageExample'
description: The response shape for a single filter in the `listTemplatingExtensions` call to the `scaffolder-backend`
TemplateParameterSchema:
type: object
properties:
title:
type: string
description:
type: string
steps:
type: array
items:
type: object
properties:
title:
type: string
description:
type: string
schema:
type: object
required:
- title
- schema
required:
- title
- steps
description: |-
The shape of each entry of parameters which gets rendered
as a separate step in the wizard input
additionalProperties: {}
ValidationError:
type: object
properties:
path:
type: array
items:
oneOf:
- type: string
- type: integer
property:
type: string
message:
type: string
instance:
type: object
name:
type: string
argument:
oneOf:
- type: boolean
- type: number
- type: object
- type: string
stack:
type: string
required:
- path
- property
- message
- schema
- instance
- name
- argument
- stack
additionalProperties: {}
securitySchemes:
JWT:
type: http
scheme: bearer
bearerFormat: JWT
paths:
/v2/templates/{namespace}/{kind}/{name}/parameter-schema:
get:
operationId: GetTemplateParameterSchema
description: Get template parameter schema.
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/TemplateParameterSchema'
'400':
$ref: '#/components/responses/ErrorResponse'
default:
$ref: '#/components/responses/ErrorResponse'
security:
- {}
- JWT: []
parameters:
- $ref: '#/components/parameters/namespace'
- $ref: '#/components/parameters/kind'
- $ref: '#/components/parameters/name'
/v2/actions:
get:
operationId: ListActions
description: Returns a list of all installed actions.
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/ListActionsResponse'
security:
- {}
- JWT: []
parameters: []
/v2/tasks:
get:
operationId: ListTasks
description: Returns a list of tasks, filtering by ownership and/or status if given.
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/ListTasksResponse'
security:
- {}
- JWT: []
parameters:
- $ref: '#/components/parameters/createdBy'
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/offset'
- $ref: '#/components/parameters/order'
- $ref: '#/components/parameters/status'
post:
operationId: Scaffold
description: |-
Executes the scaffolding of a component, given a template and its
parameter values.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ScaffolderScaffoldOptions'
responses:
'201':
description: Created
content:
application/json:
schema:
type: object
properties:
id:
type: string
required:
- id
'400':
description: Validation errors.
content:
application/json:
schema:
type: object
properties:
errors:
type: array
items:
$ref: '#/components/schemas/ValidationError'
required:
- errors
security:
- {}
- JWT: []
parameters: []
/v2/tasks/{taskId}:
get:
operationId: GetTask
description: Get a task by ID.
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/SerializedTask'
'403':
$ref: '#/components/responses/ErrorResponse'
security:
- {}
- JWT: []
parameters:
- $ref: '#/components/parameters/taskId'
/v2/tasks/{taskId}/cancel:
post:
operationId: CancelTask
description: Sends a signal to a task broker to cancel the running task by taskId.
responses:
'200':
description: Ok
content:
application/json:
schema:
type: object
properties:
status:
$ref: '#/components/schemas/TaskStatus'
security:
- {}
- JWT: []
parameters:
- $ref: '#/components/parameters/taskId'
/v2/tasks/{taskId}/retry:
post:
operationId: Retry
description: Starts the task again from the point where it failed.
requestBody:
# this should probably be marked as required, but for legacy reasons we're not.
required: false
content:
application/json:
schema:
type: object
properties:
secrets:
type: object
additionalProperties:
type: string
responses:
'201':
description: Ok
content:
application/json:
schema:
type: object
properties:
id:
type: string
required:
- id
security:
- {}
- JWT: []
parameters:
- $ref: '#/components/parameters/taskId'
/v2/tasks/{taskId}/events:
get:
operationId: StreamLogsPolling
description: Get events for a task by ID.
responses:
'200':
description: Ok
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SerializedTaskEvent'
'403':
$ref: '#/components/responses/ErrorResponse'
parameters:
- $ref: '#/components/parameters/eventsAfter'
- $ref: '#/components/parameters/taskId'
/v2/dry-run:
post:
operationId: DryRun
description: Perform a dry-run of a template
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
template:
type: object
values:
$ref: '#/components/schemas/JsonObject'
secrets:
type: object
additionalProperties:
type: string
directoryContents:
type: array
items:
type: object
properties:
path:
type: string
base64Content:
type: string
required:
- template
- values
- directoryContents
responses:
'200':
description: Ok
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/DryRunResult'
- type: object
properties:
steps:
type: array
items:
type: object
properties:
id:
type: string
name:
type: string
action:
type: string
required:
- id
- name
- action
additionalProperties: {}
directoryContents:
type: array
items:
type: object
properties:
path:
type: string
executable:
type: boolean
base64Content:
type: string
required:
- path
- base64Content
required:
- steps
'400':
description: Validation errors.
content:
application/json:
schema:
type: object
properties:
errors:
type: array
items:
$ref: '#/components/schemas/ValidationError'
required:
- errors
parameters: []
/v2/autocomplete/{provider}/{resource}:
post:
operationId: Autocomplete
description: Perform an autocomplete for the given provider and resource.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
context:
type: object
additionalProperties:
type: string
token:
type: string
required:
- context
- token
responses:
'200':
description: Ok
content:
application/json:
schema:
type: object
properties:
results:
type: array
items:
type: object
properties:
title:
type: string
id:
type: string
required:
- id
required:
- results
'400':
description: Unsupported provider.
content:
application/json:
schema:
type: object
properties:
message:
type: string
name:
type: string
parameters:
- in: path
name: provider
required: true
allowReserved: true
schema:
type: string
- in: path
name: resource
required: true
allowReserved: true
schema:
type: string
/v2/templating-extensions:
get:
operationId: ListTemplatingExtensions
description: Returns a structure describing the available templating extensions.
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/ListTemplatingExtensionsResponse'
security:
- {}
- JWT: []
parameters: []
@@ -0,0 +1,163 @@
/*
* Copyright 2025 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.
*/
//
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { Action } from '../models/Action.model';
import { Autocomplete200Response } from '../models/Autocomplete200Response.model';
import { Autocomplete400Response } from '../models/Autocomplete400Response.model';
import { AutocompleteRequest } from '../models/AutocompleteRequest.model';
import { CancelTask200Response } from '../models/CancelTask200Response.model';
import { DryRun200Response } from '../models/DryRun200Response.model';
import { DryRunRequest } from '../models/DryRunRequest.model';
import { ListTasksResponse } from '../models/ListTasksResponse.model';
import { ListTemplatingExtensionsResponse } from '../models/ListTemplatingExtensionsResponse.model';
import { RetryRequest } from '../models/RetryRequest.model';
import { Scaffold201Response } from '../models/Scaffold201Response.model';
import { Scaffold400Response } from '../models/Scaffold400Response.model';
import { ScaffolderScaffoldOptions } from '../models/ScaffolderScaffoldOptions.model';
import { SerializedTask } from '../models/SerializedTask.model';
import { SerializedTaskEvent } from '../models/SerializedTaskEvent.model';
import { TemplateParameterSchema } from '../models/TemplateParameterSchema.model';
/**
* @public
*/
export type Autocomplete = {
path: {
provider: string;
resource: string;
};
body: AutocompleteRequest;
response: Autocomplete200Response | Autocomplete400Response;
};
/**
* @public
*/
export type CancelTask = {
path: {
taskId: string;
};
response: CancelTask200Response;
};
/**
* @public
*/
export type DryRun = {
body: DryRunRequest;
response: DryRun200Response | Scaffold400Response;
};
/**
* @public
*/
export type GetTask = {
path: {
taskId: string;
};
response: SerializedTask | Error;
};
/**
* @public
*/
export type GetTemplateParameterSchema = {
path: {
namespace: string;
kind: string;
name: string;
};
response: TemplateParameterSchema | Error | Error;
};
/**
* @public
*/
export type ListActions = {
response: Array<Action>;
};
/**
* @public
*/
export type ListTasks = {
query: {
createdBy?: Array<string>;
limit?: number;
offset?: number;
order?: Array<string>;
status?: Array<string>;
};
response: ListTasksResponse;
};
/**
* @public
*/
export type ListTemplatingExtensions = {
response: ListTemplatingExtensionsResponse;
};
/**
* @public
*/
export type Retry = {
path: {
taskId: string;
};
body: RetryRequest;
response: Scaffold201Response;
};
/**
* @public
*/
export type Scaffold = {
body: ScaffolderScaffoldOptions;
response: Scaffold201Response | Scaffold400Response;
};
/**
* @public
*/
export type StreamLogsPolling = {
path: {
taskId: string;
};
query: {
after?: number;
};
response: Array<SerializedTaskEvent> | Error;
};
export type EndpointMap = {
'#post|/v2/autocomplete/{provider}/{resource}': Autocomplete;
'#post|/v2/tasks/{taskId}/cancel': CancelTask;
'#post|/v2/dry-run': DryRun;
'#get|/v2/tasks/{taskId}': GetTask;
'#get|/v2/templates/{namespace}/{kind}/{name}/parameter-schema': GetTemplateParameterSchema;
'#get|/v2/actions': ListActions;
'#get|/v2/tasks': ListTasks;
'#get|/v2/templating-extensions': ListTemplatingExtensions;
'#post|/v2/tasks/{taskId}/retry': Retry;
'#post|/v2/tasks': Scaffold;
'#get|/v2/tasks/{taskId}/events': StreamLogsPolling;
};
@@ -0,0 +1,23 @@
/*
* Copyright 2025 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.
*/
//
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
export * from './Api.server';
@@ -0,0 +1,18 @@
/*
* Copyright 2025 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.
*/
export * from './apis';
export * from './router';
@@ -0,0 +1,32 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ActionExample } from '../models/ActionExample.model';
import { ActionSchema } from '../models/ActionSchema.model';
/**
* The response shape for a single action in the `listActions` call to the `scaffolder-backend`
* @public
*/
export interface Action {
id: string;
description?: string;
examples?: Array<ActionExample>;
schema?: ActionSchema;
}
@@ -0,0 +1,28 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* A single action example
* @public
*/
export interface ActionExample {
description: string;
example: string;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface ActionSchema {
/**
* A type representing all allowed JSON object values.
*/
input?: { [key: string]: any };
/**
* A type representing all allowed JSON object values.
*/
output?: { [key: string]: any };
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { Autocomplete200ResponseResultsInner } from '../models/Autocomplete200ResponseResultsInner.model';
/**
* @public
*/
export interface Autocomplete200Response {
results: Array<Autocomplete200ResponseResultsInner>;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface Autocomplete200ResponseResultsInner {
title?: string;
id: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface Autocomplete400Response {
message?: string;
name?: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface AutocompleteRequest {
context: { [key: string]: string };
token: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TaskStatus } from '../models/TaskStatus.model';
/**
* @public
*/
export interface CancelTask200Response {
status?: TaskStatus;
}
@@ -0,0 +1,35 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRun200ResponseAllOfDirectoryContentsInner } from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model';
import { DryRun200ResponseAllOfStepsInner } from '../models/DryRun200ResponseAllOfStepsInner.model';
import { DryRunResultLogInner } from '../models/DryRunResultLogInner.model';
/**
* @public
*/
export interface DryRun200Response {
log: Array<DryRunResultLogInner>;
directoryContents: Array<DryRun200ResponseAllOfDirectoryContentsInner>;
/**
* A type representing all allowed JSON object values.
*/
output: { [key: string]: any };
steps: Array<DryRun200ResponseAllOfStepsInner>;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRun200ResponseAllOfDirectoryContentsInner } from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model';
import { DryRun200ResponseAllOfStepsInner } from '../models/DryRun200ResponseAllOfStepsInner.model';
/**
* @public
*/
export interface DryRun200ResponseAllOf {
steps: Array<DryRun200ResponseAllOfStepsInner>;
directoryContents?: Array<DryRun200ResponseAllOfDirectoryContentsInner>;
}
@@ -0,0 +1,28 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface DryRun200ResponseAllOfDirectoryContentsInner {
path: string;
executable?: boolean;
base64Content: string;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface DryRun200ResponseAllOfStepsInner {
[key: string]: any;
id: string;
name: string;
action: string;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRunRequestDirectoryContentsInner } from '../models/DryRunRequestDirectoryContentsInner.model';
/**
* @public
*/
export interface DryRunRequest {
template: any;
/**
* A type representing all allowed JSON object values.
*/
values: { [key: string]: any };
secrets?: { [key: string]: string };
directoryContents: Array<DryRunRequestDirectoryContentsInner>;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface DryRunRequestDirectoryContentsInner {
path?: string;
base64Content?: string;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRunResultLogInner } from '../models/DryRunResultLogInner.model';
import { SerializedFile } from '../models/SerializedFile.model';
/**
* @public
*/
export interface DryRunResult {
log: Array<DryRunResultLogInner>;
directoryContents: Array<SerializedFile>;
/**
* A type representing all allowed JSON object values.
*/
output: { [key: string]: any };
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRunResultLogInnerBody } from '../models/DryRunResultLogInnerBody.model';
/**
* @public
*/
export interface DryRunResultLogInner {
body: DryRunResultLogInnerBody;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TaskStatus } from '../models/TaskStatus.model';
/**
* @public
*/
export interface DryRunResultLogInnerBody {
message: string;
status?: TaskStatus;
stepId?: string;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TaskStatus } from '../models/TaskStatus.model';
/**
* @public
*/
export interface DryRunResultLogInnerBodyAllOf {
message: string;
status?: TaskStatus;
stepId?: string;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface ErrorError {
name: string;
message: string;
stack?: string;
code?: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface ErrorRequest {
method: string;
url: string;
}
@@ -0,0 +1,26 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface ErrorResponse {
statusCode: number;
}
@@ -0,0 +1,25 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* A type representing all allowed JSON primitive values.
* @public
*/
export type JsonPrimitive = any | boolean | number | string;
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { JsonPrimitive } from '../models/JsonPrimitive.model';
/**
* A type representing all allowed JSON values.
* @public
*/
export type JsonValue =
| Array<JsonValue>
| JsonPrimitive
| { [key: string]: any };
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { SerializedTask } from '../models/SerializedTask.model';
/**
* The response shape for the `listTasks` call to the `scaffolder-backend`
* @public
*/
export interface ListTasksResponse {
tasks: Array<SerializedTask>;
totalTasks?: number;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ListTemplatingExtensionsResponseGlobals } from '../models/ListTemplatingExtensionsResponseGlobals.model';
import { TemplateFilter } from '../models/TemplateFilter.model';
/**
* The response shape for the `listTemplatingExtensions` call to the `scaffolder-backend`
* @public
*/
export interface ListTemplatingExtensionsResponse {
filters: { [key: string]: TemplateFilter };
globals: ListTemplatingExtensionsResponseGlobals;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TemplateGlobalFunction } from '../models/TemplateGlobalFunction.model';
import { TemplateGlobalValue } from '../models/TemplateGlobalValue.model';
/**
* @public
*/
export interface ListTemplatingExtensionsResponseGlobals {
functions: { [key: string]: TemplateGlobalFunction };
values: { [key: string]: TemplateGlobalValue };
}
@@ -0,0 +1,33 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ErrorError } from '../models/ErrorError.model';
import { ErrorRequest } from '../models/ErrorRequest.model';
import { ErrorResponse } from '../models/ErrorResponse.model';
/**
* @public
*/
export interface ModelError {
[key: string]: any;
error: ErrorError;
request?: ErrorRequest;
response: ErrorResponse;
}
@@ -0,0 +1,26 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface RetryRequest {
secrets?: { [key: string]: string };
}
@@ -0,0 +1,26 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface Scaffold201Response {
id: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ValidationError } from '../models/ValidationError.model';
/**
* @public
*/
export interface Scaffold400Response {
errors: Array<ValidationError>;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* The input options to the `scaffold` method of the `ScaffolderClient`.
* @public
*/
export interface ScaffolderScaffoldOptions {
templateRef: string;
values: { [key: string]: any };
secrets?: { [key: string]: string };
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* A single scaffolder usage example
* @public
*/
export interface ScaffolderUsageExample {
description?: string;
example: string;
notes?: string;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface SerializedFile {
path: string;
content: string;
executable?: boolean;
symlink?: boolean;
}
@@ -0,0 +1,39 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TaskSecrets } from '../models/TaskSecrets.model';
import { TaskStatus } from '../models/TaskStatus.model';
/**
* SerializedTask
* @public
*/
export interface SerializedTask {
id: string;
spec: any;
status: TaskStatus;
createdAt: string;
lastHeartbeatAt?: string;
createdBy?: string;
secrets?: TaskSecrets;
/**
* A type representing all allowed JSON object values.
*/
state?: { [key: string]: any };
}
@@ -0,0 +1,34 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRunResultLogInnerBody } from '../models/DryRunResultLogInnerBody.model';
import { TaskEventType } from '../models/TaskEventType.model';
/**
* SerializedTaskEvent
* @public
*/
export interface SerializedTaskEvent {
id: number;
isTaskRecoverable?: boolean;
taskId: string;
body: DryRunResultLogInnerBody;
type: TaskEventType;
createdAt: string;
}
@@ -0,0 +1,24 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export type TaskEventType = 'cancelled' | 'completion' | 'log' | 'recovered';
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* TaskSecrets
* @public
*/
export interface TaskSecrets {
backstageToken?: string;
}
@@ -0,0 +1,26 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface TaskSecretsAllOf {
backstageToken?: string;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export type TaskStatus =
| 'cancelled'
| 'completed'
| 'failed'
| 'open'
| 'processing'
| 'skipped';
@@ -0,0 +1,31 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ScaffolderUsageExample } from '../models/ScaffolderUsageExample.model';
import { TemplateFilterSchema } from '../models/TemplateFilterSchema.model';
/**
* The response shape for a single filter in the `listTemplatingExtensions` call to the `scaffolder-backend`
* @public
*/
export interface TemplateFilter {
description?: string;
schema?: TemplateFilterSchema;
examples?: Array<ScaffolderUsageExample>;
}
@@ -0,0 +1,34 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface TemplateFilterSchema {
/**
* A type representing all allowed JSON object values.
*/
input?: { [key: string]: any };
arguments?: Array<{ [key: string]: any }>;
/**
* A type representing all allowed JSON object values.
*/
output?: { [key: string]: any };
}
@@ -0,0 +1,31 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ScaffolderUsageExample } from '../models/ScaffolderUsageExample.model';
import { TemplateGlobalFunctionSchema } from '../models/TemplateGlobalFunctionSchema.model';
/**
* The response shape for a single global function in the `listTemplatingExtensions` call to the `scaffolder-backend`
* @public
*/
export interface TemplateGlobalFunction {
description?: string;
schema?: TemplateGlobalFunctionSchema;
examples?: Array<ScaffolderUsageExample>;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface TemplateGlobalFunctionSchema {
arguments?: Array<{ [key: string]: any }>;
/**
* A type representing all allowed JSON object values.
*/
output?: { [key: string]: any };
}
@@ -0,0 +1,28 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* The response shape for a single global value in the `listTemplatingExtensions` call to the `scaffolder-backend`
* @public
*/
export interface TemplateGlobalValue {
description?: string;
value: any | null;
}
@@ -0,0 +1,32 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TemplateParameterSchemaStepsInner } from '../models/TemplateParameterSchemaStepsInner.model';
/**
* The shape of each entry of parameters which gets rendered as a separate step in the wizard input
* @public
*/
export interface TemplateParameterSchema {
[key: string]: any;
title: string;
description?: string;
steps: Array<TemplateParameterSchemaStepsInner>;
}
@@ -0,0 +1,28 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface TemplateParameterSchemaStepsInner {
title: string;
description?: string;
schema: any;
}
@@ -0,0 +1,36 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ValidationErrorArgument } from '../models/ValidationErrorArgument.model';
import { ValidationErrorPathInner } from '../models/ValidationErrorPathInner.model';
/**
* @public
*/
export interface ValidationError {
[key: string]: any;
path: Array<ValidationErrorPathInner>;
property: string;
message: string;
instance: any;
name: string;
argument: ValidationErrorArgument;
stack: string;
}
@@ -0,0 +1,24 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export type ValidationErrorArgument = any | boolean | number | string;
@@ -0,0 +1,24 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export type ValidationErrorPathInner = number | string;
@@ -0,0 +1,65 @@
/*
* Copyright 2025 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.
*/
export * from '../models/Action.model';
export * from '../models/ActionExample.model';
export * from '../models/ActionSchema.model';
export * from '../models/Autocomplete200Response.model';
export * from '../models/Autocomplete200ResponseResultsInner.model';
export * from '../models/Autocomplete400Response.model';
export * from '../models/AutocompleteRequest.model';
export * from '../models/CancelTask200Response.model';
export * from '../models/DryRun200Response.model';
export * from '../models/DryRun200ResponseAllOf.model';
export * from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model';
export * from '../models/DryRun200ResponseAllOfStepsInner.model';
export * from '../models/DryRunRequest.model';
export * from '../models/DryRunRequestDirectoryContentsInner.model';
export * from '../models/DryRunResult.model';
export * from '../models/DryRunResultLogInner.model';
export * from '../models/DryRunResultLogInnerBody.model';
export * from '../models/DryRunResultLogInnerBodyAllOf.model';
export * from '../models/ErrorError.model';
export * from '../models/ErrorRequest.model';
export * from '../models/ErrorResponse.model';
export * from '../models/JsonPrimitive.model';
export * from '../models/JsonValue.model';
export * from '../models/ListTasksResponse.model';
export * from '../models/ListTemplatingExtensionsResponse.model';
export * from '../models/ListTemplatingExtensionsResponseGlobals.model';
export * from '../models/ModelError.model';
export * from '../models/RetryRequest.model';
export * from '../models/Scaffold201Response.model';
export * from '../models/Scaffold400Response.model';
export * from '../models/ScaffolderScaffoldOptions.model';
export * from '../models/ScaffolderUsageExample.model';
export * from '../models/SerializedFile.model';
export * from '../models/SerializedTask.model';
export * from '../models/SerializedTaskEvent.model';
export * from '../models/TaskEventType.model';
export * from '../models/TaskSecrets.model';
export * from '../models/TaskSecretsAllOf.model';
export * from '../models/TaskStatus.model';
export * from '../models/TemplateFilter.model';
export * from '../models/TemplateFilterSchema.model';
export * from '../models/TemplateGlobalFunction.model';
export * from '../models/TemplateGlobalFunctionSchema.model';
export * from '../models/TemplateGlobalValue.model';
export * from '../models/TemplateParameterSchema.model';
export * from '../models/TemplateParameterSchemaStepsInner.model';
export * from '../models/ValidationError.model';
export * from '../models/ValidationErrorArgument.model';
export * from '../models/ValidationErrorPathInner.model';
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,17 @@
/*
* Copyright 2025 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.
*/
export * from './generated';
@@ -16,6 +16,7 @@
import { DatabaseManager } from '@backstage/backend-defaults/database';
import { ConfigReader } from '@backstage/config';
import express from 'express';
import request from 'supertest';
import ObservableImpl from 'zen-observable';
@@ -41,6 +42,7 @@ import { TaskSpec } from '@backstage/plugin-scaffolder-common';
import { JsonValue } from '@backstage/types';
import { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';
import { AuthorizeResult } from '@backstage/plugin-permission-common';
import { wrapServer } from '@backstage/backend-openapi-utils/testUtils';
import {
mockCredentials,
mockErrorHandler,
@@ -56,7 +58,7 @@ import {
} from '@backstage/plugin-scaffolder-node/alpha';
import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils';
import { DatabaseService } from '@backstage/backend-plugin-api';
import { createDebugLogAction } from '../scaffolder/actions/builtin';
import { ScmIntegrations } from '@backstage/integration';
import {
extractFilterMetadata,
@@ -242,11 +244,20 @@ const createTestRouter = async (
},
handler: async () => {},
}),
createDebugLogAction(),
],
});
router.use(mockErrorHandler());
return { router, logger, taskBroker, permissions, catalog };
const wrappedRouter = await wrapServer(express().use(router));
return {
router: wrappedRouter,
unwrappedRouter: router,
logger,
taskBroker,
permissions,
catalog,
};
};
describe('scaffolder router', () => {
@@ -262,7 +273,7 @@ describe('scaffolder router', () => {
const response = await request(router).get('/v2/actions').send();
expect(response.status).toEqual(200);
expect(response.body[0].id).toBeDefined();
expect(response.body.length).toBe(1);
expect(response.body.length).toBe(2);
});
});
@@ -704,7 +715,10 @@ describe('scaffolder router', () => {
},
});
console.log(status, body);
expect(status).toBe(201);
expect(body).toMatchObject({
id: expect.any(String),
});
expect(logger.info).toHaveBeenCalledTimes(1);
expect(logger.info).toHaveBeenCalledWith(
'Scaffolding task for template:default/create-react-app-template created by user:default/mock',
@@ -1034,7 +1048,7 @@ describe('scaffolder router', () => {
describe('GET /v2/tasks/:taskId/eventstream', () => {
it('should return log messages', async () => {
const { router, taskBroker } = await createTestRouter();
const { unwrappedRouter: router, taskBroker } = await createTestRouter();
(taskBroker.get as jest.Mocked<TaskBroker>['get']).mockResolvedValue({
id: 'a-random-id',
spec: {} as any,
@@ -1129,7 +1143,7 @@ data: {"id":1,"taskId":"a-random-id","type":"completion","createdAt":"","body":{
});
it('should return log messages with after query', async () => {
const { router, taskBroker } = await createTestRouter();
const { unwrappedRouter: router, taskBroker } = await createTestRouter();
(taskBroker.get as jest.Mocked<TaskBroker>['get']).mockResolvedValue({
id: 'a-random-id',
spec: {} as any,
@@ -1433,7 +1447,7 @@ data: {"id":1,"taskId":"a-random-id","type":"completion","createdAt":"","body":{
it('should call the autocomplete handler', async () => {
const handleAutocompleteRequest = jest.fn().mockResolvedValue({
results: [{ title: 'blob' }],
results: [{ id: 'a-random-id', title: 'blob' }],
});
const { router } = await createTestRouter({
@@ -1454,7 +1468,9 @@ data: {"id":1,"taskId":"a-random-id","type":"completion","createdAt":"","body":{
expect(response.status).toEqual(200);
expect(response.body).toEqual({ results: [{ title: 'blob' }] });
expect(response.body).toEqual({
results: [{ id: 'a-random-id', title: 'blob' }],
});
expect(handleAutocompleteRequest).toHaveBeenCalledWith({
token: mockToken,
context,
@@ -79,7 +79,6 @@ import {
} from '@backstage/plugin-scaffolder-node/alpha';
import { HumanDuration, JsonObject } from '@backstage/types';
import express from 'express';
import Router from 'express-promise-router';
import { validate } from 'jsonschema';
import { Duration } from 'luxon';
import { pathToFileURL } from 'url';
@@ -93,6 +92,7 @@ import {
import { createDryRunner } from '../scaffolder/dryrun';
import { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker';
import { InternalTaskSecrets } from '../scaffolder/tasks/types';
import { createOpenApiRouter } from '../schema/openapi';
import {
checkPermission,
checkTaskPermission,
@@ -102,7 +102,6 @@ import {
findTemplate,
getEntityBaseUrl,
getWorkingDirectory,
parseNumberParam,
parseStringsParam,
} from './helpers';
@@ -187,7 +186,7 @@ const readDuration = (
export async function createRouter(
options: RouterOptions,
): Promise<express.Router> {
const router = Router();
const router = await createOpenApiRouter();
// Be generous in upload size to support a wide range of templates in dry-run mode.
router.use(express.json({ limit: '10MB' }));
@@ -404,8 +403,10 @@ export async function createRouter(
description: template.metadata.description,
'ui:options': template.metadata['ui:options'],
steps: parameters.map(schema => ({
title: schema.title ?? 'Please enter the following information',
description: schema.description,
title:
(schema.title as string) ??
'Please enter the following information',
description: schema.description as string,
schema,
})),
EXPERIMENTAL_formDecorators:
@@ -587,8 +588,7 @@ export async function createRouter(
};
});
const limit = parseNumberParam(req.query.limit, 'limit');
const offset = parseNumberParam(req.query.offset, 'offset');
const { limit, offset } = req.query;
const taskPermissionFilters = await getAuthorizeConditions({
credentials: credentials,
@@ -604,8 +604,8 @@ export async function createRouter(
},
order,
pagination: {
limit: limit ? limit[0] : undefined,
offset: offset ? offset[0] : undefined,
limit,
offset,
},
permissionFilters: taskPermissionFilters,
});
@@ -747,8 +747,10 @@ export async function createRouter(
await auditorEvent?.fail({ error: err });
throw err;
}
})
.get('/v2/tasks/:taskId/eventstream', async (req, res) => {
});
(router as express.Router).get(
'/v2/tasks/:taskId/eventstream',
async (req, res) => {
const { taskId } = req.params;
const auditorEvent = await auditor?.createEvent({
@@ -823,7 +825,9 @@ export async function createRouter(
await auditorEvent?.fail({ error: err });
throw err;
}
})
},
);
router
.get('/v2/tasks/:taskId/events', async (req, res) => {
const { taskId } = req.params;
+10 -1
View File
@@ -1 +1,10 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, {
overrides: [
{
files: ['src/schema/openapi/generated/models/*.model.ts'],
rules: {
'@typescript-eslint/no-redeclare': 'off',
},
},
],
});
+12 -2
View File
@@ -61,10 +61,20 @@
},
"dependencies": {
"@backstage/catalog-model": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@backstage/types": "workspace:^"
"@backstage/types": "workspace:^",
"@microsoft/fetch-event-source": "^2.0.1",
"@types/json-schema": "^7.0.9",
"cross-fetch": "^4.0.0",
"json-schema": "^0.4.0",
"uri-template": "^2.0.0",
"zen-observable": "^0.10.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^"
"@backstage/cli": "workspace:^",
"@backstage/test-utils": "workspace:^",
"msw": "^1.0.0"
}
}
+382 -1
View File
@@ -7,15 +7,353 @@ import { Entity } from '@backstage/catalog-model';
import type { EntityMeta } from '@backstage/catalog-model';
import type { JsonArray } from '@backstage/types';
import { JsonObject } from '@backstage/types';
import type { JsonValue } from '@backstage/types';
import { JSONSchema7 } from 'json-schema';
import { JsonValue } from '@backstage/types';
import { KindValidator } from '@backstage/catalog-model';
import { Observable } from '@backstage/types';
import { ScmIntegrationRegistry } from '@backstage/integration';
import type { UserEntity } from '@backstage/catalog-model';
// @public
export type Action = {
id: string;
description?: string;
schema?: {
input?: JSONSchema7;
output?: JSONSchema7;
};
examples?: ScaffolderUsageExample[];
};
// @public
export const isTemplateEntityV1beta3: (
entity: Entity,
) => entity is TemplateEntityV1beta3;
// @public
export type ListActionsResponse = Array<Action>;
// @public
export type ListTemplatingExtensionsResponse = {
filters: Record<string, TemplateFilter>;
globals: {
functions: Record<string, TemplateGlobalFunction>;
values: Record<string, TemplateGlobalValue>;
};
};
// @public
export type LogEvent = {
type: TaskEventType;
body: {
message: string;
stepId?: string;
status?: ScaffolderTaskStatus;
};
createdAt: string;
id: number;
taskId: string;
};
// @public
export interface ScaffolderApi {
// (undocumented)
autocomplete?(
request: {
token: string;
provider: string;
resource: string;
context: Record<string, string>;
},
options?: ScaffolderRequestOptions,
): Promise<{
results: {
title?: string;
id: string;
}[];
}>;
cancelTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{
status?: ScaffolderTaskStatus;
}>;
// (undocumented)
dryRun?(
request: ScaffolderDryRunOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderDryRunResponse>;
// (undocumented)
getIntegrationsList(
options: ScaffolderGetIntegrationsListOptions,
): Promise<ScaffolderGetIntegrationsListResponse>;
// (undocumented)
getTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderTask>;
// (undocumented)
getTemplateParameterSchema(
templateRef: string,
options?: ScaffolderRequestOptions,
): Promise<TemplateParameterSchema>;
listActions(options?: ScaffolderRequestOptions): Promise<ListActionsResponse>;
// (undocumented)
listTasks?(
request: {
filterByOwnership: 'owned' | 'all';
limit?: number;
offset?: number;
},
options?: ScaffolderRequestOptions,
): Promise<{
tasks: ScaffolderTask[];
totalTasks?: number;
}>;
listTemplatingExtensions?(
options?: ScaffolderRequestOptions,
): Promise<ListTemplatingExtensionsResponse>;
retry?(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{
id: string;
}>;
scaffold(
request: ScaffolderScaffoldOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderScaffoldResponse>;
// (undocumented)
streamLogs(
request: ScaffolderStreamLogsOptions,
options?: ScaffolderRequestOptions,
): Observable<LogEvent>;
}
// @public
export class ScaffolderClient implements ScaffolderApi {
constructor(options: {
discoveryApi: {
getBaseUrl(pluginId: string): Promise<string>;
};
fetchApi: {
fetch: typeof fetch;
};
identityApi?: {
getBackstageIdentity(): Promise<{
type: 'user';
userEntityRef: string;
ownershipEntityRefs: string[];
}>;
};
scmIntegrationsApi: ScmIntegrationRegistry;
useLongPollingLogs?: boolean;
});
autocomplete({
token,
resource,
provider,
context,
}: {
token: string;
provider: string;
resource: string;
context: Record<string, string>;
}): Promise<{
results: {
title?: string;
id: string;
}[];
}>;
cancelTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{
status?: ScaffolderTaskStatus;
}>;
// (undocumented)
dryRun(
request: ScaffolderDryRunOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderDryRunResponse>;
// (undocumented)
getIntegrationsList(
options: ScaffolderGetIntegrationsListOptions,
): Promise<ScaffolderGetIntegrationsListResponse>;
// (undocumented)
getTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderTask>;
// (undocumented)
getTemplateParameterSchema(
templateRef: string,
options?: ScaffolderRequestOptions,
): Promise<TemplateParameterSchema>;
listActions(options?: ScaffolderRequestOptions): Promise<ListActionsResponse>;
// (undocumented)
listTasks(
request: {
filterByOwnership: 'owned' | 'all';
limit?: number;
offset?: number;
},
options?: ScaffolderRequestOptions,
): Promise<{
tasks: ScaffolderTask[];
totalTasks?: number;
}>;
listTemplatingExtensions(
options?: ScaffolderRequestOptions,
): Promise<ListTemplatingExtensionsResponse>;
retry?(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{
id: string;
}>;
scaffold(
request: ScaffolderScaffoldOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderScaffoldResponse>;
// (undocumented)
streamLogs(
request: ScaffolderStreamLogsOptions,
options?: ScaffolderRequestOptions,
): Observable<LogEvent>;
}
// @public (undocumented)
export interface ScaffolderDryRunOptions {
// (undocumented)
directoryContents: {
path: string;
base64Content: string;
}[];
// (undocumented)
secrets?: Record<string, string>;
// (undocumented)
template: TemplateEntityV1beta3;
// (undocumented)
values: JsonObject;
}
// @public (undocumented)
export interface ScaffolderDryRunResponse {
// (undocumented)
directoryContents: Array<{
path: string;
base64Content: string;
executable?: boolean;
}>;
// (undocumented)
log: Array<Pick<LogEvent, 'body'>>;
// (undocumented)
output: ScaffolderTaskOutput;
// (undocumented)
steps: TaskStep[];
}
// @public
export interface ScaffolderGetIntegrationsListOptions {
// (undocumented)
allowedHosts: string[];
}
// @public
export interface ScaffolderGetIntegrationsListResponse {
// (undocumented)
integrations: {
type: string;
title: string;
host: string;
}[];
}
// @public (undocumented)
export type ScaffolderOutputLink = {
title?: string;
icon?: string;
url?: string;
entityRef?: string;
};
// @public (undocumented)
export type ScaffolderOutputText = {
title?: string;
icon?: string;
content?: string;
default?: boolean;
};
// @public
export interface ScaffolderRequestOptions {
// (undocumented)
token?: string;
}
// @public
export interface ScaffolderScaffoldOptions {
// (undocumented)
secrets?: Record<string, string>;
// (undocumented)
templateRef: string;
// (undocumented)
values: Record<string, JsonValue>;
}
// @public
export interface ScaffolderScaffoldResponse {
// (undocumented)
taskId: string;
}
// @public
export interface ScaffolderStreamLogsOptions {
// (undocumented)
after?: number;
// (undocumented)
isTaskRecoverable?: boolean;
// (undocumented)
taskId: string;
}
// @public
export type ScaffolderTask = {
id: string;
spec: TaskSpec;
status: ScaffolderTaskStatus;
lastHeartbeatAt?: string;
createdAt: string;
};
// @public (undocumented)
export type ScaffolderTaskOutput = {
links?: ScaffolderOutputLink[];
text?: ScaffolderOutputText[];
} & {
[key: string]: unknown;
};
// @public (undocumented)
export type ScaffolderTaskStatus =
| 'cancelled'
| 'completed'
| 'failed'
| 'open'
| 'processing'
| 'skipped';
// @public
export type ScaffolderUsageExample = {
description?: string;
example: string;
notes?: string;
};
// @public (undocumented)
export type TaskEventType = 'cancelled' | 'completion' | 'log' | 'recovered';
// @public
export type TaskRecoverStrategy = 'none' | 'startOver';
@@ -94,6 +432,33 @@ export interface TemplateEntityV1beta3 extends Entity {
// @public
export const templateEntityV1beta3Validator: KindValidator;
// @public
export type TemplateFilter = {
description?: string;
schema?: {
input?: JSONSchema7;
arguments?: JSONSchema7[];
output?: JSONSchema7;
};
examples?: ScaffolderUsageExample[];
};
// @public
export type TemplateGlobalFunction = {
description?: string;
schema?: {
arguments?: JSONSchema7[];
output?: JSONSchema7;
};
examples?: ScaffolderUsageExample[];
};
// @public
export type TemplateGlobalValue = {
description?: string;
value: JsonValue;
};
// @public
export type TemplateInfo = {
entityRef: string;
@@ -103,6 +468,22 @@ export type TemplateInfo = {
};
};
// @public
export type TemplateParameterSchema = {
title: string;
description?: string;
presentation?: TemplatePresentationV1beta3;
steps: Array<{
title: string;
description?: string;
schema: JsonObject;
}>;
EXPERIMENTAL_formDecorators?: {
id: string;
input?: JsonObject;
}[];
};
// @public
export interface TemplateParametersV1beta3 extends JsonObject {
// (undocumented)
@@ -14,12 +14,15 @@
* limitations under the License.
*/
import { ConfigReader } from '@backstage/core-app-api';
import { ScmIntegrations } from '@backstage/integration';
import { MockFetchApi, registerMswTestHooks } from '@backstage/test-utils';
import {
MockFetchApi,
mockApis,
registerMswTestHooks,
} from '@backstage/test-utils';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import { ScaffolderClient } from './api';
import { ScaffolderClient } from './ScaffolderClient';
import { fetchEventSource } from '@microsoft/fetch-event-source';
jest.mock('@microsoft/fetch-event-source');
@@ -31,6 +34,17 @@ const server = setupServer();
describe('api', () => {
registerMswTestHooks(server);
const githubIntegrationConfig = mockApis.config({
data: {
integrations: {
github: [
{
host: 'hello.com',
},
],
},
},
});
const mockBaseUrl = 'http://backstage/api';
const discoveryApi = { getBaseUrl: async () => mockBaseUrl };
@@ -43,15 +57,7 @@ describe('api', () => {
};
const scmIntegrationsApi = ScmIntegrations.fromConfig(
new ConfigReader({
integrations: {
github: [
{
host: 'hello.com',
},
],
},
}),
githubIntegrationConfig,
);
let apiClient: ScaffolderClient;
@@ -0,0 +1,426 @@
/*
* Copyright 2020 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 { parseEntityRef } from '@backstage/catalog-model';
import { ResponseError } from '@backstage/errors';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { Observable } from '@backstage/types';
import {
EventSourceMessage,
fetchEventSource,
} from '@microsoft/fetch-event-source';
import ObservableImpl from 'zen-observable';
import { type TemplateParameterSchema } from './TemplateEntityV1beta3';
import {
ListActionsResponse,
ListTemplatingExtensionsResponse,
LogEvent,
ScaffolderApi,
ScaffolderDryRunOptions,
ScaffolderDryRunResponse,
ScaffolderGetIntegrationsListOptions,
ScaffolderGetIntegrationsListResponse,
ScaffolderRequestOptions,
ScaffolderScaffoldOptions,
ScaffolderScaffoldResponse,
ScaffolderStreamLogsOptions,
ScaffolderTask,
} from './api';
import { DefaultApiClient, TaskStatus, TypedResponse } from './schema/openapi';
/**
* An API to interact with the scaffolder backend.
*
* @public
*/
export class ScaffolderClient implements ScaffolderApi {
private readonly apiClient: DefaultApiClient;
private readonly discoveryApi: {
getBaseUrl(pluginId: string): Promise<string>;
};
private readonly scmIntegrationsApi: ScmIntegrationRegistry;
private readonly fetchApi: { fetch: typeof fetch };
private readonly identityApi?: {
getBackstageIdentity(): Promise<{
type: 'user';
userEntityRef: string;
ownershipEntityRefs: string[];
}>;
};
private readonly useLongPollingLogs: boolean;
constructor(options: {
discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };
fetchApi: { fetch: typeof fetch };
identityApi?: {
getBackstageIdentity(): Promise<{
type: 'user';
userEntityRef: string;
ownershipEntityRefs: string[];
}>;
};
scmIntegrationsApi: ScmIntegrationRegistry;
useLongPollingLogs?: boolean;
}) {
this.apiClient = new DefaultApiClient(options);
this.discoveryApi = options.discoveryApi;
this.fetchApi = options.fetchApi ?? { fetch };
this.scmIntegrationsApi = options.scmIntegrationsApi;
this.useLongPollingLogs = options.useLongPollingLogs ?? false;
this.identityApi = options.identityApi;
}
/**
* {@inheritdoc ScaffolderApi.listTasks}
*/
async listTasks(
request: {
filterByOwnership: 'owned' | 'all';
limit?: number;
offset?: number;
},
options?: ScaffolderRequestOptions,
): Promise<{ tasks: ScaffolderTask[]; totalTasks?: number }> {
if (!this.identityApi) {
throw new Error(
'IdentityApi is not available in the ScaffolderClient, please pass through the IdentityApi to the ScaffolderClient constructor in order to use the listTasks method',
);
}
const { userEntityRef } = await this.identityApi.getBackstageIdentity();
return await this.requestRequired(
await this.apiClient.listTasks(
{
query: {
createdBy:
request.filterByOwnership === 'owned'
? [userEntityRef]
: undefined,
limit: request.limit,
offset: request.offset,
},
},
options,
),
);
}
async getIntegrationsList(
options: ScaffolderGetIntegrationsListOptions,
): Promise<ScaffolderGetIntegrationsListResponse> {
const integrations = [
...this.scmIntegrationsApi.azure.list(),
...this.scmIntegrationsApi.bitbucket
.list()
.filter(
item =>
!this.scmIntegrationsApi.bitbucketCloud.byHost(item.config.host) &&
!this.scmIntegrationsApi.bitbucketServer.byHost(item.config.host),
),
...this.scmIntegrationsApi.bitbucketCloud.list(),
...this.scmIntegrationsApi.bitbucketServer.list(),
...this.scmIntegrationsApi.gerrit.list(),
...this.scmIntegrationsApi.gitea.list(),
...this.scmIntegrationsApi.github.list(),
...this.scmIntegrationsApi.gitlab.list(),
]
.map(c => ({ type: c.type, title: c.title, host: c.config.host }))
.filter(c => options.allowedHosts.includes(c.host));
return {
integrations,
};
}
/**
* {@inheritdoc ScaffolderApi.getTemplateParameterSchema}
*/
async getTemplateParameterSchema(
templateRef: string,
options?: ScaffolderRequestOptions,
): Promise<TemplateParameterSchema> {
return await this.requestRequired(
await this.apiClient.getTemplateParameterSchema(
{
path: parseEntityRef(templateRef, {
defaultKind: 'template',
}),
},
options,
),
);
}
/**
* {@inheritdoc ScaffolderApi.scaffold}
*/
async scaffold(
request: ScaffolderScaffoldOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderScaffoldResponse> {
const response = await this.apiClient.scaffold(
{
body: request,
},
options,
);
if (response.status !== 201) {
const status = `${response.status} ${response.statusText}`;
const body = await response.text();
throw new Error(`Backend request failed, ${status} ${body.trim()}`);
}
const { id } = await response.json();
return { taskId: id };
}
/**
* {@inheritdoc ScaffolderApi.getTask}
*/
async getTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderTask> {
return await this.requestRequired(
await this.apiClient.getTask(
{
path: { taskId },
},
options,
),
);
}
/**
* {@inheritdoc ScaffolderApi.streamLogs}
*/
streamLogs(
request: ScaffolderStreamLogsOptions,
options?: ScaffolderRequestOptions,
): Observable<LogEvent> {
if (this.useLongPollingLogs) {
return this.streamLogsPolling(request, options);
}
return this.streamLogsEventStream(request);
}
/**
* {@inheritdoc ScaffolderApi.dryRun}
*/
async dryRun(
request: ScaffolderDryRunOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderDryRunResponse> {
return await this.requestRequired(
await this.apiClient.dryRun(
{
body: {
template: request.template,
values: request.values,
secrets: request.secrets,
directoryContents: request.directoryContents,
},
},
options,
),
);
}
private streamLogsEventStream({
isTaskRecoverable,
taskId,
after,
}: ScaffolderStreamLogsOptions): Observable<LogEvent> {
return new ObservableImpl(subscriber => {
const params = new URLSearchParams();
if (after !== undefined) {
params.set('after', String(Number(after)));
}
this.discoveryApi.getBaseUrl('scaffolder').then(
baseUrl => {
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
taskId,
)}/eventstream`;
const processEvent = (event: any) => {
if (event.data) {
try {
subscriber.next(JSON.parse(event.data));
} catch (ex) {
subscriber.error(ex);
}
}
};
const ctrl = new AbortController();
void fetchEventSource(url, {
fetch: this.fetchApi.fetch,
signal: ctrl.signal,
onmessage(e: EventSourceMessage) {
if (e.event === 'log') {
processEvent(e);
return;
} else if (e.event === 'completion' && !isTaskRecoverable) {
processEvent(e);
subscriber.complete();
ctrl.abort();
return;
}
processEvent(e);
},
onerror(err) {
subscriber.error(err);
},
});
},
error => {
subscriber.error(error);
},
);
});
}
private streamLogsPolling(
{
taskId,
after: inputAfter,
}: {
taskId: string;
after?: number;
},
options?: ScaffolderRequestOptions,
): Observable<LogEvent> {
let after = inputAfter;
return new ObservableImpl(subscriber => {
(async () => {
while (!subscriber.closed) {
const response = await this.apiClient.streamLogsPolling(
{
path: { taskId },
query: { after },
},
options,
);
if (!response.ok) {
// wait for one second to not run into an
await new Promise(resolve => setTimeout(resolve, 1000));
continue;
}
const logs = (await response.json()) as LogEvent[];
for (const event of logs) {
after = Number(event.id);
subscriber.next(event);
if (event.type === 'completion') {
subscriber.complete();
return;
}
}
}
})();
});
}
/**
* {@inheritdoc ScaffolderApi.listActions}
*/
async listActions(
options?: ScaffolderRequestOptions,
): Promise<ListActionsResponse> {
return await this.requestRequired(
await this.apiClient.listActions(null as any, options),
);
}
/**
* {@inheritdoc ScaffolderApi.listTemplatingExtensions}
*/
async listTemplatingExtensions(
options?: ScaffolderRequestOptions,
): Promise<ListTemplatingExtensionsResponse> {
return await this.requestRequired(
await this.apiClient.listTemplatingExtensions(null as any, options),
);
}
/**
* {@inheritdoc ScaffolderApi.cancelTask}
*/
async cancelTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{ status?: TaskStatus }> {
return await this.requestRequired(
await this.apiClient.cancelTask({ path: { taskId } }, options),
);
}
/**
* {@inheritdoc ScaffolderApi.retry}
*/
async retry?(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{ id: string }> {
return await this.requestRequired(
await this.apiClient.retry({ body: {}, path: { taskId } }, options),
);
}
/**
* {@inheritdoc ScaffolderApi.retry}
*/
async autocomplete({
token,
resource,
provider,
context,
}: {
token: string;
provider: string;
resource: string;
context: Record<string, string>;
}): Promise<{ results: { title?: string; id: string }[] }> {
return await this.requestRequired(
await this.apiClient.autocomplete({
path: { provider, resource },
body: { token, context },
}),
);
}
//
// Private methods
//
private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return response.json();
}
}
@@ -142,6 +142,24 @@ export interface TemplateEntityStepV1beta3 extends JsonObject {
'backstage:permissions'?: TemplatePermissionsV1beta3;
}
/**
* The shape of each entry of parameters which gets rendered
* as a separate step in the wizard input
*
* @public
*/
export type TemplateParameterSchema = {
title: string;
description?: string;
presentation?: TemplatePresentationV1beta3;
steps: Array<{
title: string;
description?: string;
schema: JsonObject;
}>;
EXPERIMENTAL_formDecorators?: { id: string; input?: JsonObject }[];
};
/**
* Parameter that is part of a Template Entity.
*
+337
View File
@@ -0,0 +1,337 @@
/*
* Copyright 2020 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 { JsonObject, JsonValue, Observable } from '@backstage/types';
import { JSONSchema7 } from 'json-schema';
import { TaskSpec, TaskStep } from './TaskSpec';
import type {
TemplateEntityV1beta3,
TemplateParameterSchema,
} from './TemplateEntityV1beta3';
import type {
TaskEventType,
TaskStatus as ScaffolderTaskStatus,
} from './schema/openapi';
export type { ScaffolderTaskStatus, TaskEventType };
/**
* Options you can pass into a Scaffolder request for additional information.
*
* @public
*/
export interface ScaffolderRequestOptions {
token?: string;
}
/**
* The shape of each task returned from the `scaffolder-backend`
*
* @public
*/
export type ScaffolderTask = {
id: string;
spec: TaskSpec;
status: ScaffolderTaskStatus;
lastHeartbeatAt?: string;
createdAt: string;
};
/**
* A single scaffolder usage example
*
* @public
*/
export type ScaffolderUsageExample = {
description?: string;
example: string;
notes?: string;
};
/**
* The response shape for a single action in the `listActions` call to the `scaffolder-backend`
*
* @public
*/
export type Action = {
id: string;
description?: string;
schema?: {
input?: JSONSchema7;
output?: JSONSchema7;
};
examples?: ScaffolderUsageExample[];
};
/**
* The response shape for the `listActions` call to the `scaffolder-backend`
*
* @public
*/
export type ListActionsResponse = Array<Action>;
/**
* The response shape for a single filter in the `listTemplatingExtensions` call to the `scaffolder-backend`
*
* @public
*/
export type TemplateFilter = {
description?: string;
schema?: {
input?: JSONSchema7;
arguments?: JSONSchema7[];
output?: JSONSchema7;
};
examples?: ScaffolderUsageExample[];
};
/**
* The response shape for a single global function in the `listTemplatingExtensions` call to the `scaffolder-backend`
*
* @public
*/
export type TemplateGlobalFunction = {
description?: string;
schema?: {
arguments?: JSONSchema7[];
output?: JSONSchema7;
};
examples?: ScaffolderUsageExample[];
};
/**
* The response shape for a single global value in the `listTemplatingExtensions` call to the `scaffolder-backend`
*
* @public
*/
export type TemplateGlobalValue = {
description?: string;
value: JsonValue;
};
/**
* The response shape for the `listTemplatingExtensions` call to the `scaffolder-backend`
*
* @public
*/
export type ListTemplatingExtensionsResponse = {
filters: Record<string, TemplateFilter>;
globals: {
functions: Record<string, TemplateGlobalFunction>;
values: Record<string, TemplateGlobalValue>;
};
};
/** @public */
export type ScaffolderOutputLink = {
title?: string;
icon?: string;
url?: string;
entityRef?: string;
};
/** @public */
export type ScaffolderOutputText = {
title?: string;
icon?: string;
content?: string;
default?: boolean;
};
/** @public */
export type ScaffolderTaskOutput = {
links?: ScaffolderOutputLink[];
text?: ScaffolderOutputText[];
} & {
[key: string]: unknown;
};
/**
* The shape of a `LogEvent` message from the `scaffolder-backend`
*
* @public
*/
export type LogEvent = {
type: TaskEventType;
body: {
message: string;
stepId?: string;
status?: ScaffolderTaskStatus;
};
createdAt: string;
id: number;
taskId: string;
};
/**
* The input options to the `scaffold` method of the `ScaffolderClient`.
*
* @public
*/
export interface ScaffolderScaffoldOptions {
templateRef: string;
values: Record<string, JsonValue>;
secrets?: Record<string, string>;
}
/**
* The response shape of the `scaffold` method of the `ScaffolderClient`.
*
* @public
*/
export interface ScaffolderScaffoldResponse {
taskId: string;
}
/**
* The arguments for `getIntegrationsList`.
*
* @public
*/
export interface ScaffolderGetIntegrationsListOptions {
allowedHosts: string[];
}
/**
* The response shape for `getIntegrationsList`.
*
* @public
*/
export interface ScaffolderGetIntegrationsListResponse {
integrations: { type: string; title: string; host: string }[];
}
/**
* The input options to the `streamLogs` method of the `ScaffolderClient`.
*
* @public
*/
export interface ScaffolderStreamLogsOptions {
isTaskRecoverable?: boolean;
taskId: string;
after?: number;
}
/** @public */
export interface ScaffolderDryRunOptions {
template: TemplateEntityV1beta3;
values: JsonObject;
secrets?: Record<string, string>;
directoryContents: { path: string; base64Content: string }[];
}
/** @public */
export interface ScaffolderDryRunResponse {
directoryContents: Array<{
path: string;
base64Content: string;
executable?: boolean;
}>;
log: Array<Pick<LogEvent, 'body'>>;
steps: TaskStep[];
output: ScaffolderTaskOutput;
}
/**
* An API to interact with the scaffolder backend.
*
* @public
*/
export interface ScaffolderApi {
getTemplateParameterSchema(
templateRef: string,
options?: ScaffolderRequestOptions,
): Promise<TemplateParameterSchema>;
/**
* Executes the scaffolding of a component, given a template and its
* parameter values.
*
* @param options - The {@link ScaffolderScaffoldOptions} the scaffolding.
*/
scaffold(
request: ScaffolderScaffoldOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderScaffoldResponse>;
getTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderTask>;
/**
* Sends a signal to a task broker to cancel the running task by taskId.
*
* @param taskId - the id of the task
*/
cancelTask(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{ status?: ScaffolderTaskStatus }>;
/**
* Starts the task again from the point where it failed.
*
* @param taskId - the id of the task
*/
retry?(
taskId: string,
options?: ScaffolderRequestOptions,
): Promise<{ id: string }>;
listTasks?(
request: {
filterByOwnership: 'owned' | 'all';
limit?: number;
offset?: number;
},
options?: ScaffolderRequestOptions,
): Promise<{ tasks: ScaffolderTask[]; totalTasks?: number }>;
getIntegrationsList(
options: ScaffolderGetIntegrationsListOptions,
): Promise<ScaffolderGetIntegrationsListResponse>;
/**
* Returns a list of all installed actions.
*/
listActions(options?: ScaffolderRequestOptions): Promise<ListActionsResponse>;
/**
* Returns a structure describing the available templating extensions.
*/
listTemplatingExtensions?(
options?: ScaffolderRequestOptions,
): Promise<ListTemplatingExtensionsResponse>;
streamLogs(
request: ScaffolderStreamLogsOptions,
options?: ScaffolderRequestOptions,
): Observable<LogEvent>;
dryRun?(
request: ScaffolderDryRunOptions,
options?: ScaffolderRequestOptions,
): Promise<ScaffolderDryRunResponse>;
autocomplete?(
request: {
token: string;
provider: string;
resource: string;
context: Record<string, string>;
},
options?: ScaffolderRequestOptions,
): Promise<{ results: { title?: string; id: string }[] }>;
}
+5
View File
@@ -30,7 +30,12 @@ export type {
TemplatePresentationV1beta3,
TemplateEntityV1beta3,
TemplateEntityStepV1beta3,
TemplateParameterSchema,
TemplateParametersV1beta3,
TemplatePermissionsV1beta3,
TemplateRecoveryV1beta3,
} from './TemplateEntityV1beta3';
export * from './ScaffolderClient';
export * from './api';
@@ -0,0 +1,454 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DiscoveryApi } from '../types/discovery';
import { FetchApi } from '../types/fetch';
import crossFetch from 'cross-fetch';
import { pluginId } from '../pluginId';
import * as parser from 'uri-template';
import { Action } from '../models/Action.model';
import { Autocomplete200Response } from '../models/Autocomplete200Response.model';
import { AutocompleteRequest } from '../models/AutocompleteRequest.model';
import { CancelTask200Response } from '../models/CancelTask200Response.model';
import { DryRun200Response } from '../models/DryRun200Response.model';
import { DryRunRequest } from '../models/DryRunRequest.model';
import { ListTasksResponse } from '../models/ListTasksResponse.model';
import { ListTemplatingExtensionsResponse } from '../models/ListTemplatingExtensionsResponse.model';
import { RetryRequest } from '../models/RetryRequest.model';
import { Scaffold201Response } from '../models/Scaffold201Response.model';
import { ScaffolderScaffoldOptions } from '../models/ScaffolderScaffoldOptions.model';
import { SerializedTask } from '../models/SerializedTask.model';
import { SerializedTaskEvent } from '../models/SerializedTaskEvent.model';
import { TemplateParameterSchema } from '../models/TemplateParameterSchema.model';
/**
* Wraps the Response type to convey a type on the json call.
*
* @public
*/
export type TypedResponse<T> = Omit<Response, 'json'> & {
json: () => Promise<T>;
};
/**
* Options you can pass into a request for additional information.
*
* @public
*/
export interface RequestOptions {
token?: string;
}
/**
* @public
*/
export type Autocomplete = {
path: {
provider: string;
resource: string;
};
body: AutocompleteRequest;
};
/**
* @public
*/
export type CancelTask = {
path: {
taskId: string;
};
};
/**
* @public
*/
export type DryRun = {
body: DryRunRequest;
};
/**
* @public
*/
export type GetTask = {
path: {
taskId: string;
};
};
/**
* @public
*/
export type GetTemplateParameterSchema = {
path: {
namespace: string;
kind: string;
name: string;
};
};
/**
* @public
*/
export type ListActions = {};
/**
* @public
*/
export type ListTasks = {
query: {
createdBy?: Array<string>;
limit?: number;
offset?: number;
order?: Array<string>;
status?: Array<string>;
};
};
/**
* @public
*/
export type ListTemplatingExtensions = {};
/**
* @public
*/
export type Retry = {
path: {
taskId: string;
};
body: RetryRequest;
};
/**
* @public
*/
export type Scaffold = {
body: ScaffolderScaffoldOptions;
};
/**
* @public
*/
export type StreamLogsPolling = {
path: {
taskId: string;
};
query: {
after?: number;
};
};
/**
* @public
*/
export class DefaultApiClient {
private readonly discoveryApi: DiscoveryApi;
private readonly fetchApi: FetchApi;
constructor(options: {
discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };
fetchApi?: { fetch: typeof fetch };
}) {
this.discoveryApi = options.discoveryApi;
this.fetchApi = options.fetchApi || { fetch: crossFetch };
}
/**
* Perform an autocomplete for the given provider and resource.
* @param provider -
* @param resource -
* @param autocompleteRequest -
*/
public async autocomplete(
// @ts-ignore
request: Autocomplete,
options?: RequestOptions,
): Promise<TypedResponse<Autocomplete200Response>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/autocomplete/{provider}/{resource}`;
const uri = parser.parse(uriTemplate).expand({
provider: request.path.provider,
resource: request.path.resource,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
body: JSON.stringify(request.body),
});
}
/**
* Sends a signal to a task broker to cancel the running task by taskId.
* @param taskId -
*/
public async cancelTask(
// @ts-ignore
request: CancelTask,
options?: RequestOptions,
): Promise<TypedResponse<CancelTask200Response>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/tasks/{taskId}/cancel`;
const uri = parser.parse(uriTemplate).expand({
taskId: request.path.taskId,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
});
}
/**
* Perform a dry-run of a template
* @param dryRunRequest -
*/
public async dryRun(
// @ts-ignore
request: DryRun,
options?: RequestOptions,
): Promise<TypedResponse<DryRun200Response>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/dry-run`;
const uri = parser.parse(uriTemplate).expand({});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
body: JSON.stringify(request.body),
});
}
/**
* Get a task by ID.
* @param taskId -
*/
public async getTask(
// @ts-ignore
request: GetTask,
options?: RequestOptions,
): Promise<TypedResponse<SerializedTask>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/tasks/{taskId}`;
const uri = parser.parse(uriTemplate).expand({
taskId: request.path.taskId,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'GET',
});
}
/**
* Get template parameter schema.
* @param namespace -
* @param kind -
* @param name -
*/
public async getTemplateParameterSchema(
// @ts-ignore
request: GetTemplateParameterSchema,
options?: RequestOptions,
): Promise<TypedResponse<TemplateParameterSchema>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/templates/{namespace}/{kind}/{name}/parameter-schema`;
const uri = parser.parse(uriTemplate).expand({
namespace: request.path.namespace,
kind: request.path.kind,
name: request.path.name,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'GET',
});
}
/**
* Returns a list of all installed actions.
*/
public async listActions(
// @ts-ignore
request: ListActions,
options?: RequestOptions,
): Promise<TypedResponse<Array<Action>>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/actions`;
const uri = parser.parse(uriTemplate).expand({});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'GET',
});
}
/**
* Returns a list of tasks, filtering by ownership and/or status if given.
* @param createdBy - Created by
* @param limit - Number of records to return in the response.
* @param offset - Number of records to skip in the query page.
* @param order - Order
* @param status - Status
*/
public async listTasks(
// @ts-ignore
request: ListTasks,
options?: RequestOptions,
): Promise<TypedResponse<ListTasksResponse>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/tasks{?createdBy*,limit,offset,order*,status*}`;
const uri = parser.parse(uriTemplate).expand({
...request.query,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'GET',
});
}
/**
* Returns a structure describing the available templating extensions.
*/
public async listTemplatingExtensions(
// @ts-ignore
request: ListTemplatingExtensions,
options?: RequestOptions,
): Promise<TypedResponse<ListTemplatingExtensionsResponse>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/templating-extensions`;
const uri = parser.parse(uriTemplate).expand({});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'GET',
});
}
/**
* Starts the task again from the point where it failed.
* @param taskId -
* @param retryRequest -
*/
public async retry(
// @ts-ignore
request: Retry,
options?: RequestOptions,
): Promise<TypedResponse<Scaffold201Response>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/tasks/{taskId}/retry`;
const uri = parser.parse(uriTemplate).expand({
taskId: request.path.taskId,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
body: JSON.stringify(request.body),
});
}
/**
* Executes the scaffolding of a component, given a template and its parameter values.
* @param scaffolderScaffoldOptions -
*/
public async scaffold(
// @ts-ignore
request: Scaffold,
options?: RequestOptions,
): Promise<TypedResponse<Scaffold201Response>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/tasks`;
const uri = parser.parse(uriTemplate).expand({});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
body: JSON.stringify(request.body),
});
}
/**
* Get events for a task by ID.
* @param taskId -
* @param after - Offset event ID to stream events after.
*/
public async streamLogsPolling(
// @ts-ignore
request: StreamLogsPolling,
options?: RequestOptions,
): Promise<TypedResponse<Array<SerializedTaskEvent>>> {
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
const uriTemplate = `/v2/tasks/{taskId}/events{?after}`;
const uri = parser.parse(uriTemplate).expand({
taskId: request.path.taskId,
...request.query,
});
return await this.fetchApi.fetch(`${baseUrl}${uri}`, {
headers: {
'Content-Type': 'application/json',
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'GET',
});
}
}
@@ -0,0 +1,17 @@
/*
* Copyright 2025 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.
*/
export * from './Api.client';
@@ -0,0 +1,18 @@
/*
* Copyright 2025 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.
*/
export * from './apis';
export * from './models';
@@ -0,0 +1,32 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { ActionExample } from '../models/ActionExample.model';
import { ActionSchema } from '../models/ActionSchema.model';
/**
* The response shape for a single action in the `listActions` call to the `scaffolder-backend`
* @public
*/
export interface Action {
id: string;
description?: string;
examples?: Array<ActionExample>;
schema?: ActionSchema;
}
@@ -0,0 +1,28 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* A single action example
* @public
*/
export interface ActionExample {
description: string;
example: string;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface ActionSchema {
/**
* A type representing all allowed JSON object values.
*/
input?: { [key: string]: any };
/**
* A type representing all allowed JSON object values.
*/
output?: { [key: string]: any };
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { Autocomplete200ResponseResultsInner } from '../models/Autocomplete200ResponseResultsInner.model';
/**
* @public
*/
export interface Autocomplete200Response {
results: Array<Autocomplete200ResponseResultsInner>;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface Autocomplete200ResponseResultsInner {
title?: string;
id: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface Autocomplete400Response {
message?: string;
name?: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface AutocompleteRequest {
context: { [key: string]: string };
token: string;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TaskStatus } from '../models/TaskStatus.model';
/**
* @public
*/
export interface CancelTask200Response {
status?: TaskStatus;
}
@@ -0,0 +1,35 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRun200ResponseAllOfDirectoryContentsInner } from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model';
import { DryRun200ResponseAllOfStepsInner } from '../models/DryRun200ResponseAllOfStepsInner.model';
import { DryRunResultLogInner } from '../models/DryRunResultLogInner.model';
/**
* @public
*/
export interface DryRun200Response {
log: Array<DryRunResultLogInner>;
directoryContents: Array<DryRun200ResponseAllOfDirectoryContentsInner>;
/**
* A type representing all allowed JSON object values.
*/
output: { [key: string]: any };
steps: Array<DryRun200ResponseAllOfStepsInner>;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRun200ResponseAllOfDirectoryContentsInner } from '../models/DryRun200ResponseAllOfDirectoryContentsInner.model';
import { DryRun200ResponseAllOfStepsInner } from '../models/DryRun200ResponseAllOfStepsInner.model';
/**
* @public
*/
export interface DryRun200ResponseAllOf {
steps: Array<DryRun200ResponseAllOfStepsInner>;
directoryContents?: Array<DryRun200ResponseAllOfDirectoryContentsInner>;
}
@@ -0,0 +1,28 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface DryRun200ResponseAllOfDirectoryContentsInner {
path: string;
executable?: boolean;
base64Content: string;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface DryRun200ResponseAllOfStepsInner {
[key: string]: any;
id: string;
name: string;
action: string;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRunRequestDirectoryContentsInner } from '../models/DryRunRequestDirectoryContentsInner.model';
/**
* @public
*/
export interface DryRunRequest {
template: any;
/**
* A type representing all allowed JSON object values.
*/
values: { [key: string]: any };
secrets?: { [key: string]: string };
directoryContents: Array<DryRunRequestDirectoryContentsInner>;
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface DryRunRequestDirectoryContentsInner {
path?: string;
base64Content?: string;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRunResultLogInner } from '../models/DryRunResultLogInner.model';
import { SerializedFile } from '../models/SerializedFile.model';
/**
* @public
*/
export interface DryRunResult {
log: Array<DryRunResultLogInner>;
directoryContents: Array<SerializedFile>;
/**
* A type representing all allowed JSON object values.
*/
output: { [key: string]: any };
}
@@ -0,0 +1,27 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { DryRunResultLogInnerBody } from '../models/DryRunResultLogInnerBody.model';
/**
* @public
*/
export interface DryRunResultLogInner {
body: DryRunResultLogInnerBody;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TaskStatus } from '../models/TaskStatus.model';
/**
* @public
*/
export interface DryRunResultLogInnerBody {
message: string;
status?: TaskStatus;
stepId?: string;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
import { TaskStatus } from '../models/TaskStatus.model';
/**
* @public
*/
export interface DryRunResultLogInnerBodyAllOf {
message: string;
status?: TaskStatus;
stepId?: string;
}
@@ -0,0 +1,29 @@
/*
* Copyright 2025 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.
*/
// ******************************************************************
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
// ******************************************************************
/**
* @public
*/
export interface ErrorError {
name: string;
message: string;
stack?: string;
code?: string;
}

Some files were not shown because too many files have changed in this diff Show More