@backstage/plugin-scaffolder-backend 1.10.0-next.1 → 1.10.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/alpha/package.json +1 -1
- package/dist/index.alpha.d.ts +4 -0
- package/dist/index.beta.d.ts +4 -0
- package/dist/index.cjs.js +138 -8
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,92 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder-backend
|
|
2
2
|
|
|
3
|
+
## 1.10.0-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2fadff2a25: Change scaffolder task actions to include markdown to demonstrate the new `ActionsPage` markdown feature.
|
|
8
|
+
- b44eb68bcb: This patch adds changes to provide examples alongside scaffolder task actions.
|
|
9
|
+
|
|
10
|
+
The `createTemplateAction` function now takes a list of examples e.g.
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
const actionExamples = [
|
|
14
|
+
{
|
|
15
|
+
description: 'Example 1',
|
|
16
|
+
example: yaml.stringify({
|
|
17
|
+
steps: [
|
|
18
|
+
{
|
|
19
|
+
action: 'test:action',
|
|
20
|
+
id: 'test',
|
|
21
|
+
input: {
|
|
22
|
+
input1: 'value',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
}),
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export function createTestAction() {
|
|
31
|
+
return createTemplateAction({
|
|
32
|
+
id: 'test:action',
|
|
33
|
+
examples: [
|
|
34
|
+
{
|
|
35
|
+
description: 'Example 1',
|
|
36
|
+
examples: actionExamples
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
...,
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
These examples can be retrieved later from the api.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
curl http://localhost:7007/api/scaffolder/v2/actions
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
[
|
|
51
|
+
{
|
|
52
|
+
"id": "test:action",
|
|
53
|
+
"examples": [
|
|
54
|
+
{
|
|
55
|
+
"description": "Example 1",
|
|
56
|
+
"example": "steps:\n - action: test:action\n id: test\n input:\n input1: value\n"
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
"schema": {
|
|
60
|
+
"input": {
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"input1": {
|
|
64
|
+
"title": "Input 1",
|
|
65
|
+
"type": "string"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- 8e06f3cf00: Switched imports of `loggerToWinstonLogger` to `@backstage/backend-common`.
|
|
75
|
+
- Updated dependencies
|
|
76
|
+
- @backstage/backend-plugin-api@0.3.0-next.1
|
|
77
|
+
- @backstage/backend-common@0.18.0-next.1
|
|
78
|
+
- @backstage/backend-tasks@0.4.1-next.1
|
|
79
|
+
- @backstage/catalog-client@1.3.0-next.2
|
|
80
|
+
- @backstage/plugin-catalog-backend@1.7.0-next.2
|
|
81
|
+
- @backstage/plugin-catalog-node@1.3.1-next.2
|
|
82
|
+
- @backstage/plugin-auth-node@0.2.9-next.1
|
|
83
|
+
- @backstage/catalog-model@1.1.5-next.1
|
|
84
|
+
- @backstage/config@1.0.6-next.0
|
|
85
|
+
- @backstage/errors@1.1.4
|
|
86
|
+
- @backstage/integration@1.4.2-next.0
|
|
87
|
+
- @backstage/types@1.0.2
|
|
88
|
+
- @backstage/plugin-scaffolder-common@1.2.4-next.1
|
|
89
|
+
|
|
3
90
|
## 1.10.0-next.1
|
|
4
91
|
|
|
5
92
|
### Minor Changes
|
package/alpha/package.json
CHANGED
package/dist/index.alpha.d.ts
CHANGED
|
@@ -1063,6 +1063,10 @@ export declare class TaskWorker {
|
|
|
1063
1063
|
export declare type TemplateAction<Input extends JsonObject> = {
|
|
1064
1064
|
id: string;
|
|
1065
1065
|
description?: string;
|
|
1066
|
+
examples?: {
|
|
1067
|
+
description: string;
|
|
1068
|
+
example: string;
|
|
1069
|
+
}[];
|
|
1066
1070
|
supportsDryRun?: boolean;
|
|
1067
1071
|
schema?: {
|
|
1068
1072
|
input?: Schema;
|
package/dist/index.beta.d.ts
CHANGED
|
@@ -1045,6 +1045,10 @@ export declare class TaskWorker {
|
|
|
1045
1045
|
export declare type TemplateAction<Input extends JsonObject> = {
|
|
1046
1046
|
id: string;
|
|
1047
1047
|
description?: string;
|
|
1048
|
+
examples?: {
|
|
1049
|
+
description: string;
|
|
1050
|
+
example: string;
|
|
1051
|
+
}[];
|
|
1048
1052
|
supportsDryRun?: boolean;
|
|
1049
1053
|
schema?: {
|
|
1050
1054
|
input?: Schema;
|
package/dist/index.cjs.js
CHANGED
|
@@ -4,8 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var errors = require('@backstage/errors');
|
|
6
6
|
var catalogModel = require('@backstage/catalog-model');
|
|
7
|
-
var fs = require('fs-extra');
|
|
8
7
|
var yaml = require('yaml');
|
|
8
|
+
var fs = require('fs-extra');
|
|
9
9
|
var backendCommon = require('@backstage/backend-common');
|
|
10
10
|
var integration = require('@backstage/integration');
|
|
11
11
|
var path = require('path');
|
|
@@ -62,8 +62,9 @@ function _interopNamespace(e) {
|
|
|
62
62
|
return Object.freeze(n);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
var
|
|
65
|
+
var yaml__default = /*#__PURE__*/_interopDefaultLegacy(yaml);
|
|
66
66
|
var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
|
|
67
|
+
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
67
68
|
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
68
69
|
var globby__default = /*#__PURE__*/_interopDefaultLegacy(globby);
|
|
69
70
|
var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
|
|
@@ -81,11 +82,30 @@ const createTemplateAction = (templateAction) => {
|
|
|
81
82
|
return templateAction;
|
|
82
83
|
};
|
|
83
84
|
|
|
85
|
+
const id$2 = "catalog:register";
|
|
86
|
+
const examples$2 = [
|
|
87
|
+
{
|
|
88
|
+
description: "Register with the catalog",
|
|
89
|
+
example: yaml__default["default"].stringify({
|
|
90
|
+
steps: [
|
|
91
|
+
{
|
|
92
|
+
action: id$2,
|
|
93
|
+
id: "register-with-catalog",
|
|
94
|
+
name: "Register with the catalog",
|
|
95
|
+
input: {
|
|
96
|
+
catalogInfoUrl: "http://github.com/backstage/backstage/blob/master/catalog-info.yaml"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
];
|
|
84
103
|
function createCatalogRegisterAction(options) {
|
|
85
104
|
const { catalogClient, integrations } = options;
|
|
86
105
|
return createTemplateAction({
|
|
87
|
-
id:
|
|
106
|
+
id: id$2,
|
|
88
107
|
description: "Registers entities from a catalog descriptor file in the workspace into the software catalog.",
|
|
108
|
+
examples: examples$2,
|
|
89
109
|
schema: {
|
|
90
110
|
input: {
|
|
91
111
|
oneOf: [
|
|
@@ -203,10 +223,41 @@ function createCatalogRegisterAction(options) {
|
|
|
203
223
|
});
|
|
204
224
|
}
|
|
205
225
|
|
|
226
|
+
const id$1 = "catalog:write";
|
|
227
|
+
const examples$1 = [
|
|
228
|
+
{
|
|
229
|
+
description: "Write a catalog yaml file",
|
|
230
|
+
example: yaml__namespace.stringify({
|
|
231
|
+
steps: [
|
|
232
|
+
{
|
|
233
|
+
action: id$1,
|
|
234
|
+
id: "create-catalog-info-file",
|
|
235
|
+
name: "Create catalog file",
|
|
236
|
+
input: {
|
|
237
|
+
entity: {
|
|
238
|
+
apiVersion: "backstage.io/v1alpha1",
|
|
239
|
+
kind: "Component",
|
|
240
|
+
metadata: {
|
|
241
|
+
name: "test",
|
|
242
|
+
annotations: {}
|
|
243
|
+
},
|
|
244
|
+
spec: {
|
|
245
|
+
type: "service",
|
|
246
|
+
lifecycle: "production",
|
|
247
|
+
owner: "default/owner"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
];
|
|
206
256
|
function createCatalogWriteAction() {
|
|
207
257
|
return createTemplateAction({
|
|
208
|
-
id:
|
|
258
|
+
id: id$1,
|
|
209
259
|
description: "Writes the catalog-info.yaml for your template",
|
|
260
|
+
examples: examples$1,
|
|
210
261
|
schema: {
|
|
211
262
|
input: {
|
|
212
263
|
type: "object",
|
|
@@ -237,10 +288,44 @@ function createCatalogWriteAction() {
|
|
|
237
288
|
});
|
|
238
289
|
}
|
|
239
290
|
|
|
291
|
+
const id = "debug:log";
|
|
292
|
+
const examples = [
|
|
293
|
+
{
|
|
294
|
+
description: "Write a debug message",
|
|
295
|
+
example: yaml__default["default"].stringify({
|
|
296
|
+
steps: [
|
|
297
|
+
{
|
|
298
|
+
action: id,
|
|
299
|
+
id: "write-debug-line",
|
|
300
|
+
name: 'Write "Hello Backstage!" log line',
|
|
301
|
+
input: {
|
|
302
|
+
message: "Hello Backstage!"
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
})
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
description: "List the workspace directory",
|
|
310
|
+
example: yaml__default["default"].stringify({
|
|
311
|
+
steps: [
|
|
312
|
+
{
|
|
313
|
+
action: id,
|
|
314
|
+
id: "write-workspace-directory",
|
|
315
|
+
name: "List the workspace directory",
|
|
316
|
+
input: {
|
|
317
|
+
listWorkspace: true
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
]
|
|
321
|
+
})
|
|
322
|
+
}
|
|
323
|
+
];
|
|
240
324
|
function createDebugLogAction() {
|
|
241
325
|
return createTemplateAction({
|
|
242
|
-
id
|
|
326
|
+
id,
|
|
243
327
|
description: "Writes a message into the log or lists all files in the workspace.",
|
|
328
|
+
examples,
|
|
244
329
|
schema: {
|
|
245
330
|
input: {
|
|
246
331
|
type: "object",
|
|
@@ -327,7 +412,7 @@ function createFetchPlainAction(options) {
|
|
|
327
412
|
const { reader, integrations } = options;
|
|
328
413
|
return createTemplateAction({
|
|
329
414
|
id: "fetch:plain",
|
|
330
|
-
description: "Downloads content and places it in the workspace, or optionally in a subdirectory specified by the
|
|
415
|
+
description: "Downloads content and places it in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.",
|
|
331
416
|
schema: {
|
|
332
417
|
input: {
|
|
333
418
|
type: "object",
|
|
@@ -512,7 +597,7 @@ function createFetchTemplateAction(options) {
|
|
|
512
597
|
} = options;
|
|
513
598
|
return createTemplateAction({
|
|
514
599
|
id: "fetch:template",
|
|
515
|
-
description: "Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the
|
|
600
|
+
description: "Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the `targetPath` input option.",
|
|
516
601
|
schema: {
|
|
517
602
|
input: {
|
|
518
603
|
type: "object",
|
|
@@ -1007,6 +1092,13 @@ const enableBranchProtectionOnDefaultRepoBranch = async ({
|
|
|
1007
1092
|
try {
|
|
1008
1093
|
await client.rest.repos.updateBranchProtection({
|
|
1009
1094
|
mediaType: {
|
|
1095
|
+
/**
|
|
1096
|
+
* 👇 we need this preview because allowing a custom
|
|
1097
|
+
* reviewer count on branch protection is a preview
|
|
1098
|
+
* feature
|
|
1099
|
+
*
|
|
1100
|
+
* More here: https://docs.github.com/en/rest/overview/api-previews#require-multiple-approving-reviews
|
|
1101
|
+
*/
|
|
1010
1102
|
previews: ["luke-cage-preview"]
|
|
1011
1103
|
},
|
|
1012
1104
|
owner,
|
|
@@ -1056,6 +1148,7 @@ async function getOctokitOptions(options) {
|
|
|
1056
1148
|
const { integrations, credentialsProvider, repoUrl, token } = options;
|
|
1057
1149
|
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
|
1058
1150
|
const requestOptions = {
|
|
1151
|
+
// set timeout to 60 seconds
|
|
1059
1152
|
timeout: DEFAULT_TIMEOUT_MS
|
|
1060
1153
|
};
|
|
1061
1154
|
if (!owner) {
|
|
@@ -3155,6 +3248,8 @@ async function serializeDirectoryContents(sourcePath, options) {
|
|
|
3155
3248
|
dot: true,
|
|
3156
3249
|
gitignore: options == null ? void 0 : options.gitignore,
|
|
3157
3250
|
followSymbolicLinks: false,
|
|
3251
|
+
// In order to pick up 'broken' symlinks, we oxymoronically request files AND folders yet we filter out folders
|
|
3252
|
+
// This is because broken symlinks aren't classed as files so we need to glob everything
|
|
3158
3253
|
onlyFiles: false,
|
|
3159
3254
|
objectMode: true,
|
|
3160
3255
|
stats: true
|
|
@@ -3352,7 +3447,16 @@ const createPublishGithubPullRequestAction = ({
|
|
|
3352
3447
|
directoryContents.map((file) => [
|
|
3353
3448
|
targetPath ? path__default["default"].posix.join(targetPath, file.path) : file.path,
|
|
3354
3449
|
{
|
|
3450
|
+
// See the properties of tree items
|
|
3451
|
+
// in https://docs.github.com/en/rest/reference/git#trees
|
|
3355
3452
|
mode: determineFileMode(file),
|
|
3453
|
+
// Always use base64 encoding where possible to avoid doubling a binary file in size
|
|
3454
|
+
// due to interpreting a binary file as utf-8 and sending github
|
|
3455
|
+
// the utf-8 encoded content. Symlinks are kept as utf-8 to avoid them
|
|
3456
|
+
// being formatted as a series of scrambled characters
|
|
3457
|
+
//
|
|
3458
|
+
// For example, the original gradle-wrapper.jar is 57.8k in https://github.com/kennethzfeng/pull-request-test/pull/5/files.
|
|
3459
|
+
// Its size could be doubled to 98.3K (See https://github.com/kennethzfeng/pull-request-test/pull/4/files)
|
|
3356
3460
|
encoding: determineFileEncoding(file),
|
|
3357
3461
|
content: file.content.toString(determineFileEncoding(file))
|
|
3358
3462
|
}
|
|
@@ -3589,6 +3693,7 @@ const createPublishGitlabMergeRequestAction = (options) => {
|
|
|
3589
3693
|
title: "Repository Location",
|
|
3590
3694
|
description: `Accepts the format 'gitlab.com/group_name/project_name' where 'project_name' is the repository name and 'group_name' is a group or username`
|
|
3591
3695
|
},
|
|
3696
|
+
/** @deprecated projectID is passed as query parameters in the repoUrl */
|
|
3592
3697
|
projectid: {
|
|
3593
3698
|
type: "string",
|
|
3594
3699
|
title: "projectid",
|
|
@@ -3990,6 +4095,7 @@ class DatabaseTaskStore {
|
|
|
3990
4095
|
const updateCount = await tx("tasks").where({ id: task.id, status: "open" }).update({
|
|
3991
4096
|
status: "processing",
|
|
3992
4097
|
last_heartbeat_at: this.db.fn.now(),
|
|
4098
|
+
// remove the secrets when moving moving to processing state.
|
|
3993
4099
|
secrets: null
|
|
3994
4100
|
});
|
|
3995
4101
|
if (updateCount < 1) {
|
|
@@ -4140,6 +4246,7 @@ class DatabaseTaskStore {
|
|
|
4140
4246
|
}
|
|
4141
4247
|
|
|
4142
4248
|
class TaskManager {
|
|
4249
|
+
// Runs heartbeat internally
|
|
4143
4250
|
constructor(task, storage, logger) {
|
|
4144
4251
|
this.task = task;
|
|
4145
4252
|
this.storage = storage;
|
|
@@ -4223,6 +4330,9 @@ class StorageTaskBroker {
|
|
|
4223
4330
|
}
|
|
4224
4331
|
return await this.storage.list({ createdBy: options == null ? void 0 : options.createdBy });
|
|
4225
4332
|
}
|
|
4333
|
+
/**
|
|
4334
|
+
* {@inheritdoc TaskBroker.claim}
|
|
4335
|
+
*/
|
|
4226
4336
|
async claim() {
|
|
4227
4337
|
for (; ; ) {
|
|
4228
4338
|
const pendingTask = await this.storage.claimTask();
|
|
@@ -4241,6 +4351,9 @@ class StorageTaskBroker {
|
|
|
4241
4351
|
await this.waitForDispatch();
|
|
4242
4352
|
}
|
|
4243
4353
|
}
|
|
4354
|
+
/**
|
|
4355
|
+
* {@inheritdoc TaskBroker.dispatch}
|
|
4356
|
+
*/
|
|
4244
4357
|
async dispatch(options) {
|
|
4245
4358
|
const taskRow = await this.storage.createTask(options);
|
|
4246
4359
|
this.signalDispatch();
|
|
@@ -4248,9 +4361,15 @@ class StorageTaskBroker {
|
|
|
4248
4361
|
taskId: taskRow.taskId
|
|
4249
4362
|
};
|
|
4250
4363
|
}
|
|
4364
|
+
/**
|
|
4365
|
+
* {@inheritdoc TaskBroker.get}
|
|
4366
|
+
*/
|
|
4251
4367
|
async get(taskId) {
|
|
4252
4368
|
return this.storage.getTask(taskId);
|
|
4253
4369
|
}
|
|
4370
|
+
/**
|
|
4371
|
+
* {@inheritdoc TaskBroker.event$}
|
|
4372
|
+
*/
|
|
4254
4373
|
event$(options) {
|
|
4255
4374
|
return new ObservableImpl__default["default"]((observer) => {
|
|
4256
4375
|
const { taskId } = options;
|
|
@@ -4272,6 +4391,9 @@ class StorageTaskBroker {
|
|
|
4272
4391
|
};
|
|
4273
4392
|
});
|
|
4274
4393
|
}
|
|
4394
|
+
/**
|
|
4395
|
+
* {@inheritdoc TaskBroker.vacuumTasks}
|
|
4396
|
+
*/
|
|
4275
4397
|
async vacuumTasks(options) {
|
|
4276
4398
|
const { tasks } = await this.storage.listStaleTasks(options);
|
|
4277
4399
|
await Promise.all(
|
|
@@ -4441,6 +4563,10 @@ class NunjucksWorkflowRunner {
|
|
|
4441
4563
|
);
|
|
4442
4564
|
const { integrations } = this.options;
|
|
4443
4565
|
const renderTemplate = await SecureTemplater.loadRenderer({
|
|
4566
|
+
// TODO(blam): let's work out how we can deprecate this.
|
|
4567
|
+
// We shouldn't really need to be exposing these now we can deal with
|
|
4568
|
+
// objects in the params block.
|
|
4569
|
+
// Maybe we can expose a new RepoUrlPicker with secrets for V3 that provides an object already.
|
|
4444
4570
|
parseRepoUrl(url) {
|
|
4445
4571
|
return parseRepoUrl(url, integrations);
|
|
4446
4572
|
},
|
|
@@ -4693,6 +4819,7 @@ class TaskWorker {
|
|
|
4693
4819
|
workingDirectory,
|
|
4694
4820
|
additionalTemplateFilters,
|
|
4695
4821
|
concurrentTasksLimit = 10,
|
|
4822
|
+
// from 1 to Infinity
|
|
4696
4823
|
additionalTemplateGlobals
|
|
4697
4824
|
} = options;
|
|
4698
4825
|
const workflowRunner = new NunjucksWorkflowRunner({
|
|
@@ -4809,6 +4936,7 @@ function createDryRunner(options) {
|
|
|
4809
4936
|
}
|
|
4810
4937
|
},
|
|
4811
4938
|
secrets: input.secrets,
|
|
4939
|
+
// No need to update this at the end of the run, so just hard-code it
|
|
4812
4940
|
done: false,
|
|
4813
4941
|
isDryRun: true,
|
|
4814
4942
|
getWorkspaceName: async () => `dry-run-${dryRunId}`,
|
|
@@ -4963,6 +5091,7 @@ async function createRouter(options) {
|
|
|
4963
5091
|
await scheduler.scheduleTask({
|
|
4964
5092
|
id: "close_stale_tasks",
|
|
4965
5093
|
frequency: { cron: "*/5 * * * *" },
|
|
5094
|
+
// every 5 minutes, also supports Duration
|
|
4966
5095
|
timeout: { minutes: 15 },
|
|
4967
5096
|
fn: async () => {
|
|
4968
5097
|
const { tasks } = await databaseTaskStore.listStaleTasks({
|
|
@@ -5051,6 +5180,7 @@ async function createRouter(options) {
|
|
|
5051
5180
|
return {
|
|
5052
5181
|
id: action.id,
|
|
5053
5182
|
description: action.description,
|
|
5183
|
+
examples: action.examples,
|
|
5054
5184
|
schema: action.schema
|
|
5055
5185
|
};
|
|
5056
5186
|
});
|
|
@@ -5409,7 +5539,7 @@ const scaffolderPlugin = backendPluginApi.createBackendPlugin({
|
|
|
5409
5539
|
taskWorkers,
|
|
5410
5540
|
additionalTemplateGlobals
|
|
5411
5541
|
} = options;
|
|
5412
|
-
const log =
|
|
5542
|
+
const log = backendCommon.loggerToWinstonLogger(logger);
|
|
5413
5543
|
const actions = options.actions || [
|
|
5414
5544
|
...actionsExtensions.actions,
|
|
5415
5545
|
...createBuiltinActions({
|