Merge branch 'master' of https://github.com/backstage/backstage into fix/scaffolder-after-zero-query-param
This commit is contained in:
@@ -1,5 +1,46 @@
|
||||
# @backstage/plugin-scaffolder-backend
|
||||
|
||||
## 3.4.0-next.2
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 5af48e7: Migrated permission registration to use the `PermissionsRegistryService` instead of the deprecated `createPermissionIntegrationRouter`. This fixes an issue where scaffolder permissions were not visible to RBAC plugins because the `actionsRegistryServiceRef` dependency caused an empty permissions metadata router to shadow the scaffolder's actual permission metadata. The old `createPermissionIntegrationRouter` path is retained as a fallback for standalone `createRouter` usage.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 482ceed: Migrated from `assertError` to `toError` for error handling.
|
||||
- 961e274: Migrated OpenTelemetry metrics to use the `MetricsService` from `@backstage/backend-plugin-api/alpha` instead of the raw `@opentelemetry/api` meter.
|
||||
- Updated dependencies
|
||||
- @backstage/errors@1.3.0-next.0
|
||||
- @backstage/plugin-catalog-node@2.2.0-next.2
|
||||
- @backstage/plugin-scaffolder-node@0.13.2-next.2
|
||||
- @backstage/integration@2.0.1-next.0
|
||||
- @backstage/backend-openapi-utils@0.6.8-next.2
|
||||
- @backstage/backend-plugin-api@1.9.0-next.2
|
||||
- @backstage/catalog-model@1.7.8-next.0
|
||||
- @backstage/config@1.3.7-next.0
|
||||
- @backstage/plugin-events-node@0.4.21-next.2
|
||||
- @backstage/plugin-permission-common@0.9.8-next.0
|
||||
- @backstage/plugin-permission-node@0.10.12-next.2
|
||||
- @backstage/plugin-scaffolder-common@2.0.1-next.0
|
||||
|
||||
## 3.3.0-next.1
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 309b712: Added a new `execute-template` actions registry action that executes a scaffolder template with provided input values and returns a task ID for tracking progress.
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4559806: Removed unnecessary empty `examples` array from actions bridged via the actions registry.
|
||||
- Updated dependencies
|
||||
- @backstage/backend-plugin-api@1.9.0-next.1
|
||||
- @backstage/backend-openapi-utils@0.6.8-next.1
|
||||
- @backstage/plugin-catalog-node@2.1.1-next.1
|
||||
- @backstage/plugin-events-node@0.4.21-next.1
|
||||
- @backstage/plugin-permission-node@0.10.12-next.1
|
||||
- @backstage/plugin-scaffolder-node@0.13.1-next.1
|
||||
|
||||
## 3.2.1-next.0
|
||||
|
||||
### Patch Changes
|
||||
@@ -5634,7 +5675,7 @@
|
||||
- `step`: The name of the step that was run
|
||||
- `result`: A string describing whether the task ran successfully, failed, or was skipped
|
||||
|
||||
You can find a guide for running Prometheus metrics here: https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/prometheus-metrics.md
|
||||
You can find a guide for running Prometheus metrics here: https://github.com/backstage/backstage/blob/384b7bac2e/contrib/docs/tutorials/prometheus-metrics.md
|
||||
|
||||
- 5921b5ce49: - The GitLab Project ID for the `publish:gitlab:merge-request` action is now passed through the query parameter `project` in the `repoUrl`. It still allows people to not use the `projectid` and use the `repoUrl` with the `owner` and `repo` query parameters instead. This makes it easier to publish to repositories instead of writing the full path to the project.
|
||||
- 5025d2e8b6: Adds the ability to pass (an optional) array of strings that will be applied to the newly scaffolded repository as topic labels.
|
||||
@@ -5727,7 +5768,7 @@
|
||||
- `step`: The name of the step that was run
|
||||
- `result`: A string describing whether the task ran successfully, failed, or was skipped
|
||||
|
||||
You can find a guide for running Prometheus metrics here: https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/prometheus-metrics.md
|
||||
You can find a guide for running Prometheus metrics here: https://github.com/backstage/backstage/blob/384b7bac2e/contrib/docs/tutorials/prometheus-metrics.md
|
||||
|
||||
### Patch Changes
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-scaffolder-backend",
|
||||
"version": "3.2.1-next.0",
|
||||
"version": "3.4.0-next.2",
|
||||
"description": "The Backstage backend plugin that helps you create new things",
|
||||
"backstage": {
|
||||
"role": "backend-plugin",
|
||||
@@ -78,7 +78,6 @@
|
||||
"@backstage/plugin-scaffolder-common": "workspace:^",
|
||||
"@backstage/plugin-scaffolder-node": "workspace:^",
|
||||
"@backstage/types": "workspace:^",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@types/luxon": "^3.0.0",
|
||||
"express": "^4.22.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
|
||||
@@ -27,6 +27,12 @@ import { stringifyEntityRef } from '@backstage/catalog-model';
|
||||
import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils';
|
||||
import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
|
||||
import { scaffolderAutocompleteExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import {
|
||||
scaffolderPermissions,
|
||||
RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
||||
RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
||||
RESOURCE_TYPE_SCAFFOLDER_TASK,
|
||||
} from '@backstage/plugin-scaffolder-common/alpha';
|
||||
|
||||
import { scaffolderPlugin } from './ScaffolderPlugin';
|
||||
|
||||
@@ -1216,6 +1222,32 @@ describe('scaffolderPlugin', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('exposes permissions metadata via the well-known endpoint', async () => {
|
||||
const { server } = await startTestBackend({
|
||||
features: [scaffolderPlugin],
|
||||
});
|
||||
|
||||
const { body, status } = await request(server).get(
|
||||
'/api/scaffolder/.well-known/backstage/permissions/metadata',
|
||||
);
|
||||
|
||||
expect(status).toBe(200);
|
||||
|
||||
const permissionNames = body.permissions.map(
|
||||
(p: { name: string }) => p.name,
|
||||
);
|
||||
for (const permission of scaffolderPermissions) {
|
||||
expect(permissionNames).toContain(permission.name);
|
||||
}
|
||||
|
||||
const ruleResourceTypes = body.rules.map(
|
||||
(r: { resourceType: string }) => r.resourceType,
|
||||
);
|
||||
expect(ruleResourceTypes).toContain(RESOURCE_TYPE_SCAFFOLDER_TEMPLATE);
|
||||
expect(ruleResourceTypes).toContain(RESOURCE_TYPE_SCAFFOLDER_ACTION);
|
||||
expect(ruleResourceTypes).toContain(RESOURCE_TYPE_SCAFFOLDER_TASK);
|
||||
});
|
||||
|
||||
it('supports listing templating extensions', async () => {
|
||||
const { server } = await startTestBackend({
|
||||
features: [scaffolderPlugin],
|
||||
|
||||
@@ -63,6 +63,7 @@ import {
|
||||
import {
|
||||
actionsServiceRef,
|
||||
actionsRegistryServiceRef,
|
||||
metricsServiceRef,
|
||||
} from '@backstage/backend-plugin-api/alpha';
|
||||
import { createScaffolderActions } from './actions';
|
||||
|
||||
@@ -141,6 +142,7 @@ export const scaffolderPlugin = createBackendPlugin({
|
||||
lifecycle: coreServices.rootLifecycle,
|
||||
reader: coreServices.urlReader,
|
||||
permissions: coreServices.permissions,
|
||||
permissionsRegistry: coreServices.permissionsRegistry,
|
||||
database: coreServices.database,
|
||||
auth: coreServices.auth,
|
||||
httpRouter: coreServices.httpRouter,
|
||||
@@ -151,6 +153,7 @@ export const scaffolderPlugin = createBackendPlugin({
|
||||
actionsRegistry: actionsServiceRef,
|
||||
actionsRegistryService: actionsRegistryServiceRef,
|
||||
scaffolderService: scaffolderServiceRef,
|
||||
metrics: metricsServiceRef,
|
||||
},
|
||||
async init({
|
||||
logger,
|
||||
@@ -163,11 +166,13 @@ export const scaffolderPlugin = createBackendPlugin({
|
||||
httpAuth,
|
||||
catalog,
|
||||
permissions,
|
||||
permissionsRegistry,
|
||||
events,
|
||||
auditor,
|
||||
actionsRegistry,
|
||||
actionsRegistryService,
|
||||
scaffolderService,
|
||||
metrics,
|
||||
}) {
|
||||
const log = loggerToWinstonLogger(logger);
|
||||
const integrations = ScmIntegrations.fromConfig(config);
|
||||
@@ -239,11 +244,13 @@ export const scaffolderPlugin = createBackendPlugin({
|
||||
auth,
|
||||
httpAuth,
|
||||
permissions,
|
||||
permissionsRegistry,
|
||||
autocompleteHandlers,
|
||||
additionalWorkspaceProviders,
|
||||
events,
|
||||
auditor,
|
||||
actionsRegistry,
|
||||
metrics,
|
||||
});
|
||||
httpRouter.use(router);
|
||||
},
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
BackstageCredentials,
|
||||
LoggerService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import type { MetricsService } from '@backstage/backend-plugin-api/alpha';
|
||||
import type { UserEntity } from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
@@ -81,6 +82,7 @@ export type TemplateTesterCreateOptions = {
|
||||
additionalTemplateGlobals?: Record<string, TemplateGlobal>;
|
||||
permissions?: PermissionEvaluator;
|
||||
config?: Config;
|
||||
metrics: MetricsService;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,7 +39,10 @@ import {
|
||||
mockCredentials,
|
||||
mockServices,
|
||||
} from '@backstage/backend-test-utils';
|
||||
import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha';
|
||||
import {
|
||||
actionsRegistryServiceMock,
|
||||
metricsServiceMock,
|
||||
} from '@backstage/backend-test-utils/alpha';
|
||||
|
||||
describe('NunjucksWorkflowRunner', () => {
|
||||
let actionRegistry: TemplateActionRegistry;
|
||||
@@ -249,6 +252,7 @@ describe('NunjucksWorkflowRunner', () => {
|
||||
logger,
|
||||
permissions: mockedPermissionApi,
|
||||
config,
|
||||
metrics: metricsServiceMock.mock(),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
TaskStep,
|
||||
} from '@backstage/plugin-scaffolder-common';
|
||||
import { JsonArray, JsonObject, JsonValue } from '@backstage/types';
|
||||
import { metrics } from '@opentelemetry/api';
|
||||
import fs from 'fs-extra';
|
||||
import { validate as validateJsonSchema } from 'jsonschema';
|
||||
import nunjucks from 'nunjucks';
|
||||
@@ -42,6 +41,7 @@ import type {
|
||||
LoggerService,
|
||||
PermissionsService,
|
||||
} from '@backstage/backend-plugin-api';
|
||||
import type { MetricsService } from '@backstage/backend-plugin-api/alpha';
|
||||
import { UserEntity } from '@backstage/catalog-model';
|
||||
import {
|
||||
AuthorizeResult,
|
||||
@@ -78,6 +78,7 @@ type NunjucksWorkflowRunnerOptions = {
|
||||
additionalTemplateGlobals?: Record<string, TemplateGlobal>;
|
||||
permissions?: PermissionsService;
|
||||
config?: Config;
|
||||
metrics: MetricsService;
|
||||
};
|
||||
|
||||
type TemplateContext = {
|
||||
@@ -188,6 +189,8 @@ export class NunjucksWorkflowRunner implements WorkflowRunner {
|
||||
secrets?: Record<string, string>;
|
||||
} = { parameters: {}, secrets: {} };
|
||||
|
||||
private readonly tracker: ReturnType<typeof scaffoldingTracker>;
|
||||
|
||||
constructor(options: NunjucksWorkflowRunnerOptions) {
|
||||
this.options = options;
|
||||
this.defaultTemplateFilters = convertFiltersToRecord(
|
||||
@@ -195,10 +198,9 @@ export class NunjucksWorkflowRunner implements WorkflowRunner {
|
||||
integrations: this.options.integrations,
|
||||
}),
|
||||
);
|
||||
this.tracker = scaffoldingTracker(options.metrics);
|
||||
}
|
||||
|
||||
private readonly tracker = scaffoldingTracker();
|
||||
|
||||
async getEnvironmentConfig(): Promise<{
|
||||
parameters: JsonObject;
|
||||
secrets?: TaskSecrets;
|
||||
@@ -700,7 +702,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner {
|
||||
}
|
||||
}
|
||||
|
||||
function scaffoldingTracker() {
|
||||
function scaffoldingTracker(metrics: MetricsService) {
|
||||
// prom-client metrics are deprecated in favour of OpenTelemetry metrics.
|
||||
const promTaskCount = createCounterMetric({
|
||||
name: 'scaffolder_task_count',
|
||||
@@ -723,23 +725,22 @@ function scaffoldingTracker() {
|
||||
labelNames: ['template', 'step', 'result'],
|
||||
});
|
||||
|
||||
const meter = metrics.getMeter('default');
|
||||
const taskCount = meter.createCounter('scaffolder.task.count', {
|
||||
description: 'Count of task runs',
|
||||
const taskCount = metrics.createCounter('scaffolder.task.count', {
|
||||
description: 'Total number of scaffolder tasks executed',
|
||||
});
|
||||
|
||||
const taskDuration = meter.createHistogram('scaffolder.task.duration', {
|
||||
description: 'Duration of a task run',
|
||||
unit: 'seconds',
|
||||
const taskDuration = metrics.createHistogram('scaffolder.task.duration', {
|
||||
description: 'Time taken to complete a scaffolder task end-to-end',
|
||||
unit: 's',
|
||||
});
|
||||
|
||||
const stepCount = meter.createCounter('scaffolder.step.count', {
|
||||
description: 'Count of step runs',
|
||||
const stepCount = metrics.createCounter('scaffolder.step.count', {
|
||||
description: 'Total number of individual scaffolder action steps executed',
|
||||
});
|
||||
|
||||
const stepDuration = meter.createHistogram('scaffolder.step.duration', {
|
||||
description: 'Duration of a step runs',
|
||||
unit: 'seconds',
|
||||
const stepDuration = metrics.createHistogram('scaffolder.step.duration', {
|
||||
description: 'Time taken to complete a single scaffolder action step',
|
||||
unit: 's',
|
||||
});
|
||||
|
||||
async function taskStart(task: TaskContext) {
|
||||
|
||||
@@ -36,6 +36,7 @@ import { WorkflowRunner } from './types';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
import waitForExpect from 'wait-for-expect';
|
||||
import { mockServices } from '@backstage/backend-test-utils';
|
||||
import { metricsServiceMock } from '@backstage/backend-test-utils/alpha';
|
||||
import { loggerToWinstonLogger } from '../../util/loggerToWinstonLogger';
|
||||
|
||||
jest.mock('./NunjucksWorkflowRunner');
|
||||
@@ -93,6 +94,7 @@ describe('TaskWorker', () => {
|
||||
integrations,
|
||||
taskBroker: broker,
|
||||
actionRegistry,
|
||||
metrics: metricsServiceMock.mock(),
|
||||
});
|
||||
|
||||
await broker.dispatch({
|
||||
@@ -124,6 +126,7 @@ describe('TaskWorker', () => {
|
||||
integrations,
|
||||
taskBroker: broker,
|
||||
actionRegistry,
|
||||
metrics: metricsServiceMock.mock(),
|
||||
});
|
||||
|
||||
const { taskId } = await broker.dispatch({
|
||||
@@ -174,6 +177,7 @@ describe('TaskWorker', () => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
metrics: metricsServiceMock.mock(),
|
||||
});
|
||||
|
||||
await taskWorker.runOneTask({
|
||||
@@ -261,6 +265,7 @@ describe('Concurrent TaskWorker', () => {
|
||||
taskBroker: broker,
|
||||
actionRegistry,
|
||||
concurrentTasksLimit: expectedConcurrentTasks,
|
||||
metrics: metricsServiceMock.mock(),
|
||||
});
|
||||
|
||||
taskWorker.start();
|
||||
@@ -307,6 +312,7 @@ describe('Cancellable TaskWorker', () => {
|
||||
integrations,
|
||||
taskBroker,
|
||||
actionRegistry,
|
||||
metrics: metricsServiceMock.mock(),
|
||||
});
|
||||
|
||||
const steps = [...Array(10)].map(n => ({
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
|
||||
import { AuditorService, LoggerService } from '@backstage/backend-plugin-api';
|
||||
import { assertError, InputError, stringifyError } from '@backstage/errors';
|
||||
import type { MetricsService } from '@backstage/backend-plugin-api/alpha';
|
||||
import { InputError, stringifyError, toError } from '@backstage/errors';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
|
||||
import {
|
||||
@@ -78,6 +79,7 @@ export type CreateWorkerOptions = {
|
||||
additionalTemplateGlobals?: Record<string, TemplateGlobal>;
|
||||
permissions?: PermissionEvaluator;
|
||||
gracefulShutdown?: boolean;
|
||||
metrics: MetricsService;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -123,6 +125,7 @@ export class TaskWorker {
|
||||
additionalTemplateGlobals,
|
||||
permissions,
|
||||
gracefulShutdown,
|
||||
metrics,
|
||||
} = options;
|
||||
|
||||
const workflowRunner = new NunjucksWorkflowRunner({
|
||||
@@ -135,6 +138,7 @@ export class TaskWorker {
|
||||
additionalTemplateGlobals,
|
||||
permissions,
|
||||
config,
|
||||
metrics,
|
||||
});
|
||||
|
||||
return new TaskWorker({
|
||||
@@ -224,12 +228,12 @@ export class TaskWorker {
|
||||
await task.complete('completed', { output });
|
||||
await auditorEvent?.success();
|
||||
} catch (error) {
|
||||
assertError(error);
|
||||
const err = toError(error);
|
||||
await auditorEvent?.fail({
|
||||
error,
|
||||
error: err,
|
||||
});
|
||||
await task.complete('failed', {
|
||||
error: { name: error.name, message: error.message },
|
||||
error: { name: err.name, message: err.message },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
stringifyEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import { Config } from '@backstage/config';
|
||||
import { assertError, InputError, NotFoundError } from '@backstage/errors';
|
||||
import { InputError, NotFoundError, toError } from '@backstage/errors';
|
||||
import { CatalogService } from '@backstage/plugin-catalog-node';
|
||||
import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';
|
||||
import fs from 'fs-extra';
|
||||
@@ -47,13 +47,13 @@ export async function getWorkingDirectory(
|
||||
await fs.access(workingDirectory, fs.constants.F_OK | fs.constants.W_OK);
|
||||
logger.info(`using working directory: ${workingDirectory}`);
|
||||
} catch (err) {
|
||||
assertError(err);
|
||||
const error = toError(err);
|
||||
logger.error(
|
||||
`working directory ${workingDirectory} ${
|
||||
err.code === 'ENOENT' ? 'does not exist' : 'is not writable'
|
||||
error.code === 'ENOENT' ? 'does not exist' : 'is not writable'
|
||||
}`,
|
||||
);
|
||||
throw err;
|
||||
throw error;
|
||||
}
|
||||
return workingDirectory;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,10 @@ import {
|
||||
import { createDefaultFilters } from '../lib/templating/filters/createDefaultFilters';
|
||||
import { createRouter } from './router';
|
||||
import { DatabaseTaskStore } from '../scaffolder/tasks/DatabaseTaskStore';
|
||||
import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha';
|
||||
import {
|
||||
actionsRegistryServiceMock,
|
||||
metricsServiceMock,
|
||||
} from '@backstage/backend-test-utils/alpha';
|
||||
import { ActionsService } from '@backstage/backend-plugin-api/alpha';
|
||||
|
||||
function createDatabase(): DatabaseService {
|
||||
@@ -201,6 +204,7 @@ const createTestRouter = async (
|
||||
const httpAuth = mockServices.httpAuth();
|
||||
const events = mockServices.events();
|
||||
|
||||
const permissionsRegistry = mockServices.permissionsRegistry.mock();
|
||||
const router = await createRouter({
|
||||
logger,
|
||||
config: new ConfigReader({}),
|
||||
@@ -208,6 +212,7 @@ const createTestRouter = async (
|
||||
catalog,
|
||||
taskBroker,
|
||||
permissions,
|
||||
permissionsRegistry,
|
||||
auth,
|
||||
httpAuth,
|
||||
events,
|
||||
@@ -229,6 +234,7 @@ const createTestRouter = async (
|
||||
createDebugLogAction(),
|
||||
],
|
||||
actionsRegistry: overrides.actionsRegistry ?? actionsRegistryServiceMock(),
|
||||
metrics: metricsServiceMock.mock(),
|
||||
});
|
||||
|
||||
router.use(mockErrorHandler());
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
HttpAuthService,
|
||||
LifecycleService,
|
||||
LoggerService,
|
||||
PermissionsRegistryService,
|
||||
PermissionsService,
|
||||
resolveSafeChildPath,
|
||||
SchedulerService,
|
||||
@@ -45,7 +46,6 @@ import {
|
||||
ConditionTransformer,
|
||||
createConditionAuthorizer,
|
||||
createConditionTransformer,
|
||||
createPermissionIntegrationRouter,
|
||||
} from '@backstage/plugin-permission-node';
|
||||
import {
|
||||
TaskSpec,
|
||||
@@ -53,16 +53,13 @@ import {
|
||||
templateEntityV1beta3Validator,
|
||||
} from '@backstage/plugin-scaffolder-common';
|
||||
import {
|
||||
RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
||||
RESOURCE_TYPE_SCAFFOLDER_TASK,
|
||||
RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
||||
scaffolderActionPermissions,
|
||||
scaffolderPermissions,
|
||||
scaffolderTaskPermissions,
|
||||
scaffolderTemplatePermissions,
|
||||
taskCancelPermission,
|
||||
taskCreatePermission,
|
||||
taskReadPermission,
|
||||
templateManagementPermission,
|
||||
templateParameterReadPermission,
|
||||
templateStepReadPermission,
|
||||
} from '@backstage/plugin-scaffolder-common/alpha';
|
||||
@@ -78,6 +75,9 @@ import {
|
||||
AutocompleteHandler,
|
||||
CreatedTemplateFilter,
|
||||
CreatedTemplateGlobal,
|
||||
scaffolderActionPermissionResourceRef,
|
||||
scaffolderTaskPermissionResourceRef,
|
||||
scaffolderTemplatePermissionResourceRef,
|
||||
WorkspaceProvider,
|
||||
} from '@backstage/plugin-scaffolder-node/alpha';
|
||||
import { HumanDuration, JsonObject } from '@backstage/types';
|
||||
@@ -131,7 +131,10 @@ import {
|
||||
scaffolderTaskRules,
|
||||
scaffolderTemplateRules,
|
||||
} from './rules';
|
||||
import { ActionsService } from '@backstage/backend-plugin-api/alpha';
|
||||
import {
|
||||
ActionsService,
|
||||
MetricsService,
|
||||
} from '@backstage/backend-plugin-api/alpha';
|
||||
|
||||
/**
|
||||
* RouterOptions
|
||||
@@ -158,6 +161,7 @@ export interface RouterOptions {
|
||||
| CreatedTemplateGlobal[];
|
||||
additionalWorkspaceProviders?: Record<string, WorkspaceProvider>;
|
||||
permissions?: PermissionsService;
|
||||
permissionsRegistry: PermissionsRegistryService;
|
||||
permissionRules?: Array<ScaffolderPermissionRuleInput>;
|
||||
auth: AuthService;
|
||||
httpAuth: HttpAuthService;
|
||||
@@ -165,6 +169,7 @@ export interface RouterOptions {
|
||||
auditor?: AuditorService;
|
||||
autocompleteHandlers?: Record<string, AutocompleteHandler>;
|
||||
actionsRegistry: ActionsService;
|
||||
metrics: MetricsService;
|
||||
}
|
||||
|
||||
function isSupportedTemplate(entity: TemplateEntityV1beta3) {
|
||||
@@ -249,6 +254,7 @@ export async function createRouter(
|
||||
additionalTemplateGlobals,
|
||||
additionalWorkspaceProviders,
|
||||
permissions,
|
||||
permissionsRegistry,
|
||||
permissionRules,
|
||||
autocompleteHandlers = {},
|
||||
events: eventsService,
|
||||
@@ -256,6 +262,7 @@ export async function createRouter(
|
||||
httpAuth,
|
||||
auditor,
|
||||
actionsRegistry,
|
||||
metrics,
|
||||
} = options;
|
||||
|
||||
const concurrentTasksLimit =
|
||||
@@ -344,6 +351,7 @@ export async function createRouter(
|
||||
concurrentTasksLimit,
|
||||
permissions,
|
||||
gracefulShutdown,
|
||||
metrics,
|
||||
...templateExtensions,
|
||||
});
|
||||
|
||||
@@ -375,6 +383,7 @@ export async function createRouter(
|
||||
workingDirectory,
|
||||
permissions,
|
||||
config,
|
||||
metrics,
|
||||
...templateExtensions,
|
||||
});
|
||||
|
||||
@@ -403,35 +412,35 @@ export async function createRouter(
|
||||
const taskTransformConditions: ConditionTransformer<TaskFilters> =
|
||||
createConditionTransformer(Object.values(taskRules));
|
||||
|
||||
const permissionIntegrationRouter = createPermissionIntegrationRouter({
|
||||
resources: [
|
||||
{
|
||||
resourceType: RESOURCE_TYPE_SCAFFOLDER_TEMPLATE,
|
||||
permissions: scaffolderTemplatePermissions,
|
||||
rules: templateRules,
|
||||
},
|
||||
{
|
||||
resourceType: RESOURCE_TYPE_SCAFFOLDER_ACTION,
|
||||
permissions: scaffolderActionPermissions,
|
||||
rules: actionRules,
|
||||
},
|
||||
{
|
||||
resourceType: RESOURCE_TYPE_SCAFFOLDER_TASK,
|
||||
permissions: scaffolderTaskPermissions,
|
||||
rules: taskRules,
|
||||
getResources: async resourceRefs => {
|
||||
return Promise.all(
|
||||
resourceRefs.map(async taskId => {
|
||||
return await taskBroker.get(taskId);
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
permissions: scaffolderPermissions,
|
||||
permissionsRegistry.addResourceType({
|
||||
resourceRef: scaffolderTemplatePermissionResourceRef,
|
||||
permissions: scaffolderTemplatePermissions,
|
||||
rules: templateRules,
|
||||
});
|
||||
|
||||
router.use(permissionIntegrationRouter);
|
||||
permissionsRegistry.addResourceType({
|
||||
resourceRef: scaffolderActionPermissionResourceRef,
|
||||
permissions: scaffolderActionPermissions,
|
||||
rules: actionRules,
|
||||
});
|
||||
|
||||
permissionsRegistry.addResourceType({
|
||||
resourceRef: scaffolderTaskPermissionResourceRef,
|
||||
permissions: scaffolderTaskPermissions,
|
||||
rules: taskRules,
|
||||
getResources: async resourceRefs => {
|
||||
return Promise.all(
|
||||
resourceRefs.map(async taskId => {
|
||||
return await taskBroker.get(taskId);
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
permissionsRegistry.addPermissions([
|
||||
taskCreatePermission,
|
||||
templateManagementPermission,
|
||||
]);
|
||||
|
||||
router
|
||||
.get(
|
||||
|
||||
Reference in New Issue
Block a user