Merge branch 'master' into canon-radiogroup
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/backend-defaults': patch
|
||||
'@backstage/backend-test-utils': minor
|
||||
---
|
||||
|
||||
Add a standard `toString` on credentials objects
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-node-test-utils': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-scaffolder-node': patch
|
||||
---
|
||||
|
||||
An internal refactor which adds additional types to experimental checkpoints
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Replaced deprecated uses of `@backstage/backend-common` with the equivalents in `@backstage/backend-defaults` and `@backstage/backend-plugin-api`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/canon': patch
|
||||
---
|
||||
|
||||
adding export for ButtonLink so it's importable
|
||||
@@ -12,7 +12,7 @@ by writing custom actions which can be used alongside our
|
||||
|
||||
When adding custom actions, the actions array will **replace the
|
||||
built-in actions too**. Meaning, you will no longer be able to use them.
|
||||
If you want to continue using the builtin actions, include them in the actions
|
||||
If you want to continue using the builtin actions, include them in the `actions`
|
||||
array when registering your custom actions, as seen below.
|
||||
|
||||
:::
|
||||
@@ -52,19 +52,20 @@ its generated unit test. We will replace the existing placeholder code with our
|
||||
import { resolveSafeChildPath } from '@backstage/backend-plugin-api';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import fs from 'fs-extra';
|
||||
import { z } from 'zod';
|
||||
import { type z } from 'zod';
|
||||
|
||||
export const createNewFileAction = () => {
|
||||
return createTemplateAction({
|
||||
id: 'acme:file:create',
|
||||
description: 'Create an Acme file.',
|
||||
schema: {
|
||||
input: z.object({
|
||||
contents: z.string().describe('The contents of the file'),
|
||||
filename: z
|
||||
.string()
|
||||
.describe('The filename of the file that will be created'),
|
||||
}),
|
||||
input: {
|
||||
contents: z => z.string({ description: 'The contents of the file' }),
|
||||
filename: z =>
|
||||
z.string({
|
||||
description: 'The filename of the file that will be created',
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
async handler(ctx) {
|
||||
@@ -95,53 +96,11 @@ The `createTemplateAction` takes an object which specifies the following:
|
||||
function using `ctx.output`
|
||||
- `handler` - the actual code which is run as part of the action, with a context
|
||||
|
||||
You can also choose to define your custom action using JSON schema instead of `zod`:
|
||||
|
||||
```ts title="With JSON Schema"
|
||||
import { resolveSafeChildPath } from '@backstage/backend-plugin-api';
|
||||
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
|
||||
import { writeFile } from 'fs';
|
||||
|
||||
export const createNewFileAction = () => {
|
||||
return createTemplateAction<{ contents: string; filename: string }>({
|
||||
id: 'acme:file:create',
|
||||
description: 'Create an Acme file.',
|
||||
schema: {
|
||||
input: {
|
||||
required: ['contents', 'filename'],
|
||||
type: 'object',
|
||||
properties: {
|
||||
contents: {
|
||||
type: 'string',
|
||||
title: 'Contents',
|
||||
description: 'The contents of the file',
|
||||
},
|
||||
filename: {
|
||||
type: 'string',
|
||||
title: 'Filename',
|
||||
description: 'The filename of the file that will be created',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
async handler(ctx) {
|
||||
const { signal } = ctx;
|
||||
await writeFile(
|
||||
resolveSafeChildPath(ctx.workspacePath, ctx.input.filename),
|
||||
ctx.input.contents,
|
||||
{ signal },
|
||||
_ => {},
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
Try to keep names consistent for both your own custom actions, and any actions contributed to open source. We've found
|
||||
that a separation of `:` and using a verb as the last part of the name works well.
|
||||
We follow `provider:entity:verb` or as close to this as possible for our built in actions. For example,
|
||||
We follow `provider:entity:verb` or as close to this as possible for our built-in actions. For example,
|
||||
`github:actions:create` or `github:repo:create`.
|
||||
|
||||
Also feel free to use your company name to namespace them if you prefer too, for example `acme:file:create` like above.
|
||||
@@ -151,14 +110,14 @@ and writing of template entity definitions.
|
||||
|
||||
### Adding a TemplateExample
|
||||
|
||||
A TemplateExample is a way to document different ways that your custom action can be used. Once added it will be visible
|
||||
A TemplateExample is a way to document different ways that your custom action can be used. Once added, it will be visible
|
||||
in your Backstage instance under the [/create/actions](https://demo.backstage.io/create/actions) path. You can have multiple
|
||||
examples for one action that can demonstrate different combinations of inputs and how to use them.
|
||||
|
||||
#### Define TemplateExamples
|
||||
|
||||
Below is a sample TemplateExample that is used for `publish:github`. The source code is available
|
||||
on [github](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.ts)
|
||||
on [GitHub](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.ts)
|
||||
and preview on [demo.backstage.io/create/actions](https://demo.backstage.io/create/actions#publish-github)
|
||||
|
||||
```ts title="With JSON Schema"
|
||||
@@ -222,7 +181,7 @@ return createTemplateAction({
|
||||
#### Test TemplateAction examples
|
||||
|
||||
It is also possible to test your example TemplateActions. You can see a sample test
|
||||
on [github](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts)
|
||||
on [GitHub](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts)
|
||||
|
||||
### The context object
|
||||
|
||||
@@ -234,13 +193,12 @@ argument. It looks like the following:
|
||||
implement [idempotency of the actions](https://github.com/backstage/backstage/tree/master/beps/0004-scaffolder-task-idempotency)
|
||||
by not re-running the same function again if it was
|
||||
executed successfully on the previous run.
|
||||
- `ctx.logger` - a Winston logger for additional logging inside your action
|
||||
- `ctx.logStream` - a stream version of the logger if needed
|
||||
- `ctx.logger` - a [LoggerService](../../backend-system/core-services/logger.md) instance for additional logging inside your action
|
||||
- `ctx.workspacePath` - a string of the working directory of the template run
|
||||
- `ctx.input` - an object which should match the `zod` or JSON schema provided in the
|
||||
`schema.input` part of the action definition
|
||||
- `ctx.output` - a function which you can call to set outputs that match the
|
||||
JSON schema or `zod` in `schema.output` for ex. `ctx.output('downloadUrl', myDownloadUrl)`
|
||||
`zod` schema in `schema.output` for ex. `ctx.output('downloadUrl', myDownloadUrl)`
|
||||
- `createTemporaryDirectory` a function to call to give you a temporary
|
||||
directory somewhere on the runner, so you can store some files there rather
|
||||
than polluting the `workspacePath`
|
||||
@@ -249,7 +207,7 @@ argument. It looks like the following:
|
||||
|
||||
## Registering Custom Actions
|
||||
|
||||
To register your new custom action in the Backend System you will need to create a backend module. Here is a very
|
||||
To register your new custom action in the Backend System, you will need to create a backend module. Here is a very
|
||||
simplified example of how to do that:
|
||||
|
||||
```ts title="packages/backend/src/index.ts"
|
||||
@@ -327,8 +285,8 @@ const res = await ctx.checkpoint?.({
|
||||
});
|
||||
```
|
||||
|
||||
You have to define the unique key in scope of the scaffolder task for your checkpoint. During the execution task engine
|
||||
will check if the checkpoint with such key was already executed or not, if yes, and the run was successful, the callback
|
||||
You have to define the unique key in the scope of the scaffolder task for your checkpoint. During the execution task engine
|
||||
will check if the checkpoint with such a key was already executed or not, if yes, and the run was successful, the callback
|
||||
will be skipped and instead the stored value will be returned.
|
||||
|
||||
Whenever you change the return type of the checkpoint, we encourage you to change the ID.
|
||||
|
||||
+3
-3
@@ -5942,11 +5942,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"docusaurus-pushfeedback@npm:^1.0.0":
|
||||
version: 1.0.3
|
||||
resolution: "docusaurus-pushfeedback@npm:1.0.3"
|
||||
version: 1.0.5
|
||||
resolution: "docusaurus-pushfeedback@npm:1.0.5"
|
||||
peerDependencies:
|
||||
"@docusaurus/core": 3.x
|
||||
checksum: 10/ee80ae0c1fc079b2c317cab86d83ba50cce18938a6ce0ac647aad25dc68fc0ad659e55c11e93d0e7c23270c503c3cb300111dfbdd04785ef7aaf6fb123b57eae
|
||||
checksum: 10/5323af7f1c7b4590744ea9099cacb49087d98c48c11e2ed957ed744d6210a3d82fa0cc42ef0f011f25b0d08c2d0040065c8a2b641c7c9160532ceb51ad41475c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
@@ -42,6 +42,23 @@ describe('credentials', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
createCredentialsWithUserPrincipal(
|
||||
'user:default/mock',
|
||||
'my-token',
|
||||
undefined,
|
||||
'my-actor',
|
||||
),
|
||||
).toEqual({
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
version: 'v1',
|
||||
principal: {
|
||||
type: 'user',
|
||||
userEntityRef: 'user:default/mock',
|
||||
actor: { type: 'service', subject: 'my-actor' },
|
||||
},
|
||||
});
|
||||
|
||||
expect(createCredentialsWithNonePrincipal()).toEqual({
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
version: 'v1',
|
||||
@@ -64,4 +81,63 @@ describe('credentials', () => {
|
||||
),
|
||||
).not.toMatch(/my-token/);
|
||||
});
|
||||
|
||||
it('should have a serializable form both as strings and as JSON', () => {
|
||||
const simpleService = createCredentialsWithServicePrincipal('my-service');
|
||||
expect(String(simpleService)).toMatchInlineSnapshot(
|
||||
`"backstageCredentials{servicePrincipal{my-service}}"`,
|
||||
);
|
||||
expect(JSON.stringify(simpleService)).toMatchInlineSnapshot(
|
||||
`"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"service","subject":"my-service"}}"`,
|
||||
);
|
||||
|
||||
const serviceWithAccessRestrictions = createCredentialsWithServicePrincipal(
|
||||
'my-service',
|
||||
undefined,
|
||||
{
|
||||
permissionNames: ['perm'],
|
||||
permissionAttributes: {
|
||||
action: ['read'],
|
||||
},
|
||||
},
|
||||
);
|
||||
expect(String(serviceWithAccessRestrictions)).toMatchInlineSnapshot(
|
||||
`"backstageCredentials{servicePrincipal{my-service,accessRestrictions=cXWOJgUirHkHNZIowUi/YO5nwEwhTicC38iXi2XTYCk}}"`,
|
||||
);
|
||||
expect(JSON.stringify(serviceWithAccessRestrictions)).toMatchInlineSnapshot(
|
||||
`"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"service","subject":"my-service","accessRestrictions":{"permissionNames":["perm"],"permissionAttributes":{"action":["read"]}}}}"`,
|
||||
);
|
||||
|
||||
const simpleUser = createCredentialsWithUserPrincipal(
|
||||
'user:default/mock',
|
||||
'my-token',
|
||||
);
|
||||
expect(String(simpleUser)).toMatchInlineSnapshot(
|
||||
`"backstageCredentials{userPrincipal{user:default/mock}}"`,
|
||||
);
|
||||
expect(JSON.stringify(simpleUser)).toMatchInlineSnapshot(
|
||||
`"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"user","userEntityRef":"user:default/mock"}}"`,
|
||||
);
|
||||
|
||||
const userWithActor = createCredentialsWithUserPrincipal(
|
||||
'user:default/mock',
|
||||
'my-token',
|
||||
undefined,
|
||||
'my-actor',
|
||||
);
|
||||
expect(String(userWithActor)).toMatchInlineSnapshot(
|
||||
`"backstageCredentials{userPrincipal{user:default/mock,actor={servicePrincipal{my-actor}}}}"`,
|
||||
);
|
||||
expect(JSON.stringify(userWithActor)).toMatchInlineSnapshot(
|
||||
`"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"user","userEntityRef":"user:default/mock","actor":{"type":"service","subject":"my-actor"}}}"`,
|
||||
);
|
||||
|
||||
const none = createCredentialsWithNonePrincipal();
|
||||
expect(String(none)).toMatchInlineSnapshot(
|
||||
`"backstageCredentials{nonePrincipal}"`,
|
||||
);
|
||||
expect(JSON.stringify(none)).toMatchInlineSnapshot(
|
||||
`"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"none"}}"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,29 +22,34 @@ import {
|
||||
BackstageUserPrincipal,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { InternalBackstageCredentials } from './types';
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
export function createCredentialsWithServicePrincipal(
|
||||
sub: string,
|
||||
token?: string,
|
||||
accessRestrictions?: BackstagePrincipalAccessRestrictions,
|
||||
): InternalBackstageCredentials<BackstageServicePrincipal> {
|
||||
return Object.defineProperty(
|
||||
{
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
version: 'v1',
|
||||
principal: {
|
||||
type: 'service',
|
||||
subject: sub,
|
||||
accessRestrictions,
|
||||
},
|
||||
},
|
||||
'token',
|
||||
{
|
||||
const principal = createServicePrincipal(sub, accessRestrictions);
|
||||
const result = {
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
version: 'v1',
|
||||
principal,
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
token: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: token,
|
||||
},
|
||||
);
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => `backstageCredentials{${principal}}`,
|
||||
},
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export function createCredentialsWithUserPrincipal(
|
||||
@@ -53,36 +58,49 @@ export function createCredentialsWithUserPrincipal(
|
||||
expiresAt?: Date,
|
||||
actor?: string,
|
||||
): InternalBackstageCredentials<BackstageUserPrincipal> {
|
||||
return Object.defineProperty(
|
||||
{
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
version: 'v1',
|
||||
expiresAt,
|
||||
principal: {
|
||||
type: 'user',
|
||||
userEntityRef: sub,
|
||||
...(actor && {
|
||||
actor: { type: 'service', subject: actor },
|
||||
}),
|
||||
},
|
||||
},
|
||||
'token',
|
||||
{
|
||||
const principal = createUserPrincipal(
|
||||
sub,
|
||||
actor ? createServicePrincipal(actor) : undefined,
|
||||
);
|
||||
const result = {
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
version: 'v1',
|
||||
expiresAt,
|
||||
principal,
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
token: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: token,
|
||||
},
|
||||
);
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => `backstageCredentials{${principal}}`,
|
||||
},
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export function createCredentialsWithNonePrincipal(): InternalBackstageCredentials<BackstageNonePrincipal> {
|
||||
return {
|
||||
const principal = createNonePrincipal();
|
||||
const result = {
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
version: 'v1',
|
||||
principal: {
|
||||
type: 'none',
|
||||
principal,
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => `backstageCredentials{${principal}}`,
|
||||
},
|
||||
};
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export function toInternalBackstageCredentials(
|
||||
@@ -106,3 +124,74 @@ export function toInternalBackstageCredentials(
|
||||
|
||||
return internalCredentials;
|
||||
}
|
||||
|
||||
function createServicePrincipal(
|
||||
sub: string,
|
||||
accessRestrictions?: BackstagePrincipalAccessRestrictions,
|
||||
): BackstageServicePrincipal {
|
||||
const result = {
|
||||
type: 'service',
|
||||
subject: sub,
|
||||
accessRestrictions,
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => {
|
||||
let parts = sub;
|
||||
if (accessRestrictions) {
|
||||
const hash = createHash('sha256')
|
||||
.update(JSON.stringify(accessRestrictions))
|
||||
.digest('base64')
|
||||
.replace(/=+$/, '');
|
||||
parts += `,accessRestrictions=${hash}`;
|
||||
}
|
||||
return `servicePrincipal{${parts}}`;
|
||||
},
|
||||
},
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function createUserPrincipal(
|
||||
userEntityRef: string,
|
||||
actor?: BackstageServicePrincipal,
|
||||
): BackstageUserPrincipal {
|
||||
const result = {
|
||||
type: 'user',
|
||||
userEntityRef,
|
||||
actor,
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => {
|
||||
let parts = userEntityRef;
|
||||
if (actor) {
|
||||
parts += `,actor={${actor}}`;
|
||||
}
|
||||
return `userPrincipal{${parts}}`;
|
||||
},
|
||||
},
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function createNonePrincipal(): BackstageNonePrincipal {
|
||||
const result = {
|
||||
type: 'none',
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => 'nonePrincipal',
|
||||
},
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -170,4 +170,27 @@ describe('mockCredentials', () => {
|
||||
"Invalid user entity reference 'wrong', expected <kind>:<namespace>/<name>",
|
||||
);
|
||||
});
|
||||
|
||||
it('should have a serializable form', () => {
|
||||
expect(String(mockCredentials.service('my-service'))).toMatchInlineSnapshot(
|
||||
`"mockCredentials{servicePrincipal{my-service}}"`,
|
||||
);
|
||||
expect(
|
||||
String(mockCredentials.user('user:default/mock')),
|
||||
).toMatchInlineSnapshot(
|
||||
`"mockCredentials{userPrincipal{user:default/mock}}"`,
|
||||
);
|
||||
expect(
|
||||
String(
|
||||
mockCredentials.user('user:default/mock', {
|
||||
actor: { subject: 'my-actor' },
|
||||
}),
|
||||
),
|
||||
).toMatchInlineSnapshot(
|
||||
`"mockCredentials{userPrincipal{user:default/mock,actor={my-actor}}}"`,
|
||||
);
|
||||
expect(String(mockCredentials.none())).toMatchInlineSnapshot(
|
||||
`"mockCredentials{nonePrincipal}"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -76,10 +76,19 @@ export namespace mockCredentials {
|
||||
* Creates a mocked credentials object for a unauthenticated principal.
|
||||
*/
|
||||
export function none(): BackstageCredentials<BackstageNonePrincipal> {
|
||||
return {
|
||||
const result = {
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
principal: { type: 'none' },
|
||||
};
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: () => `mockCredentials{nonePrincipal}`,
|
||||
},
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,24 +120,32 @@ export namespace mockCredentials {
|
||||
options?: { actor?: { subject: string } },
|
||||
): BackstageCredentials<BackstageUserPrincipal> {
|
||||
validateUserEntityRef(userEntityRef);
|
||||
return Object.defineProperty(
|
||||
{
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
principal: {
|
||||
type: 'user',
|
||||
userEntityRef,
|
||||
...(options?.actor && {
|
||||
actor: { type: 'service', subject: options.actor.subject },
|
||||
}),
|
||||
},
|
||||
const result = {
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
principal: {
|
||||
type: 'user',
|
||||
userEntityRef,
|
||||
...(options?.actor && {
|
||||
actor: { type: 'service', subject: options.actor.subject } as const,
|
||||
}),
|
||||
},
|
||||
'token',
|
||||
{
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
value: () =>
|
||||
`mockCredentials{userPrincipal{${userEntityRef}${
|
||||
options?.actor ? `,actor={${options.actor.subject}}` : ''
|
||||
}}}`,
|
||||
},
|
||||
token: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
value: user.token(),
|
||||
},
|
||||
);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,14 +248,27 @@ export namespace mockCredentials {
|
||||
subject: string = DEFAULT_MOCK_SERVICE_SUBJECT,
|
||||
accessRestrictions?: BackstagePrincipalAccessRestrictions,
|
||||
): BackstageCredentials<BackstageServicePrincipal> {
|
||||
return {
|
||||
const result = {
|
||||
$$type: '@backstage/BackstageCredentials',
|
||||
principal: {
|
||||
type: 'service',
|
||||
subject,
|
||||
...(accessRestrictions ? { accessRestrictions } : {}),
|
||||
},
|
||||
};
|
||||
} as const;
|
||||
Object.defineProperties(result, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
value: () =>
|
||||
`mockCredentials{servicePrincipal{${subject}${
|
||||
accessRestrictions
|
||||
? `,accessRestrictions=${JSON.stringify(accessRestrictions)}`
|
||||
: ''
|
||||
}}}`,
|
||||
},
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+10
-12
@@ -28,30 +28,28 @@ export * from './components/Box';
|
||||
export * from './components/Grid';
|
||||
export * from './components/Flex';
|
||||
export * from './components/Container';
|
||||
export * from './components/Text';
|
||||
export * from './components/Heading';
|
||||
|
||||
// UI components
|
||||
export * from './components/Avatar';
|
||||
export * from './components/Button';
|
||||
export * from './components/ButtonIcon';
|
||||
export * from './components/ButtonLink';
|
||||
export * from './components/Checkbox';
|
||||
export * from './components/Collapsible';
|
||||
export * from './components/DataTable';
|
||||
export * from './components/FieldLabel';
|
||||
export * from './components/FieldError';
|
||||
export * from './components/Heading';
|
||||
export * from './components/Icon';
|
||||
export * from './components/Link';
|
||||
export * from './components/Menu';
|
||||
export * from './components/RadioGroup';
|
||||
export * from './components/ScrollArea';
|
||||
export * from './components/Select';
|
||||
export * from './components/Switch';
|
||||
export * from './components/ButtonIcon';
|
||||
export * from './components/ButtonLink';
|
||||
export * from './components/Checkbox';
|
||||
export * from './components/Table';
|
||||
export * from './components/Tabs';
|
||||
export * from './components/Text';
|
||||
export * from './components/TextField';
|
||||
export * from './components/Tooltip';
|
||||
export * from './components/Menu';
|
||||
export * from './components/ScrollArea';
|
||||
export * from './components/Link';
|
||||
export * from './components/Select';
|
||||
export * from './components/Switch';
|
||||
|
||||
// Types
|
||||
export * from './types';
|
||||
|
||||
@@ -5,13 +5,13 @@ module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, {
|
||||
name: 'path',
|
||||
importNames: ['resolve'],
|
||||
message:
|
||||
'Do not use path.resolve, use `resolveSafeChildPath` from `@backstage/backend-common` instead as it prevents security issues',
|
||||
'Do not use path.resolve, use `resolveSafeChildPath` from `@backstage/backend-plugin-api` instead as it prevents security issues',
|
||||
},
|
||||
],
|
||||
restrictedSrcSyntax: [
|
||||
{
|
||||
message:
|
||||
'Do not use path.resolve, use `resolveSafeChildPath` from `@backstage/backend-common` instead as it prevents security issues',
|
||||
'Do not use path.resolve, use `resolveSafeChildPath` from `@backstage/backend-plugin-api` instead as it prevents security issues',
|
||||
selector: 'MemberExpression[object.name="path"][property.name="resolve"]',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
"test": "backstage-cli package test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.25.0",
|
||||
"@backstage/backend-defaults": "workspace:^",
|
||||
"@backstage/backend-plugin-api": "workspace:^",
|
||||
"@backstage/catalog-model": "workspace:^",
|
||||
|
||||
@@ -14,7 +14,6 @@ import { Duration } from 'luxon';
|
||||
import { EventsService } from '@backstage/plugin-events-node';
|
||||
import { HumanDuration } from '@backstage/types';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { Knex } from 'knex';
|
||||
import { LoggerService } from '@backstage/backend-plugin-api';
|
||||
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
@@ -38,6 +37,7 @@ import { TemplateEntityStepV1beta3 } from '@backstage/plugin-scaffolder-common';
|
||||
import { TemplateFilter } from '@backstage/plugin-scaffolder-node';
|
||||
import { TemplateGlobal } from '@backstage/plugin-scaffolder-node';
|
||||
import { TemplateParametersV1beta3 } from '@backstage/plugin-scaffolder-common';
|
||||
import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import { UrlReaderService } from '@backstage/backend-plugin-api';
|
||||
import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
|
||||
@@ -442,19 +442,7 @@ export class TaskManager implements TaskContext {
|
||||
// (undocumented)
|
||||
get spec(): TaskSpecV1beta3;
|
||||
// (undocumented)
|
||||
updateCheckpoint?(
|
||||
options:
|
||||
| {
|
||||
key: string;
|
||||
status: 'success';
|
||||
value: JsonValue;
|
||||
}
|
||||
| {
|
||||
key: string;
|
||||
status: 'failed';
|
||||
reason: string;
|
||||
},
|
||||
): Promise<void>;
|
||||
updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise<void>;
|
||||
}
|
||||
|
||||
// @public @deprecated
|
||||
|
||||
@@ -14,12 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DatabaseManager } from '@backstage/backend-common';
|
||||
import { DatabaseManager } from '@backstage/backend-defaults/database';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { DatabaseTaskStore, RawDbTaskEventRow } from './DatabaseTaskStore';
|
||||
import { TaskSpec } from '@backstage/plugin-scaffolder-common';
|
||||
import { ConflictError } from '@backstage/errors';
|
||||
import { createMockDirectory } from '@backstage/backend-test-utils';
|
||||
import {
|
||||
mockServices,
|
||||
createMockDirectory,
|
||||
} from '@backstage/backend-test-utils';
|
||||
import fs from 'fs-extra';
|
||||
import { EventsService } from '@backstage/plugin-events-node';
|
||||
|
||||
@@ -33,7 +36,10 @@ const createStore = async (events?: EventsService) => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
).forPlugin('scaffolder');
|
||||
).forPlugin('scaffolder', {
|
||||
logger: mockServices.logger.mock(),
|
||||
lifecycle: mockServices.lifecycle.mock(),
|
||||
});
|
||||
const store = await DatabaseTaskStore.create({
|
||||
database: manager,
|
||||
events,
|
||||
|
||||
@@ -60,6 +60,10 @@ import { scaffolderActionRules } from '../../service/rules';
|
||||
import { createCounterMetric, createHistogramMetric } from '../../util/metrics';
|
||||
import { BackstageLoggerTransport, WinstonLogger } from './logger';
|
||||
import { convertFiltersToRecord } from '../../util/templating';
|
||||
import {
|
||||
CheckpointState,
|
||||
CheckpointContext,
|
||||
} from '@backstage/plugin-scaffolder-node/alpha';
|
||||
|
||||
type NunjucksWorkflowRunnerOptions = {
|
||||
workingDirectory: string;
|
||||
@@ -91,16 +95,6 @@ type TemplateContext = {
|
||||
};
|
||||
};
|
||||
|
||||
type CheckpointState =
|
||||
| {
|
||||
status: 'failed';
|
||||
reason: string;
|
||||
}
|
||||
| {
|
||||
status: 'success';
|
||||
value: JsonValue;
|
||||
};
|
||||
|
||||
const isValidTaskSpec = (taskSpec: TaskSpec): taskSpec is TaskSpecV1beta3 => {
|
||||
return taskSpec.apiVersion === 'scaffolder.backstage.io/v1beta3';
|
||||
};
|
||||
@@ -384,10 +378,9 @@ export class NunjucksWorkflowRunner implements WorkflowRunner {
|
||||
secrets: task.secrets ?? {},
|
||||
logger: taskLogger,
|
||||
workspacePath,
|
||||
async checkpoint<T extends JsonValue | void>(opts: {
|
||||
key?: string;
|
||||
fn: () => Promise<T> | T;
|
||||
}) {
|
||||
async checkpoint<T extends JsonValue | void>(
|
||||
opts: CheckpointContext<T>,
|
||||
) {
|
||||
const { key: checkpointKey, fn } = opts;
|
||||
const key = `v1.task.checkpoint.${step.id}.${checkpointKey}`;
|
||||
|
||||
@@ -396,9 +389,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner {
|
||||
|
||||
if (prevTaskState) {
|
||||
const prevState = (
|
||||
prevTaskState.state?.checkpoints as {
|
||||
[key: string]: CheckpointState;
|
||||
}
|
||||
prevTaskState.state?.checkpoints as CheckpointState
|
||||
)?.[key];
|
||||
|
||||
if (prevState && prevState.status === 'success') {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DatabaseManager } from '@backstage/backend-common';
|
||||
import { DatabaseManager } from '@backstage/backend-defaults/database';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { TaskSpec } from '@backstage/plugin-scaffolder-common';
|
||||
import {
|
||||
@@ -36,7 +36,10 @@ async function createStore(): Promise<DatabaseTaskStore> {
|
||||
},
|
||||
},
|
||||
}),
|
||||
).forPlugin('scaffolder');
|
||||
).forPlugin('scaffolder', {
|
||||
logger: mockServices.logger.mock(),
|
||||
lifecycle: mockServices.lifecycle.mock(),
|
||||
});
|
||||
|
||||
return await DatabaseTaskStore.create({
|
||||
database: manager,
|
||||
|
||||
@@ -32,30 +32,19 @@ import {
|
||||
TaskSecrets,
|
||||
TaskStatus,
|
||||
} from '@backstage/plugin-scaffolder-node';
|
||||
import { WorkspaceProvider } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import {
|
||||
JsonObject,
|
||||
JsonValue,
|
||||
Observable,
|
||||
createDeferred,
|
||||
} from '@backstage/types';
|
||||
CheckpointState,
|
||||
WorkspaceProvider,
|
||||
UpdateTaskCheckpointOptions,
|
||||
} from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import { JsonObject, Observable, createDeferred } from '@backstage/types';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
import { DefaultWorkspaceService, WorkspaceService } from './WorkspaceService';
|
||||
import { readDuration } from './helper';
|
||||
import { InternalTaskSecrets, TaskStore } from './types';
|
||||
|
||||
type TaskState = {
|
||||
checkpoints: {
|
||||
[key: string]:
|
||||
| {
|
||||
status: 'failed';
|
||||
reason: string;
|
||||
}
|
||||
| {
|
||||
status: 'success';
|
||||
value: JsonValue;
|
||||
};
|
||||
};
|
||||
checkpoints: CheckpointState;
|
||||
};
|
||||
/**
|
||||
* TaskManager
|
||||
@@ -152,20 +141,9 @@ export class TaskManager implements TaskContext {
|
||||
return this.storage.getTaskState?.({ taskId: this.task.taskId });
|
||||
}
|
||||
|
||||
async updateCheckpoint?(
|
||||
options:
|
||||
| {
|
||||
key: string;
|
||||
status: 'success';
|
||||
value: JsonValue;
|
||||
}
|
||||
| {
|
||||
key: string;
|
||||
status: 'failed';
|
||||
reason: string;
|
||||
},
|
||||
): Promise<void> {
|
||||
async updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise<void> {
|
||||
const { key, ...value } = options;
|
||||
|
||||
if (this.task.state) {
|
||||
(this.task.state as TaskState).checkpoints[key] = value;
|
||||
} else {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import os from 'os';
|
||||
import { DatabaseManager } from '@backstage/backend-common';
|
||||
import { DatabaseManager } from '@backstage/backend-defaults/database';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { DatabaseTaskStore } from './DatabaseTaskStore';
|
||||
import { StorageTaskBroker } from './StorageTaskBroker';
|
||||
@@ -49,7 +49,10 @@ async function createStore(): Promise<DatabaseTaskStore> {
|
||||
},
|
||||
},
|
||||
}),
|
||||
).forPlugin('scaffolder');
|
||||
).forPlugin('scaffolder', {
|
||||
logger: mockServices.logger.mock(),
|
||||
lifecycle: mockServices.lifecycle.mock(),
|
||||
});
|
||||
return await DatabaseTaskStore.create({
|
||||
database: manager,
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DatabaseManager } from '@backstage/backend-common';
|
||||
import { DatabaseManager } from '@backstage/backend-defaults/database';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import request from 'supertest';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
@@ -77,7 +77,10 @@ function createDatabase(): DatabaseService {
|
||||
},
|
||||
},
|
||||
}),
|
||||
).forPlugin('scaffolder');
|
||||
).forPlugin('scaffolder', {
|
||||
logger: mockServices.logger.mock(),
|
||||
lifecycle: mockServices.lifecycle.mock(),
|
||||
});
|
||||
}
|
||||
|
||||
const config = new ConfigReader({});
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
} from '@backstage/backend-test-utils';
|
||||
import { JsonObject, JsonValue } from '@backstage/types';
|
||||
import { ActionContext } from '@backstage/plugin-scaffolder-node';
|
||||
import { CheckpointContext } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import { loggerToWinstonLogger } from './loggerToWinstonLogger';
|
||||
|
||||
/**
|
||||
@@ -44,10 +45,9 @@ export function createMockActionContext<
|
||||
output: jest.fn(),
|
||||
createTemporaryDirectory: jest.fn(),
|
||||
input: {} as TActionInput,
|
||||
async checkpoint<T extends JsonValue | void>(opts: {
|
||||
key: string;
|
||||
fn: () => Promise<T> | T;
|
||||
}): Promise<T> {
|
||||
async checkpoint<T extends JsonValue | void>(
|
||||
opts: CheckpointContext<T>,
|
||||
): Promise<T> {
|
||||
return opts.fn();
|
||||
},
|
||||
getInitiatorCredentials: () => Promise.resolve(credentials),
|
||||
|
||||
@@ -27,6 +27,31 @@ export type AutocompleteHandler = ({
|
||||
}[];
|
||||
}>;
|
||||
|
||||
// @alpha
|
||||
export type CheckpointContext<T extends JsonValue | void = JsonValue> = {
|
||||
key: string;
|
||||
fn: () => Promise<T> | T;
|
||||
};
|
||||
|
||||
// @alpha
|
||||
export type CheckpointState = {
|
||||
[key: string]: CheckpointStateValue;
|
||||
};
|
||||
|
||||
// @alpha
|
||||
export type CheckpointStateValue<T extends JsonValue = JsonValue> =
|
||||
| {
|
||||
status: 'failed';
|
||||
reason: string;
|
||||
}
|
||||
| {
|
||||
status: 'success';
|
||||
value: T;
|
||||
};
|
||||
|
||||
// @alpha
|
||||
export type CheckpointStatus = 'failed' | 'success';
|
||||
|
||||
// @alpha (undocumented)
|
||||
export type CreatedTemplateFilter<
|
||||
TFunctionArgs extends [z.ZodTypeAny, ...z.ZodTypeAny[]],
|
||||
@@ -187,6 +212,11 @@ export type TemplateGlobalFunctionExample = {
|
||||
notes?: string;
|
||||
};
|
||||
|
||||
// @alpha
|
||||
export type UpdateTaskCheckpointOptions = {
|
||||
key: string;
|
||||
} & CheckpointStateValue;
|
||||
|
||||
// @alpha
|
||||
export interface WorkspaceProvider {
|
||||
// (undocumented)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
```ts
|
||||
import { BackstageCredentials } from '@backstage/backend-plugin-api';
|
||||
import { CheckpointContext } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import { Expand } from '@backstage/types';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
@@ -15,6 +16,7 @@ import { ScmIntegrations } from '@backstage/integration';
|
||||
import { SpawnOptionsWithoutStdio } from 'child_process';
|
||||
import { TaskSpec } from '@backstage/plugin-scaffolder-common';
|
||||
import { TemplateInfo } from '@backstage/plugin-scaffolder-common';
|
||||
import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import { UrlReaderService } from '@backstage/backend-plugin-api';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import { Writable } from 'stream';
|
||||
@@ -30,10 +32,9 @@ export type ActionContext<
|
||||
secrets?: TaskSecrets;
|
||||
workspacePath: string;
|
||||
input: TActionInput;
|
||||
checkpoint<T extends JsonValue | void>(opts: {
|
||||
key: string;
|
||||
fn: () => Promise<T> | T;
|
||||
}): Promise<T>;
|
||||
checkpoint<T extends JsonValue | void>(
|
||||
opts: CheckpointContext<T>,
|
||||
): Promise<T>;
|
||||
output(
|
||||
name: keyof TActionOutput,
|
||||
value: TActionOutput[keyof TActionOutput],
|
||||
@@ -446,19 +447,7 @@ export interface TaskContext {
|
||||
// (undocumented)
|
||||
taskId?: string;
|
||||
// (undocumented)
|
||||
updateCheckpoint?(
|
||||
options:
|
||||
| {
|
||||
key: string;
|
||||
status: 'success';
|
||||
value: JsonValue;
|
||||
}
|
||||
| {
|
||||
key: string;
|
||||
status: 'failed';
|
||||
reason: string;
|
||||
},
|
||||
): Promise<void>;
|
||||
updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise<void>;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
||||
@@ -23,6 +23,8 @@ import {
|
||||
BackstageCredentials,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import { CheckpointContext } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
|
||||
/**
|
||||
* ActionContext is passed into scaffolder actions.
|
||||
* @public
|
||||
@@ -36,10 +38,9 @@ export type ActionContext<
|
||||
secrets?: TaskSecrets;
|
||||
workspacePath: string;
|
||||
input: TActionInput;
|
||||
checkpoint<T extends JsonValue | void>(opts: {
|
||||
key: string;
|
||||
fn: () => Promise<T> | T;
|
||||
}): Promise<T>;
|
||||
checkpoint<T extends JsonValue | void>(
|
||||
opts: CheckpointContext<T>,
|
||||
): Promise<T>;
|
||||
output(
|
||||
name: keyof TActionOutput,
|
||||
value: TActionOutput[keyof TActionOutput],
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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 './types';
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { JsonValue } from '@backstage/types';
|
||||
|
||||
/**
|
||||
* The status of a checkpoint, indicating whether it succeeded or failed.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type CheckpointStatus = 'failed' | 'success';
|
||||
|
||||
/**
|
||||
* Represents the union of all possible checkpoint state values.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type CheckpointStateValue<T extends JsonValue = JsonValue> =
|
||||
| { status: 'failed'; reason: string }
|
||||
| { status: 'success'; value: T };
|
||||
|
||||
/**
|
||||
* A map of checkpoint keys to their states.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type CheckpointState = {
|
||||
[key: string]: CheckpointStateValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Context for checkpoint function invocation.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type CheckpointContext<T extends JsonValue | void = JsonValue> = {
|
||||
/**
|
||||
* Unique key for the checkpoint
|
||||
*/
|
||||
key: string;
|
||||
/**
|
||||
* Function to execute for the checkpoint
|
||||
*/
|
||||
fn: () => Promise<T> | T;
|
||||
};
|
||||
@@ -28,6 +28,7 @@ export * from '../tasks/alpha';
|
||||
export * from './filters';
|
||||
export * from './globals';
|
||||
export * from './types';
|
||||
export * from './checkpoints';
|
||||
|
||||
/**
|
||||
* Extension point for managing scaffolder actions.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CheckpointStateValue } from '../alpha';
|
||||
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
@@ -14,3 +16,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
export * from './serializer';
|
||||
|
||||
/**
|
||||
* Options for updating a checkpoint in a task.
|
||||
*
|
||||
* @alpha
|
||||
*/
|
||||
export type UpdateTaskCheckpointOptions = {
|
||||
key: string;
|
||||
} & CheckpointStateValue;
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
import { BackstageCredentials } from '@backstage/backend-plugin-api';
|
||||
import { TaskSpec } from '@backstage/plugin-scaffolder-common';
|
||||
import { JsonObject, JsonValue, Observable } from '@backstage/types';
|
||||
import { JsonObject, Observable } from '@backstage/types';
|
||||
import { UpdateTaskCheckpointOptions } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
|
||||
/**
|
||||
* TaskSecrets
|
||||
@@ -129,19 +130,7 @@ export interface TaskContext {
|
||||
| undefined
|
||||
>;
|
||||
|
||||
updateCheckpoint?(
|
||||
options:
|
||||
| {
|
||||
key: string;
|
||||
status: 'success';
|
||||
value: JsonValue;
|
||||
}
|
||||
| {
|
||||
key: string;
|
||||
status: 'failed';
|
||||
reason: string;
|
||||
},
|
||||
): Promise<void>;
|
||||
updateCheckpoint?(options: UpdateTaskCheckpointOptions): Promise<void>;
|
||||
|
||||
serializeWorkspace?(options: { path: string }): Promise<void>;
|
||||
|
||||
|
||||
@@ -7499,7 +7499,6 @@ __metadata:
|
||||
resolution: "@backstage/plugin-scaffolder-backend@workspace:plugins/scaffolder-backend"
|
||||
dependencies:
|
||||
"@backstage/backend-app-api": "workspace:^"
|
||||
"@backstage/backend-common": "npm:^0.25.0"
|
||||
"@backstage/backend-defaults": "workspace:^"
|
||||
"@backstage/backend-plugin-api": "workspace:^"
|
||||
"@backstage/backend-test-utils": "workspace:^"
|
||||
@@ -8757,9 +8756,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@changesets/assemble-release-plan@npm:^6.0.8":
|
||||
version: 6.0.8
|
||||
resolution: "@changesets/assemble-release-plan@npm:6.0.8"
|
||||
"@changesets/assemble-release-plan@npm:^6.0.9":
|
||||
version: 6.0.9
|
||||
resolution: "@changesets/assemble-release-plan@npm:6.0.9"
|
||||
dependencies:
|
||||
"@changesets/errors": "npm:^0.2.0"
|
||||
"@changesets/get-dependents-graph": "npm:^2.1.3"
|
||||
@@ -8767,7 +8766,7 @@ __metadata:
|
||||
"@changesets/types": "npm:^6.1.0"
|
||||
"@manypkg/get-packages": "npm:^1.1.3"
|
||||
semver: "npm:^7.5.3"
|
||||
checksum: 10/5d01fc42c67229874cc70b93fbdc971e11909aa7a72f1909c585ecb3fdc69f3ac105d243e1341cd5b07c02dee133be461fa48138125f00d137e71f8b7e8f428e
|
||||
checksum: 10/f84656eabb700ed77f97751b282e1701636ed45a44b443abd9af0291870495cc046fee301478010f39a1dc455799065ae007b9d7d2bb5ae8b793b65bbb8e052a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8781,16 +8780,16 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@changesets/cli@npm:^2.14.0":
|
||||
version: 2.29.4
|
||||
resolution: "@changesets/cli@npm:2.29.4"
|
||||
version: 2.29.5
|
||||
resolution: "@changesets/cli@npm:2.29.5"
|
||||
dependencies:
|
||||
"@changesets/apply-release-plan": "npm:^7.0.12"
|
||||
"@changesets/assemble-release-plan": "npm:^6.0.8"
|
||||
"@changesets/assemble-release-plan": "npm:^6.0.9"
|
||||
"@changesets/changelog-git": "npm:^0.2.1"
|
||||
"@changesets/config": "npm:^3.1.1"
|
||||
"@changesets/errors": "npm:^0.2.0"
|
||||
"@changesets/get-dependents-graph": "npm:^2.1.3"
|
||||
"@changesets/get-release-plan": "npm:^4.0.12"
|
||||
"@changesets/get-release-plan": "npm:^4.0.13"
|
||||
"@changesets/git": "npm:^3.0.4"
|
||||
"@changesets/logger": "npm:^0.1.1"
|
||||
"@changesets/pre": "npm:^2.0.2"
|
||||
@@ -8814,7 +8813,7 @@ __metadata:
|
||||
term-size: "npm:^2.1.0"
|
||||
bin:
|
||||
changeset: bin.js
|
||||
checksum: 10/fc325447b81a811464107e72a687f6c0414c5f928e518cb122d1efde1d71c205b1972464795ab97fb26087900ea55b99a551e9a010c9681def3d7561fd1c3f0b
|
||||
checksum: 10/f401da29025d7bcc07b732bb09a9627f785bfc21c7c2005861d11ffea732bc14d33394fc2fcae50cc5f2b710f6080c5babe2fa90d432de5fdb47ae6afc147936
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8854,17 +8853,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@changesets/get-release-plan@npm:^4.0.12":
|
||||
version: 4.0.12
|
||||
resolution: "@changesets/get-release-plan@npm:4.0.12"
|
||||
"@changesets/get-release-plan@npm:^4.0.13":
|
||||
version: 4.0.13
|
||||
resolution: "@changesets/get-release-plan@npm:4.0.13"
|
||||
dependencies:
|
||||
"@changesets/assemble-release-plan": "npm:^6.0.8"
|
||||
"@changesets/assemble-release-plan": "npm:^6.0.9"
|
||||
"@changesets/config": "npm:^3.1.1"
|
||||
"@changesets/pre": "npm:^2.0.2"
|
||||
"@changesets/read": "npm:^0.6.5"
|
||||
"@changesets/types": "npm:^6.1.0"
|
||||
"@manypkg/get-packages": "npm:^1.1.3"
|
||||
checksum: 10/d6482ecb6f1c2c47266493a36d05b484f0950d0a4472820649e953d073e3fdd612cdd8a4df9e3d7e00756d4e446dae639f9d6e0dab8a25f76bb6df77cd91c21c
|
||||
checksum: 10/9983fae5a68012c4c418ddd62f2fb3d325363f21160252ff7b868503a1a2effb8fdd32e4a0289b72653afc3605ce19d163ff69205c942a0004efb571a5f78fd0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -9105,11 +9104,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@dagrejs/dagre@npm:^1.1.4":
|
||||
version: 1.1.4
|
||||
resolution: "@dagrejs/dagre@npm:1.1.4"
|
||||
version: 1.1.5
|
||||
resolution: "@dagrejs/dagre@npm:1.1.5"
|
||||
dependencies:
|
||||
"@dagrejs/graphlib": "npm:2.2.4"
|
||||
checksum: 10/0b3744b170c68ae0666e03aca19c3100d5131feafeb54b3ea096b749a9f0fe5385b8bd8889c11a49493cfab945b2486b9e30bc41b321755ed718e9f5cb4b74f1
|
||||
checksum: 10/c00abd1e04d19f90ad8dfa0a4e16365371bc4309affead3827a1b39f6b0b946643b8af0b1e5519011deca3fda4c7471b27e9ebb03423309a94f95ac0b881ac4f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -14865,13 +14864,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@playwright/test@npm:^1.32.3":
|
||||
version: 1.53.0
|
||||
resolution: "@playwright/test@npm:1.53.0"
|
||||
version: 1.53.1
|
||||
resolution: "@playwright/test@npm:1.53.1"
|
||||
dependencies:
|
||||
playwright: "npm:1.53.0"
|
||||
playwright: "npm:1.53.1"
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: 10/968df4fba133dd18b8c65504c3cc5a3a6071e49f0706c6524711cdfab321a51debfeb506b9ff0a8f7dd8ce3015921d82fa51429d8f11d392cc68de1938703c33
|
||||
checksum: 10/98fb9b962710183d465b695daab2006296fd9a703ecb1b763a38cd12a39f7d6066f9539d1758e54313d393353fafb16b90fb31e4add1ca99ffec99b8b1b40fb9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -21782,9 +21781,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/lodash@npm:^4.14.151":
|
||||
version: 4.17.17
|
||||
resolution: "@types/lodash@npm:4.17.17"
|
||||
checksum: 10/496459a3cb1a0733bb60532de3899ad6297717af0b9b26ad6821154b2005fec86f29ccd47a2e6f4da4a8c7c818bb8ae73901144e8057ea86b7b02a3d7bb9d13f
|
||||
version: 4.17.18
|
||||
resolution: "@types/lodash@npm:4.17.18"
|
||||
checksum: 10/54ebb15b29925112dbe9da3abd99fb80d7202bc5ba20fc1b4fc8ea835d0012f00cbd9a3e7f367b70e7c3f2d5ee635964e3920a489625647b558f02994b3dd381
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -42032,27 +42031,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright-core@npm:1.53.0":
|
||||
version: 1.53.0
|
||||
resolution: "playwright-core@npm:1.53.0"
|
||||
"playwright-core@npm:1.53.1":
|
||||
version: 1.53.1
|
||||
resolution: "playwright-core@npm:1.53.1"
|
||||
bin:
|
||||
playwright-core: cli.js
|
||||
checksum: 10/881f27a9b7edd9954700489a5a4212cb91bcada226fd1d79a239b2eab0f333df1e2e41e275e6fa846d7f57c6a92afe14dca33ca7a2ce303dfb687d02511b7c69
|
||||
checksum: 10/d0ea8674c3abb76069255ca81bc0dfdef3f9548207f1404eec036bb8724135710f25ee791bfd7c043d5b9c2ccfa42288b0308d61dc5efc60a13b18811a15c4cd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright@npm:1.53.0":
|
||||
version: 1.53.0
|
||||
resolution: "playwright@npm:1.53.0"
|
||||
"playwright@npm:1.53.1":
|
||||
version: 1.53.1
|
||||
resolution: "playwright@npm:1.53.1"
|
||||
dependencies:
|
||||
fsevents: "npm:2.3.2"
|
||||
playwright-core: "npm:1.53.0"
|
||||
playwright-core: "npm:1.53.1"
|
||||
dependenciesMeta:
|
||||
fsevents:
|
||||
optional: true
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: 10/0b0258630f39b4d6ff1555d008ee4d591fe45cbe1e0f643a612397e3e6b1f7a99a2037a957eaa7351edd907ba10966ba105b2d244eafd1b247378910b660f086
|
||||
checksum: 10/74b3178d5ae3fde8de08fe6c221578530368f1abb8794fce234d06e0043178201eb3b7410354418517f23c105bd54ac1432da5f46c50353a5e6a80198a95f2cf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user