From f0685193efa9f22a84207eb60dc1f9f509643059 Mon Sep 17 00:00:00 2001 From: Ana Luiza Ramalho dos Santos Date: Mon, 2 Jan 2023 18:08:34 -0300 Subject: [PATCH 001/417] fix: add conditional to database different postgres Signed-off-by: Ana Luiza Ramalho dos Santos --- .changeset/rare-buses-swim.md | 5 +++ .../src/tasks/PluginTaskSchedulerJanitor.ts | 32 ++++++++++++++----- 2 files changed, 29 insertions(+), 8 deletions(-) create mode 100644 .changeset/rare-buses-swim.md diff --git a/.changeset/rare-buses-swim.md b/.changeset/rare-buses-swim.md new file mode 100644 index 0000000000..4e4c11e792 --- /dev/null +++ b/.changeset/rare-buses-swim.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-tasks': minor +--- + +Added the adapted query to mysql and sqlite3 databases to not returning warning on logs diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts index 81b0345c2c..4482f2e2bb 100644 --- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts @@ -53,15 +53,31 @@ export class PluginTaskSchedulerJanitor { private async runOnce() { const dbNull = this.knex.raw('null'); + let tasks = []; + const configClient = this.knex.client.config.client; - const tasks = await this.knex(DB_TASKS_TABLE) - .where('current_run_expires_at', '<', this.knex.fn.now()) - .update({ - current_run_ticket: dbNull, - current_run_started_at: dbNull, - current_run_expires_at: dbNull, - }) - .returning(['id']); + if (configClient.includes('sqlite3') || configClient.includes('mysql')) { + const now = await this.knex.select(this.knex.fn.now()); + tasks = await this.knex(DB_TASKS_TABLE) + .select('*') + .where('current_run_expires_at', '<', now); + await this.knex(DB_TASKS_TABLE) + .where('current_run_expires_at', '<', now) + .update({ + current_run_ticket: dbNull, + current_run_started_at: dbNull, + current_run_expires_at: dbNull, + }); + } else { + tasks = await this.knex(DB_TASKS_TABLE) + .where('current_run_expires_at', '<', this.knex.fn.now()) + .update({ + current_run_ticket: dbNull, + current_run_started_at: dbNull, + current_run_expires_at: dbNull, + }) + .returning(['id']); + } // In rare cases, knex drivers may ignore "returning", and return the number // of rows changed instead From 7d4ca3514709133c9e713d42e63d81deccfb7a5b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Jan 2023 14:31:47 +0000 Subject: [PATCH 002/417] fix(deps): update dependency postcss to v8.4.21 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a549cab5a9..4315beb6a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32367,13 +32367,13 @@ __metadata: linkType: hard "postcss@npm:^8.1.0, postcss@npm:^8.4.19": - version: 8.4.20 - resolution: "postcss@npm:8.4.20" + version: 8.4.21 + resolution: "postcss@npm:8.4.21" dependencies: nanoid: ^3.3.4 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: 1a5609ea1c1b204f9c2974a0019ae9eef2d99bf645c2c9aac675166c4cb1005be7b5e2ba196160bc771f5d9ac896ed883f236f888c891e835e59d28fff6651aa + checksum: e39ac60ccd1542d4f9d93d894048aac0d686b3bb38e927d8386005718e6793dbbb46930f0a523fe382f1bbd843c6d980aaea791252bf5e176180e5a4336d9679 languageName: node linkType: hard From 3e28855c0267fc28ad4dca3466285cee1d22049f Mon Sep 17 00:00:00 2001 From: Ana Luiza Ramalho dos Santos Date: Mon, 16 Jan 2023 13:57:39 -0300 Subject: [PATCH 003/417] fix: specify type of let Signed-off-by: Ana Luiza Ramalho dos Santos --- .../backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts index 4482f2e2bb..0d8ea79d13 100644 --- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts @@ -53,13 +53,13 @@ export class PluginTaskSchedulerJanitor { private async runOnce() { const dbNull = this.knex.raw('null'); - let tasks = []; + let tasks: Array<{ id: string }>; const configClient = this.knex.client.config.client; if (configClient.includes('sqlite3') || configClient.includes('mysql')) { const now = await this.knex.select(this.knex.fn.now()); tasks = await this.knex(DB_TASKS_TABLE) - .select('*') + .select('id') .where('current_run_expires_at', '<', now); await this.knex(DB_TASKS_TABLE) .where('current_run_expires_at', '<', now) From 8b5585a88477e9e22660ca9d297229cab1d5058a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 16:48:36 +0200 Subject: [PATCH 004/417] Add paginated entities endpoint Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 115 +++++ .../src/service/AuthorizedEntitiesCatalog.ts | 38 ++ .../service/DefaultEntitiesCatalog.test.ts | 458 ++++++++++++++++++ .../src/service/DefaultEntitiesCatalog.ts | 183 ++++++- .../src/service/createRouter.test.ts | 75 +++ .../src/service/createRouter.ts | 9 + .../src/service/request/index.ts | 1 + .../parsePaginatedEntitiesParams.test.ts | 132 +++++ .../request/parsePaginatedEntitiesParams.ts | 74 +++ plugins/catalog-backend/src/service/util.ts | 25 + 10 files changed, 1109 insertions(+), 1 deletion(-) create mode 100644 plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts create mode 100644 plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index faf7451acd..9f5ad642f2 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -174,6 +174,16 @@ export interface EntitiesCatalog { */ entitiesBatch(request: EntitiesBatchRequest): Promise; + /** + * Fetch entities and scroll back and forth between entities. + * + * @alpha + * @param request + */ + paginatedEntities( + request?: PaginatedEntitiesRequest, + ): Promise; + /** * Removes a single entity. * @@ -202,3 +212,108 @@ export interface EntitiesCatalog { */ facets(request: EntityFacetsRequest): Promise; } + +/** + * The request shape for {@link EntitiesCatalog.paginatedEntities}. + * + * @alpha + */ +export type PaginatedEntitiesRequest = + | PaginatedEntitiesInitialRequest + | PaginatedEntitiesCursorRequest; + +/** + * The initial request for {@link EntitiesCatalog.paginatedEntities}. + * The request take immutable properties that are going to be bound + * for the current and the next pagination requests. + * + * @alpha + */ +export interface PaginatedEntitiesInitialRequest { + authorizationToken?: string; + fields?: (entity: Entity) => Entity; + limit?: number; + filter?: EntityFilter; + sortField?: string; + query?: string; + sortFieldOrder?: 'asc' | 'desc' | undefined; +} + +/** + * Request for {@link EntitiesCatalog.paginatedEntities} used to + * move forward or backward on the data. + * + * @alpha + */ +export interface PaginatedEntitiesCursorRequest { + authorizationToken?: string; + fields?: (entity: Entity) => Entity; + limit?: number; + cursor: string; +} + +/** + * The response shape for {@link EntitiesCatalog.paginatedEntities}. + * + * @alpha + */ +export interface PaginatedEntitiesResponse { + /** + * The entities for the current pagination request + */ + entities: Entity[]; + /** + * The cursor of the next pagination request. + */ + nextCursor?: string; + /** + * The cursor of the previous pagination request. + */ + prevCursor?: string; + /** + * the total number of entities matching the current filters. + */ + totalItems: number; +} + +/** + * The Cursor used internally by the catalog. + * + * @alpha + */ +export type Cursor = { + /** + * the id of the field used for sorting the data. + * For example, metadata.name + */ + sortField: string; + /** + * The value of the last item returned + * by the request. This is used for performing + * cursor based pagination. + */ + sortFieldId: string; + /** + * In which order the data should be paginated. + */ + sortFieldOrder: 'asc' | 'desc'; + filter?: EntityFilter; + /** + * true if the cursor is a previous cursor. + */ + isPrevious: boolean; + /** + * Filter the data by name. + */ + query?: string; + /** + * Sort field id of the first item. + * The catalog uses this field internally for understanding when the beginning + * of the list has been reached when performing cursor based pagination. + */ + firstFieldId: string; + /** + * The number of items that match the provided filters + */ + totalItems?: number; +}; diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index c62e9f9a84..5ae31158f8 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -35,8 +35,11 @@ import { EntityFacetsRequest, EntityFacetsResponse, EntityFilter, + PaginatedEntitiesRequest, + PaginatedEntitiesResponse, } from '../catalog/types'; import { basicEntityFilter } from './request/basicEntityFilter'; +import { isPaginatedEntitiesInitialRequest } from './util'; export class AuthorizedEntitiesCatalog implements EntitiesCatalog { constructor( @@ -106,6 +109,41 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { return this.entitiesCatalog.entitiesBatch(request); } + async paginatedEntities( + request?: PaginatedEntitiesRequest, + ): Promise { + const authorizeDecision = ( + await this.permissionApi.authorizeConditional( + [{ permission: catalogEntityReadPermission }], + { token: request?.authorizationToken }, + ) + )[0]; + + if (authorizeDecision.result === AuthorizeResult.DENY) { + return { + entities: [], + totalItems: 0, + }; + } + + if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) { + const permissionFilter: EntityFilter = this.transformConditions( + authorizeDecision.conditions, + ); + + return this.entitiesCatalog.paginatedEntities({ + ...request, + ...(isPaginatedEntitiesInitialRequest(request) && { + filter: request?.filter + ? { allOf: [permissionFilter, request.filter] } + : permissionFilter, + }), + }); + } + + return this.entitiesCatalog.paginatedEntities(request); + } + async removeEntityByUid( uid: string, options?: { authorizationToken?: string }, diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 6735709662..a9592ddf86 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -18,6 +18,10 @@ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; +import { + PaginatedEntitiesCursorRequest, + PaginatedEntitiesInitialRequest, +} from '../catalog/types'; import { applyDatabaseMigrations } from '../database/migrations'; import { DbFinalEntitiesRow, @@ -674,6 +678,376 @@ describe('DefaultEntitiesCatalog', () => { ); }); + describe('paginatedEntities', () => { + it.each(databases.eachSupportedId())( + 'should return paginated entities and scroll the items accordingly, %p', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + function entityFrom(name: string) { + return { + apiVersion: 'a', + kind: 'k', + metadata: { name }, + spec: { should_include_this: 'yes' }, + }; + } + + const names = ['B', 'F', 'A', 'G', 'D', 'C', 'E']; + const entities: Entity[] = names.map(entityFrom); + + const notFoundEntities: Entity[] = [ + { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'something' }, + spec: {}, + }, + { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'something else' }, + spec: {}, + }, + ]; + + await Promise.all( + entities + .concat(notFoundEntities) + .map(e => addEntityToSearch(knex, e)), + ); + + const catalog = new DefaultEntitiesCatalog(knex); + + const filter = { + key: 'spec.should_include_this', + }; + + const limit = 2; + + // initial request + const request1: PaginatedEntitiesInitialRequest = { + filter, + limit, + sortField: 'metadata.name', + }; + const response1 = await catalog.paginatedEntities(request1); + expect(response1.entities).toEqual([entityFrom('A'), entityFrom('B')]); + expect(response1.nextCursor).toBeDefined(); + expect(response1.prevCursor).toBeUndefined(); + expect(response1.totalItems).toBe(names.length); + + // second request (forward) + const request2: PaginatedEntitiesCursorRequest = { + cursor: response1.nextCursor!, + limit, + }; + const response2 = await catalog.paginatedEntities(request2); + expect(response2.entities).toEqual([entityFrom('C'), entityFrom('D')]); + expect(response2.nextCursor).toBeDefined(); + expect(response2.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // third request (forward) + const request3: PaginatedEntitiesCursorRequest = { + cursor: response2.nextCursor!, + limit, + }; + const response3 = await catalog.paginatedEntities(request3); + expect(response3.entities).toEqual([entityFrom('E'), entityFrom('F')]); + expect(response3.nextCursor).toBeDefined(); + expect(response3.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // fourth request (backwards) + const request4: PaginatedEntitiesCursorRequest = { + cursor: response3.prevCursor!, + limit, + }; + const response4 = await catalog.paginatedEntities(request4); + expect(response4.entities).toEqual([entityFrom('C'), entityFrom('D')]); + expect(response4.nextCursor).toBeDefined(); + expect(response4.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // fifth request (backwards) + const request5: PaginatedEntitiesCursorRequest = { + cursor: response4.prevCursor!, + limit, + }; + const response5 = await catalog.paginatedEntities(request5); + expect(response5.entities).toEqual([entityFrom('A'), entityFrom('B')]); + expect(response5.nextCursor).toBeDefined(); + expect(response5.prevCursor).toBeUndefined(); + expect(response1.totalItems).toBe(names.length); + + // sixth request (forward) + const request6: PaginatedEntitiesCursorRequest = { + cursor: response5.nextCursor!, + limit, + }; + const response6 = await catalog.paginatedEntities(request6); + expect(response6.entities).toEqual([entityFrom('C'), entityFrom('D')]); + expect(response6.nextCursor).toBeDefined(); + expect(response6.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // seventh request (forward) + const request7: PaginatedEntitiesCursorRequest = { + cursor: response6.nextCursor!, + limit, + }; + const response7 = await catalog.paginatedEntities(request7); + expect(response7.entities).toEqual([entityFrom('E'), entityFrom('F')]); + expect(response7.nextCursor).toBeDefined(); + expect(response7.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // seventh.2 request (forward with a different limit) + const request7bis: PaginatedEntitiesCursorRequest = { + cursor: response6.nextCursor!, + limit: limit + 1, + }; + const response7bis = await catalog.paginatedEntities(request7bis); + expect(response7bis.entities).toEqual([ + entityFrom('E'), + entityFrom('F'), + entityFrom('G'), + ]); + expect(response7bis.nextCursor).toBeUndefined(); + expect(response7bis.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // last request (forward) + const request8: PaginatedEntitiesCursorRequest = { + cursor: response7.nextCursor!, + limit, + }; + const response8 = await catalog.paginatedEntities(request8); + expect(response8.entities).toEqual([entityFrom('G')]); + expect(response8.nextCursor).toBeUndefined(); + expect(response8.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + }, + ); + + it.each(databases.eachSupportedId())( + 'should return paginated entities ordered in descending order and scroll the items accordingly, %p', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + function entityFrom(name: string) { + return { + apiVersion: 'a', + kind: 'k', + metadata: { name }, + spec: { should_include_this: 'yes' }, + }; + } + + const names = ['B', 'F', 'A', 'G', 'D', 'C', 'E']; + const entities: Entity[] = names.map(entityFrom); + + const notFoundEntities: Entity[] = [ + { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'something' }, + spec: {}, + }, + { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'something else' }, + spec: {}, + }, + ]; + + await Promise.all( + entities + .concat(notFoundEntities) + .map(e => addEntityToSearch(knex, e)), + ); + + const catalog = new DefaultEntitiesCatalog(knex); + + const filter = { + key: 'spec.should_include_this', + }; + + const limit = 2; + + // initial request + const request1: PaginatedEntitiesInitialRequest = { + filter, + limit, + sortField: 'metadata.name', + sortFieldOrder: 'desc', + }; + const response1 = await catalog.paginatedEntities(request1); + expect(response1.entities).toEqual([entityFrom('G'), entityFrom('F')]); + expect(response1.nextCursor).toBeDefined(); + expect(response1.prevCursor).toBeUndefined(); + expect(response1.totalItems).toBe(names.length); + + // second request (forward) + const request2: PaginatedEntitiesCursorRequest = { + cursor: response1.nextCursor!, + limit, + }; + const response2 = await catalog.paginatedEntities(request2); + expect(response2.entities).toEqual([entityFrom('E'), entityFrom('D')]); + expect(response2.nextCursor).toBeDefined(); + expect(response2.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // third request (forward) + const request3: PaginatedEntitiesCursorRequest = { + cursor: response2.nextCursor!, + limit, + }; + const response3 = await catalog.paginatedEntities(request3); + expect(response3.entities).toEqual([entityFrom('C'), entityFrom('B')]); + expect(response3.nextCursor).toBeDefined(); + expect(response3.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // fourth request (backwards) + const request4: PaginatedEntitiesCursorRequest = { + cursor: response3.prevCursor!, + limit, + }; + const response4 = await catalog.paginatedEntities(request4); + + expect(response4.entities).toEqual([entityFrom('E'), entityFrom('D')]); + expect(response4.nextCursor).toBeDefined(); + expect(response4.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // fifth request (backwards) + const request5: PaginatedEntitiesCursorRequest = { + cursor: response4.prevCursor!, + limit, + }; + const response5 = await catalog.paginatedEntities(request5); + expect(response5.entities).toEqual([entityFrom('G'), entityFrom('F')]); + expect(response5.nextCursor).toBeDefined(); + expect(response5.prevCursor).toBeUndefined(); + expect(response1.totalItems).toBe(names.length); + + // sixth request (forward) + const request6: PaginatedEntitiesCursorRequest = { + cursor: response5.nextCursor!, + limit, + }; + const response6 = await catalog.paginatedEntities(request6); + expect(response6.entities).toEqual([entityFrom('E'), entityFrom('D')]); + expect(response6.nextCursor).toBeDefined(); + expect(response6.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // seventh request (forward) + const request7: PaginatedEntitiesCursorRequest = { + cursor: response6.nextCursor!, + limit, + }; + const response7 = await catalog.paginatedEntities(request7); + expect(response7.entities).toEqual([entityFrom('C'), entityFrom('B')]); + expect(response7.nextCursor).toBeDefined(); + expect(response7.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // seventh.2 request (forward with a different limit) + const request7bis: PaginatedEntitiesCursorRequest = { + cursor: response6.nextCursor!, + limit: limit + 1, + }; + const response7bis = await catalog.paginatedEntities(request7bis); + expect(response7bis.entities).toEqual([ + entityFrom('C'), + entityFrom('B'), + entityFrom('A'), + ]); + expect(response7bis.nextCursor).toBeUndefined(); + expect(response7bis.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + + // last request (forward) + const request8: PaginatedEntitiesCursorRequest = { + cursor: response7.nextCursor!, + limit, + }; + const response8 = await catalog.paginatedEntities(request8); + expect(response8.entities).toEqual([entityFrom('A')]); + expect(response8.nextCursor).toBeUndefined(); + expect(response8.prevCursor).toBeDefined(); + expect(response1.totalItems).toBe(names.length); + }, + ); + + it.each(databases.eachSupportedId())( + 'should filter the results when query is provided, %p', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + function entityFrom(name: string) { + return { + apiVersion: 'a', + kind: 'k', + metadata: { name }, + spec: { should_include_this: 'yes' }, + }; + } + + const names = ['lion', 'cat', 'atcatss', 'dog', 'dogcat', 'aa', 's']; + const entities: Entity[] = names.map(entityFrom); + + const notFoundEntities: Entity[] = [ + { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'something' }, + spec: {}, + }, + { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'something else' }, + spec: {}, + }, + ]; + + await Promise.all( + entities + .concat(notFoundEntities) + .map(e => addEntityToSearch(knex, e)), + ); + + const catalog = new DefaultEntitiesCatalog(knex); + + const filter = { + key: 'spec.should_include_this', + }; + + const request: PaginatedEntitiesInitialRequest = { + filter, + limit: 100, + sortField: 'metadata.name', + query: 'cAt ', + }; + const response = await catalog.paginatedEntities(request); + expect(response.entities).toEqual([ + entityFrom('atcatss'), + entityFrom('cat'), + entityFrom('dogcat'), + ]); + expect(response.nextCursor).toBeUndefined(); + expect(response.prevCursor).toBeUndefined(); + expect(response.totalItems).toBe(3); + }, + ); + }); + describe('removeEntityByUid', () => { it.each(databases.eachSupportedId())( 'also clears parent hashes, %p', @@ -889,5 +1263,89 @@ describe('DefaultEntitiesCatalog', () => { }, 60_000, ); + + it.each(databases.eachSupportedId())( + 'can match relations', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'one', + tags: ['java', 'rust'], + }, + spec: {}, + relations: [ + { + targetRef: 'targetRef', + type: 'ownedBy', + target: { kind: 'k', namespace: 'default', name: 'targetRef' }, + }, + ], + }); + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'two', + tags: ['java', 'node'], + }, + spec: {}, + relations: [ + { + targetRef: 'anotherTargetRef', + type: 'ownedBy', + target: { + kind: 'k', + namespace: 'default', + name: 'anotherTargetRef', + }, + }, + { + targetRef: 'tt', + type: 'somethingelse', + target: { + kind: 'k', + namespace: 'default', + name: 'tt', + }, + }, + ], + }); + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'three', + tags: ['go'], + }, + spec: {}, + relations: [ + { + targetRef: 'targetRef', + type: 'ownedBy', + target: { kind: 'k', namespace: 'default', name: 'targetRef' }, + }, + ], + }); + + const catalog = new DefaultEntitiesCatalog(knex); + + await expect( + catalog.facets({ + facets: ['relations.ownedBy'], + }), + ).resolves.toEqual({ + facets: { + 'relations.ownedBy': [ + { count: 1, value: 'anotherTargetRef' }, + { count: 2, value: 'targetRef' }, + ], + }, + }); + }, + ); }); }); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index d598881371..b860c16c86 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -25,6 +25,7 @@ import { Knex } from 'knex'; import { EntitiesBatchRequest, EntitiesBatchResponse, + Cursor, EntitiesCatalog, EntitiesRequest, EntitiesResponse, @@ -34,6 +35,8 @@ import { EntityFacetsResponse, EntityFilter, EntityPagination, + PaginatedEntitiesRequest, + PaginatedEntitiesResponse, } from '../catalog/types'; import { DbFinalEntitiesRow, @@ -43,8 +46,17 @@ import { DbRelationsRow, DbSearchRow, } from '../database/tables'; + import { Stitcher } from '../stitching/Stitcher'; +import { + isPaginatedEntitiesCursorRequest, + isPaginatedEntitiesInitialRequest, +} from './util'; + +const defaultSortField = 'metadata.name'; +const defaultSortFieldOrder = 'asc'; + function parsePagination(input?: EntityPagination): { limit?: number; offset?: number; @@ -97,7 +109,7 @@ function addCondition( // make a lot of sense. However, it had abysmal performance on sqlite // when datasets grew large, so we're using IN instead. const matchQuery = db('search') - .select('search.entity_id') + .select(entityIdField) .where({ key: filter.key.toLowerCase() }) .andWhere(function keyFilter() { if (filter.values) { @@ -310,6 +322,141 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { return { items }; } + async paginatedEntities( + request?: PaginatedEntitiesRequest, + ): Promise { + const db = this.database; + const limit = request?.limit ?? 20; + + const cursor: Omit & { sortFieldId?: string } = { + firstFieldId: '', + sortField: defaultSortField, + sortFieldOrder: defaultSortFieldOrder, + isPrevious: false, + ...parseCursorFromRequest(request), + }; + + const allowedSortFields = ['metadata.name', 'metadata.uid']; + if (!allowedSortFields.includes(cursor.sortField)) { + throw new InputError( + `Invalid sortField. Allowed values are ${allowedSortFields.join( + ', ', + )}.`, + ); + } + + const isFetchingBackwards = cursor.isPrevious; + + /** + * page number is used for quickly + * detecting the initial batch of items + * when navigating backwards without performing + * extra operations on the database. + */ + /* + const currentPage = isFetchingBackwards + ? cursor.previousPage - 1 + : cursor.previousPage + 1; + */ + + const dbQuery = db('search') + .join('final_entities', 'search.entity_id', 'final_entities.entity_id') + .where('key', cursor.sortField); + + if (cursor.filter) { + parseFilter(cursor.filter, dbQuery, db, false, 'search.entity_id'); + } + + const normalizedQueryByName = cursor.query?.trim(); + if (normalizedQueryByName) { + dbQuery.andWhereLike( + 'value', + `%${normalizedQueryByName.toLocaleLowerCase('en-US')}%`, + ); + } + + const countQuery = dbQuery.clone(); + + const isOrderingDescending = cursor.sortFieldOrder === 'desc'; + if (cursor.sortFieldId) { + dbQuery.andWhere( + 'value', + isFetchingBackwards !== isOrderingDescending ? '<' : '>', + cursor.sortFieldId, + ); + } + + dbQuery + .orderBy( + 'value', + isFetchingBackwards + ? invertOrder(cursor.sortFieldOrder) + : cursor.sortFieldOrder, + ) + // fetch an extra item for + // checking if there are more items + .limit(isFetchingBackwards ? limit : limit + 1); + + countQuery.count('search.entity_id', { as: 'count' }); + + const [rows, [{ count }]] = await Promise.all([ + dbQuery, + // for performance reasons we invoke the countQuery + // only on the first request. + // The result is then embedded into the cursor + // for subsequent requests. + typeof cursor.totalItems === 'undefined' + ? countQuery + : [{ count: cursor.totalItems }], + ]); + + const totalItems = Number(count); + + if (isFetchingBackwards) { + rows.reverse(); + } + const hasMoreResults = + limit > 0 && (isFetchingBackwards || rows.length > limit); + + // discard the extra item only when fetching forward. + if (rows.length > limit) { + rows.length -= 1; + } + + const isInitialRequest = cursor.firstFieldId === ''; + + const firstFieldId = cursor.firstFieldId || rows[0].value; + + const nextCursor = hasMoreResults + ? encodeCursor({ + ...cursor, + sortFieldId: rows[rows.length - 1].value, + firstFieldId, + isPrevious: false, + totalItems, + }) + : undefined; + + const prevCursor = + !isInitialRequest && + rows.length > 0 && + rows[0].value !== cursor.firstFieldId + ? encodeCursor({ + ...cursor, + sortFieldId: rows[0].value, + firstFieldId: cursor.firstFieldId, + isPrevious: true, + totalItems, + }) + : undefined; + + const entities = rows + .map(e => JSON.parse(e.final_entity!)) + .map(e => (request?.fields ? request.fields(e) : e)); + + return { entities, prevCursor, nextCursor, totalItems }; + } + async removeEntityByUid(uid: string): Promise { const dbConfig = this.database.client.config; @@ -490,3 +637,37 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { return { facets }; } } + +function encodeCursor(cursor: Cursor) { + const json = JSON.stringify(cursor); + return Buffer.from(json, 'utf8').toString('base64'); +} + +function parseCursorFromRequest( + request?: PaginatedEntitiesRequest, +): Partial { + if (isPaginatedEntitiesInitialRequest(request)) { + const { + filter, + sortField = defaultSortField, + sortFieldOrder = defaultSortFieldOrder, + query, + } = request; + return { filter, sortField, sortFieldOrder, query }; + } + if (isPaginatedEntitiesCursorRequest(request)) { + try { + const json = Buffer.from(request.cursor, 'base64').toString('utf8'); + const cursor = JSON.parse(json); + // TODO(vinzscam): validate the shit + return cursor as unknown as Cursor; + } catch { + throw new InputError('Malformed cursor, could not be parsed'); + } + } + return {}; +} + +function invertOrder(order: Cursor['sortFieldOrder']) { + return order === 'asc' ? 'desc' : 'asc'; +} diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 6379d65043..85fede25ca 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -52,6 +52,7 @@ describe('createRouter readonly disabled', () => { removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), facets: jest.fn(), + paginatedEntities: jest.fn(), }; locationService = { getLocation: jest.fn(), @@ -135,6 +136,80 @@ describe('createRouter readonly disabled', () => { }); }); + describe('GET /v2beta1/entities', () => { + it('happy path: lists entities', async () => { + const entities: Entity[] = [ + { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, + ]; + + entitiesCatalog.paginatedEntities.mockResolvedValueOnce({ + entities, + totalItems: 100, + nextCursor: 'something', + }); + + const response = await request(app).get('/v2beta1/entities'); + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + entities, + totalItems: 100, + nextCursor: 'something', + }); + }); + + it('parses initial request', async () => { + entitiesCatalog.paginatedEntities.mockResolvedValueOnce({ + entities: [], + totalItems: 0, + }); + const response = await request(app).get( + '/v2beta1/entities?filter=a=1,a=2,b=3&filter=c=4', + ); + + expect(response.status).toEqual(200); + expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledTimes(1); + expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledWith({ + filter: { + anyOf: [ + { + allOf: [ + { key: 'a', values: ['1', '2'] }, + { key: 'b', values: ['3'] }, + ], + }, + { allOf: [{ key: 'c', values: ['4'] }] }, + ], + }, + }); + }); + + it('parses cursor request', async () => { + const entities: Entity[] = [ + { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, + ]; + + entitiesCatalog.paginatedEntities.mockResolvedValueOnce({ + entities, + totalItems: 100, + nextCursor: 'next', + }); + + const response = await request(app).get( + '/v2beta1/entities?cursor=something', + ); + expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledTimes(1); + expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledWith({ + cursor: 'something', + }); + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + entities, + totalItems: 100, + nextCursor: 'next', + }); + }); + }); + describe('GET /entities/by-uid/:uid', () => { it('can fetch entity by uid', async () => { const entity: Entity = { diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index 62a0f970c9..a7f5373a03 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -39,6 +39,7 @@ import { parseEntityFilterParams, parseEntityPaginationParams, parseEntityTransformParams, + parsePaginatedEntitiesParams, } from './request'; import { parseEntityFacetParams } from './request/parseEntityFacetParams'; import { parseEntityOrderParams } from './request/parseEntityOrderParams'; @@ -130,6 +131,14 @@ export async function createRouter( // TODO(freben): encode the pageInfo in the response res.json(entities); }) + .get('/v2beta1/entities', async (req, res) => { + const response = await entitiesCatalog.paginatedEntities({ + ...parsePaginatedEntitiesParams(req.query), + authorizationToken: getBearerToken(req.header('authorization')), + }); + + res.json(response); + }) .get('/entities/by-uid/:uid', async (req, res) => { const { uid } = req.params; const { entities } = await entitiesCatalog.entities({ diff --git a/plugins/catalog-backend/src/service/request/index.ts b/plugins/catalog-backend/src/service/request/index.ts index 0b09355e72..5a55c11ca0 100644 --- a/plugins/catalog-backend/src/service/request/index.ts +++ b/plugins/catalog-backend/src/service/request/index.ts @@ -19,3 +19,4 @@ export { basicEntityFilter } from './basicEntityFilter'; export { parseEntityFilterParams } from './parseEntityFilterParams'; export { parseEntityPaginationParams } from './parseEntityPaginationParams'; export { parseEntityTransformParams } from './parseEntityTransformParams'; +export { parsePaginatedEntitiesParams } from './parsePaginatedEntitiesParams'; diff --git a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts new file mode 100644 index 0000000000..838b931888 --- /dev/null +++ b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts @@ -0,0 +1,132 @@ +/* + * Copyright 2022 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 { + PaginatedEntitiesCursorRequest, + PaginatedEntitiesInitialRequest, +} from '../../catalog/types'; +import { parsePaginatedEntitiesParams } from './parsePaginatedEntitiesParams'; + +describe('parsePaginatedEntitiesParams', () => { + describe('initial request', () => { + it('should parse all the defined params', () => { + const validRequest = { + authorizationToken: 'to_not_be_returned', + fields: ['kind'], + limit: '3', + filter: ['a=1', 'b=2'], + sortField: 'sortField', + sortFieldOrder: 'desc', + query: 'query', + }; + const parsedObj = parsePaginatedEntitiesParams( + validRequest, + ) as PaginatedEntitiesInitialRequest; + expect(parsedObj.limit).toBe(3); + expect(parsedObj.fields).toBeDefined(); + expect(parsedObj.sortField).toBe('sortField'); + expect(parsedObj.sortFieldOrder).toBe('desc'); + expect(parsedObj.filter).toBeDefined(); + expect(parsedObj.query).toBe('query'); + expect(parsedObj).not.toHaveProperty('authorizationToken'); + expect(parsedObj).not.toHaveProperty('cursor'); + }); + it('should ignore optional params', () => { + const parsedObj = parsePaginatedEntitiesParams( + {}, + ) as PaginatedEntitiesInitialRequest; + expect(parsedObj.limit).toBeUndefined(); + expect(parsedObj.fields).toBeUndefined(); + expect(parsedObj.sortField).toBeUndefined(); + expect(parsedObj.sortFieldOrder).toBeUndefined(); + expect(parsedObj.filter).toBeUndefined(); + expect(parsedObj.query).toBeUndefined(); + expect(parsedObj).not.toHaveProperty('authorizationToken'); + expect(parsedObj).not.toHaveProperty('cursor'); + }); + + it.each([ + { + limit: 'asd', + }, + { filter: 3 }, + { sortField: [] }, + { sortFieldOrder: 'something' }, + { fields: [4] }, + { query: [] }, + ])('should throw if some parameter is not valid %p', params => { + expect(() => parsePaginatedEntitiesParams(params)).toThrow(); + }); + }); + + describe('cursor request', () => { + it('should parse all the defined params', () => { + const validRequest = { + authorizationToken: 'to_not_be_returned', + fields: ['kind'], + limit: '3', + cursor: 'cursor', + }; + const parsedObj = parsePaginatedEntitiesParams( + validRequest, + ) as PaginatedEntitiesCursorRequest; + expect(parsedObj.limit).toBe(3); + expect(parsedObj.fields).toBeDefined(); + expect(parsedObj.cursor).toBe('cursor'); + }); + + it('should ignore unknown params', () => { + const validRequest = { + authorizationToken: 'to_not_be_returned', + fields: ['kind'], + limit: '3', + cursor: 'cursor', + filter: ['a=1', 'b=2'], + sortField: 'sortField', + sortFieldOrder: 'desc', + query: 'query', + }; + const parsedObj = parsePaginatedEntitiesParams( + validRequest, + ) as PaginatedEntitiesCursorRequest; + expect(parsedObj.limit).toBe(3); + expect(parsedObj.fields).toBeDefined(); + expect(parsedObj.cursor).toBe('cursor'); + expect(parsedObj).not.toHaveProperty('filter'); + expect(parsedObj).not.toHaveProperty('sortField'); + expect(parsedObj).not.toHaveProperty('sortFieldOrder'); + expect(parsedObj).not.toHaveProperty('query'); + }); + + it('should ignore optional params', () => { + const parsedObj = parsePaginatedEntitiesParams( + {}, + ) as PaginatedEntitiesCursorRequest; + expect(parsedObj.limit).toBeUndefined(); + expect(parsedObj.fields).toBeUndefined(); + }); + + it.each([ + { + limit: 'asd', + }, + { cursor: [] }, + { fields: [4] }, + ])('should throw if some parameter is not valid %p', params => { + expect(() => parsePaginatedEntitiesParams(params)).toThrow(); + }); + }); +}); diff --git a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts new file mode 100644 index 0000000000..84d519ec0b --- /dev/null +++ b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts @@ -0,0 +1,74 @@ +/* + * Copyright 2022 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 { InputError } from '@backstage/errors'; +import { + PaginatedEntitiesCursorRequest, + PaginatedEntitiesInitialRequest, + PaginatedEntitiesRequest, +} from '../../catalog/types'; +import { parseIntegerParam, parseStringParam } from './common'; +import { parseEntityFilterParams } from './parseEntityFilterParams'; +import { parseEntityTransformParams } from './parseEntityTransformParams'; + +export function parsePaginatedEntitiesParams( + params: Record, +): Omit { + const fields = parseEntityTransformParams(params); + const limit = parseIntegerParam(params.limit, 'limit'); + const cursor = parseStringParam(params.cursor, 'cursor'); + if (cursor) { + const response: Omit = + { + cursor, + fields, + limit, + }; + return response; + } + + const filter = parseEntityFilterParams(params); + const query = parseStringParam(params.query, 'query'); + const sortField = parseStringParam(params.sortField, 'sortField'); + const sortFieldOrder = parseSortFieldOrder( + params.sortFieldOrder, + 'sortFieldOrder', + ); + + const response: Omit = + { + fields, + filter, + limit, + sortField, + sortFieldOrder, + query, + }; + + return response; +} + +function parseSortFieldOrder(sortFieldOrder: unknown, ctx: string) { + const isSortFieldOrder = + sortFieldOrder === undefined || + sortFieldOrder === 'asc' || + sortFieldOrder === 'desc'; + + if (isSortFieldOrder) { + return sortFieldOrder; + } + throw new InputError(`Invalid ${ctx}, not asc or desc`); +} diff --git a/plugins/catalog-backend/src/service/util.ts b/plugins/catalog-backend/src/service/util.ts index 9a914aadcb..bb86654565 100644 --- a/plugins/catalog-backend/src/service/util.ts +++ b/plugins/catalog-backend/src/service/util.ts @@ -18,6 +18,11 @@ import { InputError, NotAllowedError } from '@backstage/errors'; import { Request } from 'express'; import lodash from 'lodash'; import { z } from 'zod'; +import { + EntitiesRequest, + PaginatedEntitiesCursorRequest, + PaginatedEntitiesInitialRequest, +} from '../catalog/types'; export async function requireRequestBody(req: Request): Promise { const contentType = req.header('content-type'); @@ -65,3 +70,23 @@ export function disallowReadonlyMode(readonly: boolean) { throw new NotAllowedError('This operation not allowed in readonly mode'); } } + +export function isPaginatedEntitiesInitialRequest( + input: EntitiesRequest | undefined, +): input is PaginatedEntitiesInitialRequest { + if (!input) { + return false; + } + // TODO(vinzscam) expand this + return !isPaginatedEntitiesCursorRequest(input); +} + +export function isPaginatedEntitiesCursorRequest( + input: EntitiesRequest | undefined, +): input is PaginatedEntitiesCursorRequest { + if (!input) { + return false; + } + // TODO(vinzscam) expand this + return input?.hasOwnProperty('cursor') ?? false; +} From 6a1e7fbe52b7e66b31dcee04b83dcb0ad550b198 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 18:46:25 +0200 Subject: [PATCH 005/417] CatalogClient: add getPaginatedEntities method Signed-off-by: Vincenzo Scamporlino --- .../catalog-client/src/CatalogClient.test.ts | 194 ++++++++++++++++++ packages/catalog-client/src/CatalogClient.ts | 163 ++++++++++----- packages/catalog-client/src/index.ts | 1 + packages/catalog-client/src/types/api.ts | 110 +++++++++- packages/catalog-client/src/types/index.ts | 3 + packages/catalog-client/src/utils.ts | 36 ++++ 6 files changed, 452 insertions(+), 55 deletions(-) create mode 100644 packages/catalog-client/src/utils.ts diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 2e9d2a0679..8a449c730e 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -249,6 +249,200 @@ describe('CatalogClient', () => { }); }); + describe('getPaginatedEntities', () => { + const defaultServiceResponse = { + entities: [ + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'Test2', + namespace: 'test1', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'Test1', + namespace: 'test1', + }, + }, + ], + totalItems: 10, + nextCursor: 'next', + prevCursor: 'prev', + }; + + const defaultClientResponse = { + entities: [ + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'Test2', + namespace: 'test1', + }, + }, + { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'Test1', + namespace: 'test1', + }, + }, + ], + totalItems: 10, + next: jest.fn(), + prev: jest.fn(), + }; + + beforeEach(() => { + server.use( + rest.get(`${mockBaseUrl}/v2beta1/entities`, (_, res, ctx) => { + return res(ctx.json(defaultServiceResponse)); + }), + ); + }); + + it('should fetch entities from correct endpoint', async () => { + const response = await client.getPaginatedEntities?.({}, { token }); + expect(response?.entities).toEqual(defaultClientResponse.entities); + expect(response?.totalItems).toEqual(defaultClientResponse.totalItems); + expect(response?.next).toBeDefined(); + expect(response?.prev).toBeDefined(); + }); + + it('builds multiple entity search filters properly', async () => { + const mockedEndpoint = jest + .fn() + .mockImplementation((_req, res, ctx) => + res(ctx.json({ entities: [], totalItems: 0 })), + ); + + server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + + const response = await client.getPaginatedEntities?.( + { + filter: [ + { + a: '1', + b: ['2', '3'], + ö: '=', + }, + { + a: '2', + }, + { + c: CATALOG_FILTER_EXISTS, + }, + ], + }, + { token }, + ); + + expect(response).toEqual({ entities: [], totalItems: 0 }); + expect(mockedEndpoint).toHaveBeenCalledTimes(1); + expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( + '?filter=a=1,b=2,b=3,%C3%B6=%3D&filter=a=2&filter=c', + ); + }); + + it('should send query params correctly on initial request', async () => { + const mockedEndpoint = jest + .fn() + .mockImplementation((_req, res, ctx) => + res(ctx.json({ entities: [], totalItems: 0 })), + ); + + server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + + await client.getPaginatedEntities?.({ + fields: ['a', 'b'], + limit: 100, + query: 'query', + sortField: 'metadata.name', + sortFieldOrder: 'asc', + }); + expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( + '?limit=100&sortField=metadata.name&sortFieldOrder=asc&fields=a,b&query=query', + ); + }); + + it('should ignore initial query params if cursor is passed', async () => { + const mockedEndpoint = jest + .fn() + .mockImplementation((_req, res, ctx) => + res(ctx.json({ entities: [], totalItems: 0 })), + ); + + server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + + await client.getPaginatedEntities?.({ + fields: ['a', 'b'], + limit: 100, + query: 'query', + sortField: 'metadata.name', + sortFieldOrder: 'asc', + cursor: 'cursor', + }); + expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( + '?cursor=cursor&limit=100&fields=a,b', + ); + }); + + it('should return paginated functions if next and prev cursors are present', async () => { + const mockedEndpoint = jest.fn().mockImplementation((_req, res, ctx) => + res( + ctx.json({ + entities: [ + { + apiVersion: 'v1', + kind: 'CustomKind', + metadata: { + namespace: 'default', + name: 'e1', + }, + }, + { + apiVersion: 'v1', + kind: 'CustomKind', + metadata: { + namespace: 'default', + name: 'e2', + }, + }, + ], + nextCursor: 'nextcursor', + prevCursor: 'prevcursor', + totalItems: 100, + }), + ), + ); + + server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + + const response = await client.getPaginatedEntities?.({ + limit: 2, + }); + expect(mockedEndpoint.mock.calls[0][0].url.search).toBe('?limit=2'); + + expect(response?.next).toBeDefined(); + expect(response?.prev).toBeDefined(); + + await response?.next?.(); + expect(mockedEndpoint.mock.calls[1][0].url.search).toBe( + '?cursor=nextcursor', + ); + + await response?.prev?.(); + expect(mockedEndpoint.mock.calls[2][0].url.search).toBe( + '?cursor=prevcursor', + ); + }); + }); + describe('getEntityByRef', () => { const existingEntity: Entity = { apiVersion: 'v1', diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index af4262b842..03fdd600e9 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -39,9 +39,14 @@ import { ValidateEntityResponse, GetEntitiesByRefsRequest, GetEntitiesByRefsResponse, + GetPaginatedEntitiesRequest, + GetPaginatedEntitiesResponse, + EntitiesFilter, + GetPaginatedEntitiesCursorRequest, } from './types/api'; import { DiscoveryApi } from './types/discovery'; import { FetchApi } from './types/fetch'; +import { isPaginatedEntitiesInitialRequest } from './utils'; /** * A frontend and backend compatible client for communicating with the Backstage @@ -107,30 +112,7 @@ export class CatalogClient implements CatalogApi { limit, after, } = request ?? {}; - const params: string[] = []; - - // filter param can occur multiple times, for example - // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' - // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters - // the "inner array" defined within a `filter` param corresponds to "allOf" filters - for (const filterItem of [filter].flat()) { - const filterParts: string[] = []; - for (const [key, value] of Object.entries(filterItem)) { - for (const v of [value].flat()) { - if (v === CATALOG_FILTER_EXISTS) { - filterParts.push(encodeURIComponent(key)); - } else if (typeof v === 'string') { - filterParts.push( - `${encodeURIComponent(key)}=${encodeURIComponent(v)}`, - ); - } - } - } - - if (filterParts.length) { - params.push(`filter=${filterParts.join(',')}`); - } - } + const params = this.getParams(filter); if (fields.length) { params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); @@ -223,6 +205,70 @@ export class CatalogClient implements CatalogApi { return { items }; } + /** + * {@inheritdoc CatalogApi.getPaginatedEntities} + */ + async getPaginatedEntities?( + request?: GetPaginatedEntitiesRequest, + options?: CatalogRequestOptions, + ): Promise { + const params: string[] = []; + + if (isPaginatedEntitiesInitialRequest(request)) { + const { + fields = [], + filter, + limit, + sortField, + sortFieldOrder, + query, + } = request ?? {}; + params.push(...this.getParams(filter)); + + if (limit !== undefined) { + params.push(`limit=${limit}`); + } + if (sortField !== undefined) { + params.push(`sortField=${sortField}`); + } + if (sortFieldOrder !== undefined) { + params.push(`sortFieldOrder=${sortFieldOrder}`); + } + if (fields.length) { + params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); + } + + const normalizedQuery = query?.trim(); + if (normalizedQuery) { + params.push(`query=${normalizedQuery}`); + } + } else { + const { fields = [], limit, cursor } = request; + + params.push(`cursor=${cursor}`); + if (limit !== undefined) { + params.push(`limit=${limit}`); + } + if (fields.length) { + params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); + } + } + + const query = params.length ? `?${params.join('&')}` : ''; + const { entities, totalItems, nextCursor, prevCursor } = + await this.requestRequired<{ + entities: Entity[]; + totalItems: number; + nextCursor?: string; + prevCursor?: string; + }>('GET', `/v2beta1/entities${query}`, options); + + const next = this.getEntitiesFromCursor(nextCursor, options); + const prev = this.getEntitiesFromCursor(prevCursor, options); + + return { entities, totalItems, next, prev }; + } + /** * {@inheritdoc CatalogApi.getEntityByRef} */ @@ -290,30 +336,7 @@ export class CatalogClient implements CatalogApi { options?: CatalogRequestOptions, ): Promise { const { filter = [], facets } = request; - const params: string[] = []; - - // filter param can occur multiple times, for example - // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' - // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters - // the "inner array" defined within a `filter` param corresponds to "allOf" filters - for (const filterItem of [filter].flat()) { - const filterParts: string[] = []; - for (const [key, value] of Object.entries(filterItem)) { - for (const v of [value].flat()) { - if (v === CATALOG_FILTER_EXISTS) { - filterParts.push(encodeURIComponent(key)); - } else if (typeof v === 'string') { - filterParts.push( - `${encodeURIComponent(key)}=${encodeURIComponent(v)}`, - ); - } - } - } - - if (filterParts.length) { - params.push(`filter=${filterParts.join(',')}`); - } - } + const params = this.getParams(filter); for (const facet of facets) { params.push(`facet=${encodeURIComponent(facet)}`); @@ -466,11 +489,11 @@ export class CatalogClient implements CatalogApi { } } - private async requestRequired( + private async requestRequired( method: string, path: string, options?: CatalogRequestOptions, - ): Promise { + ): Promise { const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`; const headers: Record = options?.token ? { Authorization: `Bearer ${options.token}` } @@ -481,7 +504,7 @@ export class CatalogClient implements CatalogApi { throw await ResponseError.fromResponse(response); } - return await response.json(); + return response.json(); } private async requestOptional( @@ -504,4 +527,42 @@ export class CatalogClient implements CatalogApi { return await response.json(); } + + private getParams(filter: EntitiesFilter = []) { + const params: string[] = []; + // filter param can occur multiple times, for example + // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' + // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters + // the "inner array" defined within a `filter` param corresponds to "allOf" filters + for (const filterItem of [filter].flat()) { + const filterParts: string[] = []; + for (const [key, value] of Object.entries(filterItem)) { + for (const v of [value].flat()) { + if (v === CATALOG_FILTER_EXISTS) { + filterParts.push(encodeURIComponent(key)); + } else if (typeof v === 'string') { + filterParts.push( + `${encodeURIComponent(key)}=${encodeURIComponent(v)}`, + ); + } + } + } + + if (filterParts.length) { + params.push(`filter=${filterParts.join(',')}`); + } + } + return params; + } + + private getEntitiesFromCursor( + cursor: string | undefined, + options?: CatalogRequestOptions, + ) { + if (!cursor) { + return undefined; + } + return (request: Omit = {}) => + this.getPaginatedEntities!({ ...request, cursor }, options); + } } diff --git a/packages/catalog-client/src/index.ts b/packages/catalog-client/src/index.ts index 2e81942c2f..f0b10a3eef 100644 --- a/packages/catalog-client/src/index.ts +++ b/packages/catalog-client/src/index.ts @@ -22,3 +22,4 @@ export { CatalogClient } from './CatalogClient'; export * from './types'; +export * from './utils'; diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index d662a9d106..1390a0576e 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -287,10 +287,7 @@ export interface GetEntityFacetsRequest { * (exported from this package), which means that you assert on the existence * of that key, no matter what its value is. */ - filter?: - | Record[] - | Record - | undefined; + filter?: EntitiesFilter; /** * Dot separated paths for the facets to extract from each entity. * @@ -359,6 +356,11 @@ export type AddLocationRequest = { dryRun?: boolean; }; +export type EntitiesFilter = + | Record[] + | Record + | undefined; + /** * The response type for {@link CatalogClient.addLocation}. * @@ -380,6 +382,69 @@ export type ValidateEntityResponse = | { valid: true } | { valid: false; errors: SerializedError[] }; +/** + * The request type for {@link CatalogClient.getPaginatedEntities}. + * + * @alpha + */ +export type GetPaginatedEntitiesRequest = + | GetPaginatedEntitiesInitialRequest + | GetPaginatedEntitiesCursorRequest; + +/** + * A request type for {@link CatalogClient.getPaginatedEntities}. + * The method takes this type in an initial pagination request, + * when requesting the first batch of entities. + * + * The properties filter, sortField, query and sortFieldOrder, are going + * to be immutable for the entire lifecycle of the following requests. + * + * @alpha + */ +export type GetPaginatedEntitiesInitialRequest = + | { + fields?: string[]; + limit?: number; + filter?: EntitiesFilter; + sortField?: string; + query?: string; + sortFieldOrder?: 'asc' | 'desc'; + } + | undefined; + +/** + * A request type for {@link CatalogClient.getPaginatedEntities}. + * The method takes this type in a pagination request, following + * the initial request. + * + * @alpha + */ +export type GetPaginatedEntitiesCursorRequest = { + fields?: string[]; + limit?: number; + cursor: string; +}; + +/** + * The response type for {@link CatalogClient.getPaginatedEntities}. + * + * @alpha + */ +export type GetPaginatedEntitiesResponse = { + /* The list of entities for the current request */ + entities: Entity[]; + /* The number of entities among all the requests */ + totalItems: number; + /* A method returning a promise containing the next batch of entities. */ + next?( + request?: Omit, + ): Promise; + /* A method returning a promise containing the previous batch of entities. */ + prev?( + request?: Omit, + ): Promise; +}; + /** * A client for interacting with the Backstage software catalog through its API. * @@ -414,6 +479,43 @@ export interface CatalogApi { options?: CatalogRequestOptions, ): Promise; + /** + * Gets paginated entities from the catalog. + * The method takes + * @alpha + * @remarks + * + * Example: + * + * const response = await catalogClient.getPaginatedEntities({ + * filter: [{ kind: 'group' }], + * limit: 20, + * query: 'A', + * sortField: 'metadata.name', + * sortFieldOrder: 'asc' + * }); + * + * this will match all entities of type group having a name starting + * with 'A', ordered by name ascending. + * + * The response will contain a maximum of 20 entities. In case + * more than 20 entities exist, the response will contain a next function, invocable + * using: + * + * const secondBatchResponse = await response.next({ limit: 20 }); + * + * secondBatchResponse will contain the next batch of maximum 20 entities, together + * with a prev function useful for navigating backwards and a next function + * in case more entities matching the filters of the first request are present in the catalog. + * + * @param request - Request parameters + * @param options - Additional options + */ + getPaginatedEntities?( + request?: GetPaginatedEntitiesRequest, + options?: CatalogRequestOptions, + ): Promise; + /** * Gets entity ancestor information, i.e. the hierarchy of parent entities * whose processing resulted in a given entity appearing in the catalog. diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts index 81b985eb42..7da07979fc 100644 --- a/packages/catalog-client/src/types/index.ts +++ b/packages/catalog-client/src/types/index.ts @@ -33,5 +33,8 @@ export type { GetEntityFacetsResponse, Location, ValidateEntityResponse, + GetPaginatedEntitiesCursorRequest, + GetPaginatedEntitiesInitialRequest, + GetPaginatedEntitiesResponse, } from './api'; export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status'; diff --git a/packages/catalog-client/src/utils.ts b/packages/catalog-client/src/utils.ts new file mode 100644 index 0000000000..5a26053fb9 --- /dev/null +++ b/packages/catalog-client/src/utils.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2022 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 { + GetPaginatedEntitiesCursorRequest, + GetPaginatedEntitiesInitialRequest, + GetPaginatedEntitiesRequest, +} from './types/api'; + +export function isPaginatedEntitiesInitialRequest( + request: GetPaginatedEntitiesInitialRequest, +): request is GetPaginatedEntitiesInitialRequest { + if (!request) { + return true; + } + return !(request as GetPaginatedEntitiesCursorRequest).cursor; +} + +export function isPaginatedEntitiesCursorRequest( + request: GetPaginatedEntitiesRequest, +): request is GetPaginatedEntitiesCursorRequest { + return !isPaginatedEntitiesInitialRequest(request); +} From 8b39d640b1e836e5c8840de1f33f5da4284d192a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 20:30:42 +0200 Subject: [PATCH 006/417] Fix typings Signed-off-by: Vincenzo Scamporlino --- .../src/service/AuthorizedEntitiesCatalog.test.ts | 1 + .../src/service/DefaultEntitiesCatalog.test.ts | 12 ------------ .../catalog-backend/src/service/createRouter.test.ts | 2 ++ 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts index 829e41c21e..8ee10fdbcb 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts @@ -30,6 +30,7 @@ describe('AuthorizedEntitiesCatalog', () => { facets: jest.fn(), refresh: jest.fn(), listAncestors: jest.fn(), + paginatedEntities: jest.fn(), }; const fakePermissionApi = { authorize: jest.fn(), diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index a9592ddf86..9b315f42b7 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1281,7 +1281,6 @@ describe('DefaultEntitiesCatalog', () => { { targetRef: 'targetRef', type: 'ownedBy', - target: { kind: 'k', namespace: 'default', name: 'targetRef' }, }, ], }); @@ -1297,20 +1296,10 @@ describe('DefaultEntitiesCatalog', () => { { targetRef: 'anotherTargetRef', type: 'ownedBy', - target: { - kind: 'k', - namespace: 'default', - name: 'anotherTargetRef', - }, }, { targetRef: 'tt', type: 'somethingelse', - target: { - kind: 'k', - namespace: 'default', - name: 'tt', - }, }, ], }); @@ -1326,7 +1315,6 @@ describe('DefaultEntitiesCatalog', () => { { targetRef: 'targetRef', type: 'ownedBy', - target: { kind: 'k', namespace: 'default', name: 'targetRef' }, }, ], }); diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 85fede25ca..6e2d52c63e 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -635,6 +635,7 @@ describe('createRouter readonly enabled', () => { removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), facets: jest.fn(), + paginatedEntities: jest.fn(), }; locationService = { getLocation: jest.fn(), @@ -825,6 +826,7 @@ describe('NextRouter permissioning', () => { removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), facets: jest.fn(), + paginatedEntities: jest.fn(), }; locationService = { getLocation: jest.fn(), From 7f4ea3d3602faa71760f8fac64134412db7794c2 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 20:37:19 +0200 Subject: [PATCH 007/417] Add changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/silly-suits-run.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/silly-suits-run.md diff --git a/.changeset/silly-suits-run.md b/.changeset/silly-suits-run.md new file mode 100644 index 0000000000..ed0961a584 --- /dev/null +++ b/.changeset/silly-suits-run.md @@ -0,0 +1,8 @@ +--- +'@backstage/catalog-client': minor +'@backstage/plugin-catalog-backend': minor +--- + +Add /v2beta1/entities endpoint returning paginated entities. + +The endpoint supports cursor base pagination and server side sorting of the entities by name or uid. From 29e2c48496e6cbe903fb6a001426ed510923af46 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 20:51:50 +0200 Subject: [PATCH 008/417] Add tests for limit zero Signed-off-by: Vincenzo Scamporlino --- .../service/DefaultEntitiesCatalog.test.ts | 29 ++++++++++++++++++- .../src/service/DefaultEntitiesCatalog.ts | 2 +- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 9b315f42b7..35c1f7153b 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -17,7 +17,7 @@ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; -import { v4 as uuid } from 'uuid'; +import { v4 as uuid, v4 } from 'uuid'; import { PaginatedEntitiesCursorRequest, PaginatedEntitiesInitialRequest, @@ -1046,6 +1046,33 @@ describe('DefaultEntitiesCatalog', () => { expect(response.totalItems).toBe(3); }, ); + + it.each(databases.eachSupportedId())( + 'should include totalItems and empty entities in the response in case limit is zero, %p', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + await Promise.all( + Array(20) + .fill(0) + .map(() => + addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { name: v4() }, + }), + ), + ); + + const catalog = new DefaultEntitiesCatalog(knex); + + const request: PaginatedEntitiesInitialRequest = { + limit: 0, + }; + const response = await catalog.paginatedEntities(request); + expect(response).toEqual({ totalItems: 20, entities: [] }); + }, + ); }); describe('removeEntityByUid', () => { diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index b860c16c86..bdd36af483 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -425,7 +425,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isInitialRequest = cursor.firstFieldId === ''; - const firstFieldId = cursor.firstFieldId || rows[0].value; + const firstFieldId = cursor.firstFieldId || rows[0]?.value; const nextCursor = hasMoreResults ? encodeCursor({ From 296d4f6179c81433c4a763365dfc2e7194774b6e Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 21:21:45 +0200 Subject: [PATCH 009/417] Improve api reports Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 57 +++++++++++++++++-- packages/catalog-client/src/CatalogClient.ts | 2 + packages/catalog-client/src/index.ts | 1 - packages/catalog-client/src/types/api.ts | 14 ++++- packages/catalog-client/src/types/index.ts | 2 + .../service/DefaultEntitiesCatalog.test.ts | 10 ++-- 6 files changed, 74 insertions(+), 12 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index a81314308b..f612407b1d 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -58,6 +58,11 @@ export interface CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; + // @alpha + getPaginatedEntities?( + request?: GetPaginatedEntitiesRequest, + options?: CatalogRequestOptions, + ): Promise; refreshEntity( entityRef: string, options?: CatalogRequestOptions, @@ -124,6 +129,11 @@ export class CatalogClient implements CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; + // @alpha + getPaginatedEntities?( + request?: GetPaginatedEntitiesRequest, + options?: CatalogRequestOptions, + ): Promise; refreshEntity( entityRef: string, options?: CatalogRequestOptions, @@ -149,6 +159,12 @@ export interface CatalogRequestOptions { token?: string; } +// @public +export type EntitiesFilter = + | Record[] + | Record + | undefined; + // @public export const ENTITY_STATUS_CATALOG_PROCESSING_TYPE = 'backstage.io/catalog-processing'; @@ -219,10 +235,7 @@ export interface GetEntityAncestorsResponse { // @public export interface GetEntityFacetsRequest { facets: string[]; - filter?: - | Record[] - | Record - | undefined; + filter?: EntitiesFilter; } // @public @@ -236,6 +249,42 @@ export interface GetEntityFacetsResponse { >; } +// @alpha +export type GetPaginatedEntitiesCursorRequest = { + fields?: string[]; + limit?: number; + cursor: string; +}; + +// @alpha +export type GetPaginatedEntitiesInitialRequest = + | { + fields?: string[]; + limit?: number; + filter?: EntitiesFilter; + sortField?: string; + query?: string; + sortFieldOrder?: 'asc' | 'desc'; + } + | undefined; + +// @alpha +export type GetPaginatedEntitiesRequest = + | GetPaginatedEntitiesInitialRequest + | GetPaginatedEntitiesCursorRequest; + +// @alpha +export type GetPaginatedEntitiesResponse = { + entities: Entity[]; + totalItems: number; + next?( + request?: Omit, + ): Promise; + prev?( + request?: Omit, + ): Promise; +}; + // @public type Location_2 = { id: string; diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 03fdd600e9..5846430a78 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -207,6 +207,8 @@ export class CatalogClient implements CatalogApi { /** * {@inheritdoc CatalogApi.getPaginatedEntities} + * + * @alpha */ async getPaginatedEntities?( request?: GetPaginatedEntitiesRequest, diff --git a/packages/catalog-client/src/index.ts b/packages/catalog-client/src/index.ts index f0b10a3eef..2e81942c2f 100644 --- a/packages/catalog-client/src/index.ts +++ b/packages/catalog-client/src/index.ts @@ -22,4 +22,3 @@ export { CatalogClient } from './CatalogClient'; export * from './types'; -export * from './utils'; diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 1390a0576e..b273eb9e13 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -356,6 +356,11 @@ export type AddLocationRequest = { dryRun?: boolean; }; +/** + * Used for filtering entities that match the given patterns. + * + * @public + */ export type EntitiesFilter = | Record[] | Record @@ -481,12 +486,12 @@ export interface CatalogApi { /** * Gets paginated entities from the catalog. - * The method takes - * @alpha + * * @remarks * * Example: * + * ``` * const response = await catalogClient.getPaginatedEntities({ * filter: [{ kind: 'group' }], * limit: 20, @@ -494,6 +499,7 @@ export interface CatalogApi { * sortField: 'metadata.name', * sortFieldOrder: 'asc' * }); + * ``` * * this will match all entities of type group having a name starting * with 'A', ordered by name ascending. @@ -502,12 +508,16 @@ export interface CatalogApi { * more than 20 entities exist, the response will contain a next function, invocable * using: * + * ``` * const secondBatchResponse = await response.next({ limit: 20 }); + * ``` * * secondBatchResponse will contain the next batch of maximum 20 entities, together * with a prev function useful for navigating backwards and a next function * in case more entities matching the filters of the first request are present in the catalog. * + * @alpha + * * @param request - Request parameters * @param options - Additional options */ diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts index 7da07979fc..e85b86f4af 100644 --- a/packages/catalog-client/src/types/index.ts +++ b/packages/catalog-client/src/types/index.ts @@ -25,6 +25,7 @@ export type { EntityOrderQuery, GetEntitiesByRefsRequest, GetEntitiesByRefsResponse, + EntitiesFilter, GetEntitiesRequest, GetEntitiesResponse, GetEntityAncestorsRequest, @@ -35,6 +36,7 @@ export type { ValidateEntityResponse, GetPaginatedEntitiesCursorRequest, GetPaginatedEntitiesInitialRequest, + GetPaginatedEntitiesRequest, GetPaginatedEntitiesResponse, } from './api'; export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status'; diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 35c1f7153b..8f043a594b 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -717,7 +717,7 @@ describe('DefaultEntitiesCatalog', () => { .map(e => addEntityToSearch(knex, e)), ); - const catalog = new DefaultEntitiesCatalog(knex); + const catalog = new DefaultEntitiesCatalog(knex, stitcher); const filter = { key: 'spec.should_include_this', @@ -869,7 +869,7 @@ describe('DefaultEntitiesCatalog', () => { .map(e => addEntityToSearch(knex, e)), ); - const catalog = new DefaultEntitiesCatalog(knex); + const catalog = new DefaultEntitiesCatalog(knex, stitcher); const filter = { key: 'spec.should_include_this', @@ -1023,7 +1023,7 @@ describe('DefaultEntitiesCatalog', () => { .map(e => addEntityToSearch(knex, e)), ); - const catalog = new DefaultEntitiesCatalog(knex); + const catalog = new DefaultEntitiesCatalog(knex, stitcher); const filter = { key: 'spec.should_include_this', @@ -1064,7 +1064,7 @@ describe('DefaultEntitiesCatalog', () => { ), ); - const catalog = new DefaultEntitiesCatalog(knex); + const catalog = new DefaultEntitiesCatalog(knex, stitcher); const request: PaginatedEntitiesInitialRequest = { limit: 0, @@ -1346,7 +1346,7 @@ describe('DefaultEntitiesCatalog', () => { ], }); - const catalog = new DefaultEntitiesCatalog(knex); + const catalog = new DefaultEntitiesCatalog(knex, stitcher); await expect( catalog.facets({ From 9ca120a52195ba22f0c937d25c43284cc2c619bd Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 21:46:57 +0200 Subject: [PATCH 010/417] Remove unused comment Signed-off-by: Vincenzo Scamporlino --- .../src/service/DefaultEntitiesCatalog.ts | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index bdd36af483..c471e1379a 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -347,18 +347,6 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isFetchingBackwards = cursor.isPrevious; - /** - * page number is used for quickly - * detecting the initial batch of items - * when navigating backwards without performing - * extra operations on the database. - */ - /* - const currentPage = isFetchingBackwards - ? cursor.previousPage - 1 - : cursor.previousPage + 1; - */ - const dbQuery = db('search') .join('final_entities', 'search.entity_id', 'final_entities.entity_id') .where('key', cursor.sortField); @@ -393,8 +381,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { ? invertOrder(cursor.sortFieldOrder) : cursor.sortFieldOrder, ) - // fetch an extra item for - // checking if there are more items + // fetch an extra item to check if there are more items. .limit(isFetchingBackwards ? limit : limit + 1); countQuery.count('search.entity_id', { as: 'count' }); From b8c262e4fbd2ee73acb9b1d082b817c6895d2bf2 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 23 Jun 2022 23:01:37 +0200 Subject: [PATCH 011/417] Remove sortField guard Signed-off-by: Vincenzo Scamporlino --- .../src/service/DefaultEntitiesCatalog.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index c471e1379a..9190c76dcc 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -336,15 +336,6 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { ...parseCursorFromRequest(request), }; - const allowedSortFields = ['metadata.name', 'metadata.uid']; - if (!allowedSortFields.includes(cursor.sortField)) { - throw new InputError( - `Invalid sortField. Allowed values are ${allowedSortFields.join( - ', ', - )}.`, - ); - } - const isFetchingBackwards = cursor.isPrevious; const dbQuery = db('search') From 5b35637307e072872bd51af8415f375fa21508d0 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 9 Sep 2022 11:17:21 +0200 Subject: [PATCH 012/417] catalog: add support for multiple sortfields Signed-off-by: Vincenzo Scamporlino --- .../catalog-client/src/CatalogClient.test.ts | 11 ++-- packages/catalog-client/src/CatalogClient.ts | 18 ++---- packages/catalog-client/src/types/api.ts | 8 ++- plugins/catalog-backend/src/catalog/types.ts | 26 +++++---- .../service/DefaultEntitiesCatalog.test.ts | 8 +-- .../src/service/DefaultEntitiesCatalog.ts | 47 ++++++++------- .../src/service/createRouter.test.ts | 6 +- .../parseEntitySortFieldParams.test.ts | 57 +++++++++++++++++++ .../request/parseEntitySortFieldParams.ts | 41 +++++++++++++ .../parsePaginatedEntitiesParams.test.ts | 14 ++--- .../request/parsePaginatedEntitiesParams.ts | 23 +------- 11 files changed, 173 insertions(+), 86 deletions(-) create mode 100644 plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.test.ts create mode 100644 plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 8a449c730e..4e5065e089 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -362,11 +362,13 @@ describe('CatalogClient', () => { fields: ['a', 'b'], limit: 100, query: 'query', - sortField: 'metadata.name', - sortFieldOrder: 'asc', + sortFields: [ + { field: 'metadata.name', order: 'asc' }, + { field: 'metadata.uid', order: 'desc' }, + ], }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( - '?limit=100&sortField=metadata.name&sortFieldOrder=asc&fields=a,b&query=query', + '?limit=100&sortField=metadata.name,asc&sortField=metadata.uid,desc&fields=a,b&query=query', ); }); @@ -383,8 +385,7 @@ describe('CatalogClient', () => { fields: ['a', 'b'], limit: 100, query: 'query', - sortField: 'metadata.name', - sortFieldOrder: 'asc', + sortFields: [{ field: 'metadata.name', order: 'asc' }], cursor: 'cursor', }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 5846430a78..18b614fd2e 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -217,24 +217,16 @@ export class CatalogClient implements CatalogApi { const params: string[] = []; if (isPaginatedEntitiesInitialRequest(request)) { - const { - fields = [], - filter, - limit, - sortField, - sortFieldOrder, - query, - } = request ?? {}; + const { fields = [], filter, limit, sortFields, query } = request ?? {}; params.push(...this.getParams(filter)); if (limit !== undefined) { params.push(`limit=${limit}`); } - if (sortField !== undefined) { - params.push(`sortField=${sortField}`); - } - if (sortFieldOrder !== undefined) { - params.push(`sortFieldOrder=${sortFieldOrder}`); + if (sortFields !== undefined) { + sortFields.forEach(({ field, order }) => + params.push(`sortField=${field},${order}`), + ); } if (fields.length) { params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index b273eb9e13..d006a6877c 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -366,6 +366,11 @@ export type EntitiesFilter = | Record | undefined; +/** + * Used for sorting the entities. + */ +export type EntitySortField = { field: string; order: 'asc' | 'desc' }; + /** * The response type for {@link CatalogClient.addLocation}. * @@ -411,9 +416,8 @@ export type GetPaginatedEntitiesInitialRequest = fields?: string[]; limit?: number; filter?: EntitiesFilter; - sortField?: string; + sortFields?: EntitySortField[]; query?: string; - sortFieldOrder?: 'asc' | 'desc'; } | undefined; diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 9f5ad642f2..966e09b821 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -46,6 +46,12 @@ export type EntityOrder = { order: 'asc' | 'desc'; }; +// TODO(vinzscam): remove this type in favor of EntityOrder +export type EntitySortField = { + field: string; + order?: 'asc' | 'desc' | undefined; +}; + /** * Matches rows in the search table. * @public @@ -234,9 +240,8 @@ export interface PaginatedEntitiesInitialRequest { fields?: (entity: Entity) => Entity; limit?: number; filter?: EntityFilter; - sortField?: string; + sortFields?: EntitySortField[]; query?: string; - sortFieldOrder?: 'asc' | 'desc' | undefined; } /** @@ -283,20 +288,19 @@ export interface PaginatedEntitiesResponse { */ export type Cursor = { /** - * the id of the field used for sorting the data. - * For example, metadata.name + * An array of fields used for sorting the data. + * For example, [ { field: 'metadata.name', order: 'asc' } ] */ - sortField: string; + sortFields: EntitySortField[]; /** - * The value of the last item returned - * by the request. This is used for performing - * cursor based pagination. + * The value of the cursor of the last item returned. + * This is used for performing pagination. */ - sortFieldId: string; + sortFieldIds: string[]; + /** - * In which order the data should be paginated. + * A filter to apply on the full list of entities. */ - sortFieldOrder: 'asc' | 'desc'; filter?: EntityFilter; /** * true if the cursor is a previous cursor. diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 8f043a594b..af4bacadaa 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -729,7 +729,7 @@ describe('DefaultEntitiesCatalog', () => { const request1: PaginatedEntitiesInitialRequest = { filter, limit, - sortField: 'metadata.name', + sortFields: [{ field: 'metadata.name' }], }; const response1 = await catalog.paginatedEntities(request1); expect(response1.entities).toEqual([entityFrom('A'), entityFrom('B')]); @@ -881,8 +881,7 @@ describe('DefaultEntitiesCatalog', () => { const request1: PaginatedEntitiesInitialRequest = { filter, limit, - sortField: 'metadata.name', - sortFieldOrder: 'desc', + sortFields: [{ field: 'metadata.name', order: 'desc' }], }; const response1 = await catalog.paginatedEntities(request1); expect(response1.entities).toEqual([entityFrom('G'), entityFrom('F')]); @@ -1032,7 +1031,8 @@ describe('DefaultEntitiesCatalog', () => { const request: PaginatedEntitiesInitialRequest = { filter, limit: 100, - sortField: 'metadata.name', + + sortFields: [{ field: 'metadata.name' }], query: 'cAt ', }; const response = await catalog.paginatedEntities(request); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 9190c76dcc..022313db7c 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -35,6 +35,7 @@ import { EntityFacetsResponse, EntityFilter, EntityPagination, + EntitySortField, PaginatedEntitiesRequest, PaginatedEntitiesResponse, } from '../catalog/types'; @@ -54,8 +55,10 @@ import { isPaginatedEntitiesInitialRequest, } from './util'; -const defaultSortField = 'metadata.name'; -const defaultSortFieldOrder = 'asc'; +const defaultSortField: EntitySortField = { + field: 'metadata.name', + order: 'asc', +}; function parsePagination(input?: EntityPagination): { limit?: number; @@ -328,19 +331,26 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const db = this.database; const limit = request?.limit ?? 20; - const cursor: Omit & { sortFieldId?: string } = { + const cursor: Omit & { sortFieldIds?: string[] } = { firstFieldId: '', - sortField: defaultSortField, - sortFieldOrder: defaultSortFieldOrder, + sortFields: [defaultSortField], isPrevious: false, ...parseCursorFromRequest(request), }; const isFetchingBackwards = cursor.isPrevious; + // TODO(vinzscam): at the moment only a single sortField is supported + const sortField: EntitySortField = { + ...defaultSortField, + ...cursor.sortFields[0], + }; + + const sortFieldId = cursor.sortFieldIds?.[0]; + const dbQuery = db('search') .join('final_entities', 'search.entity_id', 'final_entities.entity_id') - .where('key', cursor.sortField); + .where('key', sortField.field); if (cursor.filter) { parseFilter(cursor.filter, dbQuery, db, false, 'search.entity_id'); @@ -356,21 +366,19 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const countQuery = dbQuery.clone(); - const isOrderingDescending = cursor.sortFieldOrder === 'desc'; - if (cursor.sortFieldId) { + const isOrderingDescending = sortField.order === 'desc'; + if (sortFieldId) { dbQuery.andWhere( 'value', isFetchingBackwards !== isOrderingDescending ? '<' : '>', - cursor.sortFieldId, + sortFieldId, ); } dbQuery .orderBy( 'value', - isFetchingBackwards - ? invertOrder(cursor.sortFieldOrder) - : cursor.sortFieldOrder, + isFetchingBackwards ? invertOrder(sortField.order) : sortField.order, ) // fetch an extra item to check if there are more items. .limit(isFetchingBackwards ? limit : limit + 1); @@ -408,7 +416,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const nextCursor = hasMoreResults ? encodeCursor({ ...cursor, - sortFieldId: rows[rows.length - 1].value, + sortFieldIds: [rows[rows.length - 1].value], firstFieldId, isPrevious: false, totalItems, @@ -421,7 +429,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { rows[0].value !== cursor.firstFieldId ? encodeCursor({ ...cursor, - sortFieldId: rows[0].value, + sortFieldIds: [rows[0].value], firstFieldId: cursor.firstFieldId, isPrevious: true, totalItems, @@ -625,13 +633,8 @@ function parseCursorFromRequest( request?: PaginatedEntitiesRequest, ): Partial { if (isPaginatedEntitiesInitialRequest(request)) { - const { - filter, - sortField = defaultSortField, - sortFieldOrder = defaultSortFieldOrder, - query, - } = request; - return { filter, sortField, sortFieldOrder, query }; + const { filter, sortFields = [defaultSortField], query } = request; + return { filter, sortFields, query }; } if (isPaginatedEntitiesCursorRequest(request)) { try { @@ -646,6 +649,6 @@ function parseCursorFromRequest( return {}; } -function invertOrder(order: Cursor['sortFieldOrder']) { +function invertOrder(order: EntitySortField['order']) { return order === 'asc' ? 'desc' : 'asc'; } diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 6e2d52c63e..c3b96fbfd8 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -163,7 +163,7 @@ describe('createRouter readonly disabled', () => { totalItems: 0, }); const response = await request(app).get( - '/v2beta1/entities?filter=a=1,a=2,b=3&filter=c=4', + '/v2beta1/entities?filter=a=1,a=2,b=3&filter=c=4&sortField=metadata.name,asc&sortField=metadata.uid,desc', ); expect(response.status).toEqual(200); @@ -180,6 +180,10 @@ describe('createRouter readonly disabled', () => { { allOf: [{ key: 'c', values: ['4'] }] }, ], }, + sortFields: [ + { field: 'metadata.name', order: 'asc' }, + { field: 'metadata.uid', order: 'desc' }, + ], }); }); diff --git a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.test.ts b/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.test.ts new file mode 100644 index 0000000000..35f7c2cac0 --- /dev/null +++ b/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2022 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 { parseEntitySortFieldParams } from './parseEntitySortFieldParams'; + +describe('parseEntitySortFieldParams', () => { + it('supports no sort fields', () => { + const result = parseEntitySortFieldParams({}); + expect(result).toEqual(undefined); + }); + + it('supports single sortField', () => { + const result = parseEntitySortFieldParams({ + sortField: ['metadata.name,desc'], + })!; + expect(result).toEqual([{ field: 'metadata.name', order: 'desc' }]); + }); + + it('supports single sortField without order', () => { + const result = parseEntitySortFieldParams({ + sortField: ['metadata.name'], + })!; + expect(result).toEqual([{ field: 'metadata.name' }]); + }); + + it('supports multiple sort fields', () => { + const result = parseEntitySortFieldParams({ + sortField: ['metadata.name,desc', 'metadata.uid,asc'], + }); + + expect(result).toEqual([ + { field: 'metadata.name', order: 'desc' }, + { field: 'metadata.uid', order: 'asc' }, + ]); + }); + + it('throws if sortField order is not valid', () => { + expect(() => + parseEntitySortFieldParams({ + sortField: ['metadata.name,desc', 'metadata.uid,invalid'], + }), + ).toThrow(/Invalid sort field order/); + }); +}); diff --git a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts b/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts new file mode 100644 index 0000000000..d16295aa30 --- /dev/null +++ b/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2022 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 { InputError } from '@backstage/errors'; +import { EntitySortField } from '../../catalog/types'; +import { parseStringsParam } from './common'; + +export function parseEntitySortFieldParams( + params: Record, +): EntitySortField[] | undefined { + const sortFieldStrings = parseStringsParam(params.sortField, 'sortField'); + if (!sortFieldStrings) { + return undefined; + } + + return sortFieldStrings.map(sortFieldString => { + const [field, order] = sortFieldString.split(','); + + if (order !== undefined && !isOrder(order)) { + throw new InputError('Invalid sort field order, must be asc or desc'); + } + return { field, order }; + }); +} + +export function isOrder(order: string): order is 'asc' | 'desc' { + return ['asc', 'desc'].includes(order); +} diff --git a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts index 838b931888..53d44c8ca5 100644 --- a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts @@ -28,8 +28,7 @@ describe('parsePaginatedEntitiesParams', () => { fields: ['kind'], limit: '3', filter: ['a=1', 'b=2'], - sortField: 'sortField', - sortFieldOrder: 'desc', + sortField: ['metadata.name,desc'], query: 'query', }; const parsedObj = parsePaginatedEntitiesParams( @@ -37,8 +36,9 @@ describe('parsePaginatedEntitiesParams', () => { ) as PaginatedEntitiesInitialRequest; expect(parsedObj.limit).toBe(3); expect(parsedObj.fields).toBeDefined(); - expect(parsedObj.sortField).toBe('sortField'); - expect(parsedObj.sortFieldOrder).toBe('desc'); + expect(parsedObj.sortFields).toEqual([ + { field: 'metadata.name', order: 'desc' }, + ]); expect(parsedObj.filter).toBeDefined(); expect(parsedObj.query).toBe('query'); expect(parsedObj).not.toHaveProperty('authorizationToken'); @@ -50,8 +50,7 @@ describe('parsePaginatedEntitiesParams', () => { ) as PaginatedEntitiesInitialRequest; expect(parsedObj.limit).toBeUndefined(); expect(parsedObj.fields).toBeUndefined(); - expect(parsedObj.sortField).toBeUndefined(); - expect(parsedObj.sortFieldOrder).toBeUndefined(); + expect(parsedObj.sortFields).toBeUndefined(); expect(parsedObj.filter).toBeUndefined(); expect(parsedObj.query).toBeUndefined(); expect(parsedObj).not.toHaveProperty('authorizationToken'); @@ -63,8 +62,7 @@ describe('parsePaginatedEntitiesParams', () => { limit: 'asd', }, { filter: 3 }, - { sortField: [] }, - { sortFieldOrder: 'something' }, + { sortField: ['metadata.uid,diagonal'] }, { fields: [4] }, { query: [] }, ])('should throw if some parameter is not valid %p', params => { diff --git a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts index 84d519ec0b..f5730d3297 100644 --- a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts +++ b/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { InputError } from '@backstage/errors'; import { PaginatedEntitiesCursorRequest, PaginatedEntitiesInitialRequest, @@ -22,6 +21,7 @@ import { } from '../../catalog/types'; import { parseIntegerParam, parseStringParam } from './common'; import { parseEntityFilterParams } from './parseEntityFilterParams'; +import { parseEntitySortFieldParams } from './parseEntitySortFieldParams'; import { parseEntityTransformParams } from './parseEntityTransformParams'; export function parsePaginatedEntitiesParams( @@ -42,33 +42,16 @@ export function parsePaginatedEntitiesParams( const filter = parseEntityFilterParams(params); const query = parseStringParam(params.query, 'query'); - const sortField = parseStringParam(params.sortField, 'sortField'); - const sortFieldOrder = parseSortFieldOrder( - params.sortFieldOrder, - 'sortFieldOrder', - ); + const sortFields = parseEntitySortFieldParams(params); const response: Omit = { fields, filter, limit, - sortField, - sortFieldOrder, + sortFields, query, }; return response; } - -function parseSortFieldOrder(sortFieldOrder: unknown, ctx: string) { - const isSortFieldOrder = - sortFieldOrder === undefined || - sortFieldOrder === 'asc' || - sortFieldOrder === 'desc'; - - if (isSortFieldOrder) { - return sortFieldOrder; - } - throw new InputError(`Invalid ${ctx}, not asc or desc`); -} From 34b15da9a7bf4bc236cfe9d83773e383e44f8750 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 13 Sep 2022 11:00:38 +0200 Subject: [PATCH 013/417] catalog-client: export EntitySortField Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 9 +++++++-- packages/catalog-client/src/types/api.ts | 2 ++ packages/catalog-client/src/types/index.ts | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index f612407b1d..22afa0457e 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -188,6 +188,12 @@ export type EntityOrderQuery = order: 'asc' | 'desc'; }>; +// @public +export type EntitySortField = { + field: string; + order: 'asc' | 'desc'; +}; + // @public export interface GetEntitiesByRefsRequest { entityRefs: string[]; @@ -262,9 +268,8 @@ export type GetPaginatedEntitiesInitialRequest = fields?: string[]; limit?: number; filter?: EntitiesFilter; - sortField?: string; + sortFields?: EntitySortField[]; query?: string; - sortFieldOrder?: 'asc' | 'desc'; } | undefined; diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index d006a6877c..26c16af64d 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -368,6 +368,8 @@ export type EntitiesFilter = /** * Used for sorting the entities. + * + * @public */ export type EntitySortField = { field: string; order: 'asc' | 'desc' }; diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts index e85b86f4af..61a993eb19 100644 --- a/packages/catalog-client/src/types/index.ts +++ b/packages/catalog-client/src/types/index.ts @@ -26,6 +26,7 @@ export type { GetEntitiesByRefsRequest, GetEntitiesByRefsResponse, EntitiesFilter, + EntitySortField, GetEntitiesRequest, GetEntitiesResponse, GetEntityAncestorsRequest, From f2776735343d29988a90fdeb639b0f6d880ae3b3 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 29 Dec 2022 22:54:46 -0600 Subject: [PATCH 014/417] catalog-backend: improve cursor properties and docs Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 966e09b821..30472782a8 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -293,13 +293,11 @@ export type Cursor = { */ sortFields: EntitySortField[]; /** - * The value of the cursor of the last item returned. - * This is used for performing pagination. + * The values of the fields of a specific item used for paginating the data. */ - sortFieldIds: string[]; - + sortFieldValues: string[]; /** - * A filter to apply on the full list of entities. + * A filter to be applied to the full list of entities. */ filter?: EntityFilter; /** @@ -307,15 +305,15 @@ export type Cursor = { */ isPrevious: boolean; /** - * Filter the data by name. + * Used for filtering the data by name. */ query?: string; /** - * Sort field id of the first item. - * The catalog uses this field internally for understanding when the beginning + * The value of the fields of the first returned item used for paginating the data. + * The catalog uses this field internally to understand if the beginning * of the list has been reached when performing cursor based pagination. */ - firstFieldId: string; + firstSortFieldValues?: string[]; /** * The number of items that match the provided filters */ From 77a08f4ffce0fab40cbc52ea5d31a5eb8b37ab54 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 29 Dec 2022 22:56:07 -0600 Subject: [PATCH 015/417] catalog-backend: handle clashing items on pagination Signed-off-by: Vincenzo Scamporlino --- .../service/DefaultEntitiesCatalog.test.ts | 134 +++++++++++++++--- .../src/service/DefaultEntitiesCatalog.ts | 73 +++++++--- 2 files changed, 168 insertions(+), 39 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index af4bacadaa..d5619ec540 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -85,8 +85,7 @@ describe('DefaultEntitiesCatalog', () => { return id; } - async function addEntityToSearch(knex: Knex, entity: Entity) { - const id = uuid(); + async function addEntityToSearch(knex: Knex, entity: Entity, id = uuid()) { const entityRef = stringifyEntityRef(entity); const entityJson = JSON.stringify(entity); @@ -746,7 +745,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response2.entities).toEqual([entityFrom('C'), entityFrom('D')]); expect(response2.nextCursor).toBeDefined(); expect(response2.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response2.totalItems).toBe(names.length); // third request (forward) const request3: PaginatedEntitiesCursorRequest = { @@ -757,7 +756,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response3.entities).toEqual([entityFrom('E'), entityFrom('F')]); expect(response3.nextCursor).toBeDefined(); expect(response3.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response3.totalItems).toBe(names.length); // fourth request (backwards) const request4: PaginatedEntitiesCursorRequest = { @@ -768,7 +767,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response4.entities).toEqual([entityFrom('C'), entityFrom('D')]); expect(response4.nextCursor).toBeDefined(); expect(response4.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response4.totalItems).toBe(names.length); // fifth request (backwards) const request5: PaginatedEntitiesCursorRequest = { @@ -779,7 +778,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response5.entities).toEqual([entityFrom('A'), entityFrom('B')]); expect(response5.nextCursor).toBeDefined(); expect(response5.prevCursor).toBeUndefined(); - expect(response1.totalItems).toBe(names.length); + expect(response5.totalItems).toBe(names.length); // sixth request (forward) const request6: PaginatedEntitiesCursorRequest = { @@ -790,7 +789,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response6.entities).toEqual([entityFrom('C'), entityFrom('D')]); expect(response6.nextCursor).toBeDefined(); expect(response6.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response6.totalItems).toBe(names.length); // seventh request (forward) const request7: PaginatedEntitiesCursorRequest = { @@ -801,7 +800,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response7.entities).toEqual([entityFrom('E'), entityFrom('F')]); expect(response7.nextCursor).toBeDefined(); expect(response7.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response7.totalItems).toBe(names.length); // seventh.2 request (forward with a different limit) const request7bis: PaginatedEntitiesCursorRequest = { @@ -816,7 +815,7 @@ describe('DefaultEntitiesCatalog', () => { ]); expect(response7bis.nextCursor).toBeUndefined(); expect(response7bis.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response7bis.totalItems).toBe(names.length); // last request (forward) const request8: PaginatedEntitiesCursorRequest = { @@ -827,7 +826,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response8.entities).toEqual([entityFrom('G')]); expect(response8.nextCursor).toBeUndefined(); expect(response8.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response8.totalItems).toBe(names.length); }, ); @@ -898,7 +897,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response2.entities).toEqual([entityFrom('E'), entityFrom('D')]); expect(response2.nextCursor).toBeDefined(); expect(response2.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response2.totalItems).toBe(names.length); // third request (forward) const request3: PaginatedEntitiesCursorRequest = { @@ -909,7 +908,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response3.entities).toEqual([entityFrom('C'), entityFrom('B')]); expect(response3.nextCursor).toBeDefined(); expect(response3.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response3.totalItems).toBe(names.length); // fourth request (backwards) const request4: PaginatedEntitiesCursorRequest = { @@ -921,7 +920,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response4.entities).toEqual([entityFrom('E'), entityFrom('D')]); expect(response4.nextCursor).toBeDefined(); expect(response4.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response4.totalItems).toBe(names.length); // fifth request (backwards) const request5: PaginatedEntitiesCursorRequest = { @@ -932,7 +931,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response5.entities).toEqual([entityFrom('G'), entityFrom('F')]); expect(response5.nextCursor).toBeDefined(); expect(response5.prevCursor).toBeUndefined(); - expect(response1.totalItems).toBe(names.length); + expect(response5.totalItems).toBe(names.length); // sixth request (forward) const request6: PaginatedEntitiesCursorRequest = { @@ -943,7 +942,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response6.entities).toEqual([entityFrom('E'), entityFrom('D')]); expect(response6.nextCursor).toBeDefined(); expect(response6.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response6.totalItems).toBe(names.length); // seventh request (forward) const request7: PaginatedEntitiesCursorRequest = { @@ -954,7 +953,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response7.entities).toEqual([entityFrom('C'), entityFrom('B')]); expect(response7.nextCursor).toBeDefined(); expect(response7.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response7.totalItems).toBe(names.length); // seventh.2 request (forward with a different limit) const request7bis: PaginatedEntitiesCursorRequest = { @@ -969,7 +968,7 @@ describe('DefaultEntitiesCatalog', () => { ]); expect(response7bis.nextCursor).toBeUndefined(); expect(response7bis.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response7bis.totalItems).toBe(names.length); // last request (forward) const request8: PaginatedEntitiesCursorRequest = { @@ -980,7 +979,7 @@ describe('DefaultEntitiesCatalog', () => { expect(response8.entities).toEqual([entityFrom('A')]); expect(response8.nextCursor).toBeUndefined(); expect(response8.prevCursor).toBeDefined(); - expect(response1.totalItems).toBe(names.length); + expect(response8.totalItems).toBe(names.length); }, ); @@ -1073,6 +1072,105 @@ describe('DefaultEntitiesCatalog', () => { expect(response).toEqual({ totalItems: 20, entities: [] }); }, ); + + it.each(databases.eachSupportedId())( + 'should paginate results accordingly in case of clashing items, %p', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + function entityFrom(name: string, namespace?: string) { + return { + apiVersion: 'a', + kind: 'k', + metadata: { name, ...(!!namespace && { namespace }) }, + spec: { should_include_this: 'yes' }, + }; + } + + await Promise.all([ + addEntityToSearch(knex, entityFrom('AA')), + addEntityToSearch(knex, entityFrom('AA', 'namespace2')), + addEntityToSearch(knex, entityFrom('AA', 'namespace3')), + addEntityToSearch(knex, entityFrom('AA', 'namespace4')), + addEntityToSearch(knex, entityFrom('CC')), + addEntityToSearch(knex, entityFrom('DD')), + ]); + + const catalog = new DefaultEntitiesCatalog(knex); + + const limit = 2; + + // initial request + const request1: PaginatedEntitiesInitialRequest = { + limit, + sortFields: [{ field: 'metadata.name' }], + }; + const response1 = await catalog.paginatedEntities(request1); + expect(response1.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response1.nextCursor).toBeDefined(); + expect(response1.prevCursor).toBeUndefined(); + expect(response1.totalItems).toBe(6); + + // second request (forward) + const request2: PaginatedEntitiesCursorRequest = { + cursor: response1.nextCursor!, + limit, + }; + const response2 = await catalog.paginatedEntities(request2); + expect(response2.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response2.nextCursor).toBeDefined(); + expect(response2.prevCursor).toBeDefined(); + expect(response2.totalItems).toBe(6); + + // third request (forward) + const request3: PaginatedEntitiesCursorRequest = { + cursor: response2.nextCursor!, + limit, + }; + const response3 = await catalog.paginatedEntities(request3); + expect(response3.entities).toEqual([ + entityFrom('CC'), + entityFrom('DD'), + ]); + expect(response3.nextCursor).toBeUndefined(); + expect(response3.prevCursor).toBeDefined(); + expect(response3.totalItems).toBe(6); + + // forth request (backward) + const request4: PaginatedEntitiesCursorRequest = { + cursor: response3.prevCursor!, + limit, + }; + const response4 = await catalog.paginatedEntities(request4); + expect(response4.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response4.nextCursor).toBeDefined(); + expect(response4.prevCursor).toBeDefined(); + expect(response4.totalItems).toBe(6); + + // fifth request (backward) + const request5: PaginatedEntitiesCursorRequest = { + cursor: response4.prevCursor!, + limit, + }; + const response5 = await catalog.paginatedEntities(request5); + expect(response5.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response5.nextCursor).toBeDefined(); + expect(response5.prevCursor).toBeUndefined(); + expect(response5.totalItems).toBe(6); + }, + ); }); describe('removeEntityByUid', () => { diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 022313db7c..ce330eb9c1 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -20,8 +20,8 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { InputError, NotFoundError } from '@backstage/errors'; -import lodash from 'lodash'; import { Knex } from 'knex'; +import { isEqual } from 'lodash'; import { EntitiesBatchRequest, EntitiesBatchResponse, @@ -331,8 +331,9 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const db = this.database; const limit = request?.limit ?? 20; - const cursor: Omit & { sortFieldIds?: string[] } = { - firstFieldId: '', + const cursor: Omit & { + sortFieldValues?: string[]; + } = { sortFields: [defaultSortField], isPrevious: false, ...parseCursorFromRequest(request), @@ -346,11 +347,11 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { ...cursor.sortFields[0], }; - const sortFieldId = cursor.sortFieldIds?.[0]; + const [sortFieldId, metadataSortFieldId] = cursor.sortFieldValues || []; const dbQuery = db('search') .join('final_entities', 'search.entity_id', 'final_entities.entity_id') - .where('key', sortField.field); + .where('search.key', sortField.field); if (cursor.filter) { parseFilter(cursor.filter, dbQuery, db, false, 'search.entity_id'); @@ -368,18 +369,36 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isOrderingDescending = sortField.order === 'desc'; if (sortFieldId) { - dbQuery.andWhere( - 'value', - isFetchingBackwards !== isOrderingDescending ? '<' : '>', - sortFieldId, - ); + dbQuery + .andWhere( + 'value', + isFetchingBackwards !== isOrderingDescending ? '<' : '>', + sortFieldId, + ) + .orWhere(function nested() { + this.where('value', '=', sortFieldId).andWhere( + 'search.entity_id', + isFetchingBackwards !== isOrderingDescending ? '<' : '>', + metadataSortFieldId, + ); + }); } dbQuery - .orderBy( - 'value', - isFetchingBackwards ? invertOrder(sortField.order) : sortField.order, - ) + .orderBy([ + { + column: 'value', + order: isFetchingBackwards + ? invertOrder(sortField.order) + : sortField.order, + }, + { + column: 'search.entity_id', + order: isFetchingBackwards + ? invertOrder(sortField.order) + : sortField.order, + }, + ]) // fetch an extra item to check if there are more items. .limit(isFetchingBackwards ? limit : limit + 1); @@ -409,15 +428,22 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { rows.length -= 1; } - const isInitialRequest = cursor.firstFieldId === ''; + const isInitialRequest = cursor.firstSortFieldValues === undefined; - const firstFieldId = cursor.firstFieldId || rows[0]?.value; + const firstSortFieldValues = cursor.firstSortFieldValues || [ + rows[0]?.value, + rows[0]?.entity_id, + ]; const nextCursor = hasMoreResults ? encodeCursor({ ...cursor, - sortFieldIds: [rows[rows.length - 1].value], - firstFieldId, + sortFieldValues: [ + // TODO generalize + rows[rows.length - 1].value, + rows[rows.length - 1].entity_id, + ], + firstSortFieldValues, isPrevious: false, totalItems, }) @@ -426,11 +452,12 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const prevCursor = !isInitialRequest && rows.length > 0 && - rows[0].value !== cursor.firstFieldId + !isEqual(sortFieldsFromRow(rows[0]), cursor.firstSortFieldValues) ? encodeCursor({ ...cursor, - sortFieldIds: [rows[0].value], - firstFieldId: cursor.firstFieldId, + // TODO generalize + sortFieldValues: [rows[0].value, rows[0].entity_id], + firstSortFieldValues: cursor.firstSortFieldValues, isPrevious: true, totalItems, }) @@ -652,3 +679,7 @@ function parseCursorFromRequest( function invertOrder(order: EntitySortField['order']) { return order === 'asc' ? 'desc' : 'asc'; } + +function sortFieldsFromRow(row: DbSearchRow) { + return [row.value, row.entity_id]; +} From f0135c34ab9581c22e10d9c44fb247b38fcd1efb Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 2 Jan 2023 11:36:24 -0600 Subject: [PATCH 016/417] catalog: destroy knex connections once done Signed-off-by: Vincenzo Scamporlino --- .../service/DefaultEntitiesCatalog.test.ts | 155 +++++++++--------- 1 file changed, 75 insertions(+), 80 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index d5619ec540..9d03cf5c61 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -35,6 +35,12 @@ import { DefaultEntitiesCatalog } from './DefaultEntitiesCatalog'; import { EntitiesRequest } from '../catalog/types'; describe('DefaultEntitiesCatalog', () => { + let knex: Knex; + + afterEach(async () => { + await knex.destroy(); + }); + const databases = TestDatabases.create({ ids: ['MYSQL_8', 'POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], }); @@ -42,13 +48,11 @@ describe('DefaultEntitiesCatalog', () => { const stitcher: Stitcher = { stitch } as any; async function createDatabase(databaseId: TestDatabaseId) { - const knex = await databases.init(databaseId); + knex = await databases.init(databaseId); await applyDatabaseMigrations(knex); - return { knex }; } async function addEntity( - knex: Knex, entity: Entity, parents: { source?: string; entity?: Entity }[], ) { @@ -85,7 +89,7 @@ describe('DefaultEntitiesCatalog', () => { return id; } - async function addEntityToSearch(knex: Knex, entity: Entity, id = uuid()) { + async function addEntityToSearch(entity: Entity, id = uuid()) { const entityRef = stringifyEntityRef(entity); const entityJson = JSON.stringify(entity); @@ -123,7 +127,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return the ancestry with one parent, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const grandparent: Entity = { apiVersion: 'a', @@ -144,9 +148,9 @@ describe('DefaultEntitiesCatalog', () => { spec: {}, }; - await addEntity(knex, grandparent, [{ source: 's' }]); - await addEntity(knex, parent, [{ entity: grandparent }]); - await addEntity(knex, root, [{ entity: parent }]); + await addEntity(grandparent, [{ source: 's' }]); + await addEntity(parent, [{ entity: grandparent }]); + await addEntity(root, [{ entity: parent }]); const catalog = new DefaultEntitiesCatalog(knex, stitcher); const result = await catalog.entityAncestry('k:default/root'); @@ -177,7 +181,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should throw error if the entity does not exist, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const catalog = new DefaultEntitiesCatalog(knex, stitcher); await expect(() => catalog.entityAncestry('k:default/root'), @@ -189,7 +193,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return the ancestry with multiple parents, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const grandparent: Entity = { apiVersion: 'a', @@ -216,10 +220,10 @@ describe('DefaultEntitiesCatalog', () => { spec: {}, }; - await addEntity(knex, grandparent, [{ source: 's' }]); - await addEntity(knex, parent1, [{ entity: grandparent }]); - await addEntity(knex, parent2, [{ entity: grandparent }]); - await addEntity(knex, root, [{ entity: parent1 }, { entity: parent2 }]); + await addEntity(grandparent, [{ source: 's' }]); + await addEntity(parent1, [{ entity: grandparent }]); + await addEntity(parent2, [{ entity: grandparent }]); + await addEntity(root, [{ entity: parent1 }, { entity: parent2 }]); const catalog = new DefaultEntitiesCatalog(knex, stitcher); const result = await catalog.entityAncestry('k:default/root'); @@ -260,7 +264,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return correct entity for simple filter, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const entity1: Entity = { apiVersion: 'a', kind: 'k', @@ -275,8 +279,8 @@ describe('DefaultEntitiesCatalog', () => { test: 'test value', }, }; - await addEntityToSearch(knex, entity1); - await addEntityToSearch(knex, entity2); + await addEntityToSearch(entity1); + await addEntityToSearch(entity2); const catalog = new DefaultEntitiesCatalog(knex, stitcher); const testFilter = { @@ -294,7 +298,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return correct entity for negation filter, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const entity1: Entity = { apiVersion: 'a', kind: 'k', @@ -309,8 +313,8 @@ describe('DefaultEntitiesCatalog', () => { test: 'test value', }, }; - await addEntityToSearch(knex, entity1); - await addEntityToSearch(knex, entity2); + await addEntityToSearch(entity1); + await addEntityToSearch(entity2); const catalog = new DefaultEntitiesCatalog(knex, stitcher); const testFilter = { @@ -330,7 +334,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return correct entities for nested filter, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const entity1: Entity = { apiVersion: 'a', kind: 'k', @@ -355,10 +359,10 @@ describe('DefaultEntitiesCatalog', () => { metadata: { name: 'four', org: 'b', color: 'blue' }, spec: {}, }; - await addEntityToSearch(knex, entity1); - await addEntityToSearch(knex, entity2); - await addEntityToSearch(knex, entity3); - await addEntityToSearch(knex, entity4); + await addEntityToSearch(entity1); + await addEntityToSearch(entity2); + await addEntityToSearch(entity3); + await addEntityToSearch(entity4); const catalog = new DefaultEntitiesCatalog(knex, stitcher); const testFilter1 = { @@ -400,7 +404,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return correct entities for complex negation filter, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const entity1: Entity = { apiVersion: 'a', kind: 'k', @@ -413,8 +417,8 @@ describe('DefaultEntitiesCatalog', () => { metadata: { name: 'two', org: 'b', desc: 'description' }, spec: {}, }; - await addEntityToSearch(knex, entity1); - await addEntityToSearch(knex, entity2); + await addEntityToSearch(entity1); + await addEntityToSearch(entity2); const catalog = new DefaultEntitiesCatalog(knex, stitcher); const testFilter1 = { @@ -443,7 +447,7 @@ describe('DefaultEntitiesCatalog', () => { 'should return no matches for an empty values array, %p', // NOTE: An empty values array is not a sensible input in a realistic scenario. async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const entity1: Entity = { apiVersion: 'a', kind: 'k', @@ -456,8 +460,8 @@ describe('DefaultEntitiesCatalog', () => { metadata: { name: 'two' }, spec: {}, }; - await addEntityToSearch(knex, entity1); - await addEntityToSearch(knex, entity2); + await addEntityToSearch(entity1); + await addEntityToSearch(entity2); const catalog = new DefaultEntitiesCatalog(knex, stitcher); const testFilter = { @@ -475,9 +479,8 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return both target and targetRef for entities', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); await addEntity( - knex, { apiVersion: 'a', kind: 'k', @@ -488,7 +491,6 @@ describe('DefaultEntitiesCatalog', () => { [], ); await addEntity( - knex, { apiVersion: 'a', kind: 'k', @@ -681,7 +683,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return paginated entities and scroll the items accordingly, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); function entityFrom(name: string) { return { @@ -711,9 +713,7 @@ describe('DefaultEntitiesCatalog', () => { ]; await Promise.all( - entities - .concat(notFoundEntities) - .map(e => addEntityToSearch(knex, e)), + entities.concat(notFoundEntities).map(e => addEntityToSearch(e)), ); const catalog = new DefaultEntitiesCatalog(knex, stitcher); @@ -833,7 +833,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should return paginated entities ordered in descending order and scroll the items accordingly, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); function entityFrom(name: string) { return { @@ -863,9 +863,7 @@ describe('DefaultEntitiesCatalog', () => { ]; await Promise.all( - entities - .concat(notFoundEntities) - .map(e => addEntityToSearch(knex, e)), + entities.concat(notFoundEntities).map(e => addEntityToSearch(e)), ); const catalog = new DefaultEntitiesCatalog(knex, stitcher); @@ -986,7 +984,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should filter the results when query is provided, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); function entityFrom(name: string) { return { @@ -1016,9 +1014,7 @@ describe('DefaultEntitiesCatalog', () => { ]; await Promise.all( - entities - .concat(notFoundEntities) - .map(e => addEntityToSearch(knex, e)), + entities.concat(notFoundEntities).map(e => addEntityToSearch(e)), ); const catalog = new DefaultEntitiesCatalog(knex, stitcher); @@ -1049,13 +1045,13 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'should include totalItems and empty entities in the response in case limit is zero, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); await Promise.all( Array(20) .fill(0) .map(() => - addEntityToSearch(knex, { + addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { name: v4() }, @@ -1074,9 +1070,9 @@ describe('DefaultEntitiesCatalog', () => { ); it.each(databases.eachSupportedId())( - 'should paginate results accordingly in case of clashing items, %p', + 'should paginate results without sort fields, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); function entityFrom(name: string, namespace?: string) { return { @@ -1088,12 +1084,12 @@ describe('DefaultEntitiesCatalog', () => { } await Promise.all([ - addEntityToSearch(knex, entityFrom('AA')), - addEntityToSearch(knex, entityFrom('AA', 'namespace2')), - addEntityToSearch(knex, entityFrom('AA', 'namespace3')), - addEntityToSearch(knex, entityFrom('AA', 'namespace4')), - addEntityToSearch(knex, entityFrom('CC')), - addEntityToSearch(knex, entityFrom('DD')), + addEntityToSearch(entityFrom('AA'), 'id1'), + addEntityToSearch(entityFrom('CC'), 'id2'), + addEntityToSearch(entityFrom('AA', 'namespace2'), 'id4'), + addEntityToSearch(entityFrom('AA', 'namespace3'), 'id5'), + addEntityToSearch(entityFrom('AA', 'namespace4'), 'id6'), + addEntityToSearch(entityFrom('DD'), 'id3'), ]); const catalog = new DefaultEntitiesCatalog(knex); @@ -1103,12 +1099,11 @@ describe('DefaultEntitiesCatalog', () => { // initial request const request1: PaginatedEntitiesInitialRequest = { limit, - sortFields: [{ field: 'metadata.name' }], }; const response1 = await catalog.paginatedEntities(request1); expect(response1.entities).toMatchObject([ entityFrom('AA'), - entityFrom('AA'), + entityFrom('CC'), ]); expect(response1.nextCursor).toBeDefined(); expect(response1.prevCursor).toBeUndefined(); @@ -1121,7 +1116,7 @@ describe('DefaultEntitiesCatalog', () => { }; const response2 = await catalog.paginatedEntities(request2); expect(response2.entities).toMatchObject([ - entityFrom('AA'), + entityFrom('DD'), entityFrom('AA'), ]); expect(response2.nextCursor).toBeDefined(); @@ -1135,8 +1130,8 @@ describe('DefaultEntitiesCatalog', () => { }; const response3 = await catalog.paginatedEntities(request3); expect(response3.entities).toEqual([ - entityFrom('CC'), - entityFrom('DD'), + entityFrom('AA'), + entityFrom('AA'), ]); expect(response3.nextCursor).toBeUndefined(); expect(response3.prevCursor).toBeDefined(); @@ -1149,7 +1144,7 @@ describe('DefaultEntitiesCatalog', () => { }; const response4 = await catalog.paginatedEntities(request4); expect(response4.entities).toMatchObject([ - entityFrom('AA'), + entityFrom('DD'), entityFrom('AA'), ]); expect(response4.nextCursor).toBeDefined(); @@ -1164,7 +1159,7 @@ describe('DefaultEntitiesCatalog', () => { const response5 = await catalog.paginatedEntities(request5); expect(response5.entities).toMatchObject([ entityFrom('AA'), - entityFrom('AA'), + entityFrom('CC'), ]); expect(response5.nextCursor).toBeDefined(); expect(response5.prevCursor).toBeUndefined(); @@ -1177,7 +1172,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'also clears parent hashes, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const grandparent: Entity = { apiVersion: 'a', @@ -1216,15 +1211,15 @@ describe('DefaultEntitiesCatalog', () => { spec: {}, }; - await addEntity(knex, grandparent, [{ source: 's' }]); - await addEntity(knex, parent1, [{ entity: grandparent }]); - await addEntity(knex, parent2, [{ entity: grandparent }]); - const uid = await addEntity(knex, root, [ + await addEntity(grandparent, [{ source: 's' }]); + await addEntity(parent1, [{ entity: grandparent }]); + await addEntity(parent2, [{ entity: grandparent }]); + const uid = await addEntity(root, [ { entity: parent1 }, { entity: parent2 }, ]); - await addEntity(knex, unrelated1, []); - await addEntity(knex, unrelated2, []); + await addEntity(unrelated1, []); + await addEntity(unrelated2, []); await knex('refresh_state').update({ result_hash: 'not-changed' }); await knex('relations').insert({ originating_entity_id: uid, @@ -1266,21 +1261,21 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'can filter and collect properly, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { name: 'one' }, spec: {}, }); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { name: 'two' }, spec: {}, }); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k2', metadata: { name: 'two' }, @@ -1303,9 +1298,9 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'can match on annotations and labels with dots in them, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { @@ -1315,7 +1310,7 @@ describe('DefaultEntitiesCatalog', () => { }, spec: {}, }); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { @@ -1350,9 +1345,9 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'can match on strings in arrays, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { @@ -1361,7 +1356,7 @@ describe('DefaultEntitiesCatalog', () => { }, spec: {}, }); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { From 99dafad573e66297dd4349c24df93c3ba4dbe8d0 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 2 Jan 2023 13:49:53 -0600 Subject: [PATCH 017/417] catalog-backend: add tests for clashing items during pagination Signed-off-by: Vincenzo Scamporlino --- .../service/DefaultEntitiesCatalog.test.ts | 107 +++++++++++++++++- 1 file changed, 103 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 9d03cf5c61..bedf856ff7 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1069,6 +1069,105 @@ describe('DefaultEntitiesCatalog', () => { }, ); + it.each(databases.eachSupportedId())( + 'should paginate results accordingly in case of clashing items, %p', + async databaseId => { + await createDatabase(databaseId); + + function entityFrom(name: string, namespace?: string) { + return { + apiVersion: 'a', + kind: 'k', + metadata: { name, ...(!!namespace && { namespace }) }, + spec: { should_include_this: 'yes' }, + }; + } + + await Promise.all([ + addEntityToSearch(entityFrom('AA')), + addEntityToSearch(entityFrom('AA', 'namespace2')), + addEntityToSearch(entityFrom('AA', 'namespace3')), + addEntityToSearch(entityFrom('AA', 'namespace4')), + addEntityToSearch(entityFrom('CC')), + addEntityToSearch(entityFrom('DD')), + ]); + + const catalog = new DefaultEntitiesCatalog(knex); + + const limit = 2; + + // initial request + const request1: PaginatedEntitiesInitialRequest = { + limit, + sortFields: [{ field: 'metadata.name' }], + }; + const response1 = await catalog.paginatedEntities(request1); + expect(response1.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response1.nextCursor).toBeDefined(); + expect(response1.prevCursor).toBeUndefined(); + expect(response1.totalItems).toBe(6); + + // second request (forward) + const request2: PaginatedEntitiesCursorRequest = { + cursor: response1.nextCursor!, + limit, + }; + const response2 = await catalog.paginatedEntities(request2); + expect(response2.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response2.nextCursor).toBeDefined(); + expect(response2.prevCursor).toBeDefined(); + expect(response2.totalItems).toBe(6); + + // third request (forward) + const request3: PaginatedEntitiesCursorRequest = { + cursor: response2.nextCursor!, + limit, + }; + const response3 = await catalog.paginatedEntities(request3); + expect(response3.entities).toEqual([ + entityFrom('CC'), + entityFrom('DD'), + ]); + expect(response3.nextCursor).toBeUndefined(); + expect(response3.prevCursor).toBeDefined(); + expect(response3.totalItems).toBe(6); + + // forth request (backward) + const request4: PaginatedEntitiesCursorRequest = { + cursor: response3.prevCursor!, + limit, + }; + const response4 = await catalog.paginatedEntities(request4); + expect(response4.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response4.nextCursor).toBeDefined(); + expect(response4.prevCursor).toBeDefined(); + expect(response4.totalItems).toBe(6); + + // fifth request (backward) + const request5: PaginatedEntitiesCursorRequest = { + cursor: response4.prevCursor!, + limit, + }; + const response5 = await catalog.paginatedEntities(request5); + expect(response5.entities).toMatchObject([ + entityFrom('AA'), + entityFrom('AA'), + ]); + expect(response5.nextCursor).toBeDefined(); + expect(response5.prevCursor).toBeUndefined(); + expect(response5.totalItems).toBe(6); + }, + ); + it.each(databases.eachSupportedId())( 'should paginate results without sort fields, %p', async databaseId => { @@ -1117,7 +1216,7 @@ describe('DefaultEntitiesCatalog', () => { const response2 = await catalog.paginatedEntities(request2); expect(response2.entities).toMatchObject([ entityFrom('DD'), - entityFrom('AA'), + entityFrom('AA', 'namespace2'), ]); expect(response2.nextCursor).toBeDefined(); expect(response2.prevCursor).toBeDefined(); @@ -1130,8 +1229,8 @@ describe('DefaultEntitiesCatalog', () => { }; const response3 = await catalog.paginatedEntities(request3); expect(response3.entities).toEqual([ - entityFrom('AA'), - entityFrom('AA'), + entityFrom('AA', 'namespace3'), + entityFrom('AA', 'namespace4'), ]); expect(response3.nextCursor).toBeUndefined(); expect(response3.prevCursor).toBeDefined(); @@ -1145,7 +1244,7 @@ describe('DefaultEntitiesCatalog', () => { const response4 = await catalog.paginatedEntities(request4); expect(response4.entities).toMatchObject([ entityFrom('DD'), - entityFrom('AA'), + entityFrom('AA', 'namespace2'), ]); expect(response4.nextCursor).toBeDefined(); expect(response4.prevCursor).toBeDefined(); From c14c909126a17bff5ccfc165dd4e33f7983e3981 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 2 Jan 2023 13:58:10 -0600 Subject: [PATCH 018/417] catalog-backend: improve namings on paginateEntities Signed-off-by: Vincenzo Scamporlino --- .../src/service/DefaultEntitiesCatalog.ts | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index ce330eb9c1..ba68fb9a0e 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -56,7 +56,7 @@ import { } from './util'; const defaultSortField: EntitySortField = { - field: 'metadata.name', + field: 'metadata.uid', order: 'asc', }; @@ -341,13 +341,15 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isFetchingBackwards = cursor.isPrevious; - // TODO(vinzscam): at the moment only a single sortField is supported + // TODO(vinzscam): log if multiple sort fields are provided + const sortField: EntitySortField = { ...defaultSortField, ...cursor.sortFields[0], }; - const [sortFieldId, metadataSortFieldId] = cursor.sortFieldValues || []; + const [sortFieldValue, metadataSortFieldValue] = + cursor.sortFieldValues || []; const dbQuery = db('search') .join('final_entities', 'search.entity_id', 'final_entities.entity_id') @@ -368,20 +370,20 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const countQuery = dbQuery.clone(); const isOrderingDescending = sortField.order === 'desc'; - if (sortFieldId) { - dbQuery - .andWhere( - 'value', + + if (sortFieldValue) { + dbQuery.andWhere( + 'value', + isFetchingBackwards !== isOrderingDescending ? '<' : '>', + sortFieldValue, + ); + dbQuery.orWhere(function nested() { + this.where('value', '=', sortFieldValue).andWhere( + 'search.entity_id', isFetchingBackwards !== isOrderingDescending ? '<' : '>', - sortFieldId, - ) - .orWhere(function nested() { - this.where('value', '=', sortFieldId).andWhere( - 'search.entity_id', - isFetchingBackwards !== isOrderingDescending ? '<' : '>', - metadataSortFieldId, - ); - }); + metadataSortFieldValue, + ); + }); } dbQuery @@ -430,19 +432,18 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isInitialRequest = cursor.firstSortFieldValues === undefined; + const firstRow = rows[0]; + const lastRow = rows[rows.length - 1]; + const firstSortFieldValues = cursor.firstSortFieldValues || [ - rows[0]?.value, - rows[0]?.entity_id, + firstRow?.value, + firstRow?.entity_id, ]; const nextCursor = hasMoreResults ? encodeCursor({ ...cursor, - sortFieldValues: [ - // TODO generalize - rows[rows.length - 1].value, - rows[rows.length - 1].entity_id, - ], + sortFieldValues: sortFieldsFromRow(lastRow), firstSortFieldValues, isPrevious: false, totalItems, @@ -452,11 +453,10 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const prevCursor = !isInitialRequest && rows.length > 0 && - !isEqual(sortFieldsFromRow(rows[0]), cursor.firstSortFieldValues) + !isEqual(sortFieldsFromRow(firstRow), cursor.firstSortFieldValues) ? encodeCursor({ ...cursor, - // TODO generalize - sortFieldValues: [rows[0].value, rows[0].entity_id], + sortFieldValues: sortFieldsFromRow(firstRow), firstSortFieldValues: cursor.firstSortFieldValues, isPrevious: true, totalItems, @@ -681,5 +681,5 @@ function invertOrder(order: EntitySortField['order']) { } function sortFieldsFromRow(row: DbSearchRow) { - return [row.value, row.entity_id]; + return [row.value!, row.entity_id]; } From 2977e34ed5bc88cf5ae42a1f0e8fca1129d4b854 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 2 Jan 2023 14:15:08 -0600 Subject: [PATCH 019/417] catalog-backend: log in case of multiple sortfields are passed Signed-off-by: Vincenzo Scamporlino --- .../src/service/CatalogBuilder.ts | 7 +- .../service/DefaultEntitiesCatalog.test.ts | 139 ++++++++++++++---- .../src/service/DefaultEntitiesCatalog.ts | 22 ++- 3 files changed, 127 insertions(+), 41 deletions(-) diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 48bf6a08ef..3dfdec09e5 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -453,10 +453,11 @@ export class CatalogBuilder { legacySingleProcessorValidation: this.legacySingleProcessorValidation, }); const stitcher = new Stitcher(dbClient, logger); - const unauthorizedEntitiesCatalog = new DefaultEntitiesCatalog( - dbClient, + const unauthorizedEntitiesCatalog = new DefaultEntitiesCatalog({ + database: dbClient, + logger, stitcher, - ); + }); let permissionEvaluator: PermissionEvaluator; if ('authorizeConditional' in permissions) { diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index bedf856ff7..48ac1c4b0c 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { getVoidLogger } from '@backstage/backend-common'; import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; @@ -152,7 +153,11 @@ describe('DefaultEntitiesCatalog', () => { await addEntity(parent, [{ entity: grandparent }]); await addEntity(root, [{ entity: parent }]); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const result = await catalog.entityAncestry('k:default/root'); expect(result.rootEntityRef).toEqual('k:default/root'); @@ -182,7 +187,11 @@ describe('DefaultEntitiesCatalog', () => { 'should throw error if the entity does not exist, %p', async databaseId => { await createDatabase(databaseId); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); await expect(() => catalog.entityAncestry('k:default/root'), ).rejects.toThrow('No such entity k:default/root'); @@ -225,7 +234,11 @@ describe('DefaultEntitiesCatalog', () => { await addEntity(parent2, [{ entity: grandparent }]); await addEntity(root, [{ entity: parent1 }, { entity: parent2 }]); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const result = await catalog.entityAncestry('k:default/root'); expect(result.rootEntityRef).toEqual('k:default/root'); @@ -281,7 +294,11 @@ describe('DefaultEntitiesCatalog', () => { }; await addEntityToSearch(entity1); await addEntityToSearch(entity2); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const testFilter = { key: 'spec.test', @@ -315,7 +332,11 @@ describe('DefaultEntitiesCatalog', () => { }; await addEntityToSearch(entity1); await addEntityToSearch(entity2); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const testFilter = { not: { @@ -363,7 +384,11 @@ describe('DefaultEntitiesCatalog', () => { await addEntityToSearch(entity2); await addEntityToSearch(entity3); await addEntityToSearch(entity4); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const testFilter1 = { key: 'metadata.org', @@ -419,7 +444,11 @@ describe('DefaultEntitiesCatalog', () => { }; await addEntityToSearch(entity1); await addEntityToSearch(entity2); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const testFilter1 = { key: 'metadata.org', @@ -462,7 +491,11 @@ describe('DefaultEntitiesCatalog', () => { }; await addEntityToSearch(entity1); await addEntityToSearch(entity2); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const testFilter = { key: 'kind', @@ -505,7 +538,11 @@ describe('DefaultEntitiesCatalog', () => { }, [], ); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const { entities } = await catalog.entities(); @@ -716,7 +753,11 @@ describe('DefaultEntitiesCatalog', () => { entities.concat(notFoundEntities).map(e => addEntityToSearch(e)), ); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const filter = { key: 'spec.should_include_this', @@ -866,7 +907,11 @@ describe('DefaultEntitiesCatalog', () => { entities.concat(notFoundEntities).map(e => addEntityToSearch(e)), ); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const filter = { key: 'spec.should_include_this', @@ -1017,7 +1062,11 @@ describe('DefaultEntitiesCatalog', () => { entities.concat(notFoundEntities).map(e => addEntityToSearch(e)), ); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const filter = { key: 'spec.should_include_this', @@ -1059,7 +1108,11 @@ describe('DefaultEntitiesCatalog', () => { ), ); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const request: PaginatedEntitiesInitialRequest = { limit: 0, @@ -1092,7 +1145,10 @@ describe('DefaultEntitiesCatalog', () => { addEntityToSearch(entityFrom('DD')), ]); - const catalog = new DefaultEntitiesCatalog(knex); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + }); const limit = 2; @@ -1191,7 +1247,10 @@ describe('DefaultEntitiesCatalog', () => { addEntityToSearch(entityFrom('DD'), 'id3'), ]); - const catalog = new DefaultEntitiesCatalog(knex); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + }); const limit = 2; @@ -1320,20 +1379,26 @@ describe('DefaultEntitiesCatalog', () => { await addEntity(unrelated1, []); await addEntity(unrelated2, []); await knex('refresh_state').update({ result_hash: 'not-changed' }); - await knex('relations').insert({ - originating_entity_id: uid, - type: 't', - source_entity_ref: 'k:default/root', - target_entity_ref: 'k:default/unrelated1', - }); - await knex('relations').insert({ - originating_entity_id: uid, - type: 't', - source_entity_ref: 'k:default/unrelated2', - target_entity_ref: 'k:default/root', - }); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + // TODO(vinzscam): check whether this is needed + // await knex('relations').insert({ + // originating_entity_id: uid, + // type: 't', + // source_entity_ref: 'k:default/root', + // target_entity_ref: 'k:default/unrelated1', + // }); + // await knex('relations').insert({ + // originating_entity_id: uid, + // type: 't', + // source_entity_ref: 'k:default/unrelated2', + // target_entity_ref: 'k:default/root', + // }); + + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); await catalog.removeEntityByUid(uid); await expect( @@ -1380,7 +1445,11 @@ describe('DefaultEntitiesCatalog', () => { metadata: { name: 'two' }, spec: {}, }); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); await expect(catalog.facets({ facets: ['kind'] })).resolves.toEqual({ facets: { @@ -1419,7 +1488,11 @@ describe('DefaultEntitiesCatalog', () => { }, spec: {}, }); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); await expect( catalog.facets({ @@ -1464,7 +1537,11 @@ describe('DefaultEntitiesCatalog', () => { }, spec: {}, }); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); await expect( catalog.facets({ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index ba68fb9a0e..25d232958b 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -21,7 +21,8 @@ import { } from '@backstage/catalog-model'; import { InputError, NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; -import { isEqual } from 'lodash'; +import { isEqual, chunk as lodashChunk } from 'lodash'; +import { Logger } from 'winston'; import { EntitiesBatchRequest, EntitiesBatchResponse, @@ -183,10 +184,15 @@ function parseFilter( } export class DefaultEntitiesCatalog implements EntitiesCatalog { - constructor( - private readonly database: Knex, - private readonly stitcher: Stitcher, - ) {} + private readonly database: Knex; + private readonly logger: Logger; + private readonly stitcher: Stitcher; + + constructor(options: { database: Knex; logger: Logger; stitcher: Stitcher }) { + this.database = options.database; + this.logger = options.logger; + this.stitcher = options.stitcher; + } async entities(request?: EntitiesRequest): Promise { const db = this.database; @@ -298,7 +304,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { ): Promise { const lookup = new Map(); - for (const chunk of lodash.chunk(request.entityRefs, 200)) { + for (const chunk of lodashChunk(request.entityRefs, 200)) { let query = this.database('final_entities') .innerJoin('refresh_state', { 'refresh_state.entity_id': 'final_entities.entity_id', @@ -341,7 +347,9 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isFetchingBackwards = cursor.isPrevious; - // TODO(vinzscam): log if multiple sort fields are provided + if (cursor.sortFields.length > 1) { + this.logger.warn(`Only one sort field is supported, ignoring the rest`); + } const sortField: EntitySortField = { ...defaultSortField, From 58c78d37480a1e5d8364921ff9c75ccc99e5e37b Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 24 Jan 2023 11:12:35 +0100 Subject: [PATCH 020/417] catalog: accept null as field value Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 4 ++-- plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 30472782a8..dc85e44e7a 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -295,7 +295,7 @@ export type Cursor = { /** * The values of the fields of a specific item used for paginating the data. */ - sortFieldValues: string[]; + sortFieldValues: Array; /** * A filter to be applied to the full list of entities. */ @@ -313,7 +313,7 @@ export type Cursor = { * The catalog uses this field internally to understand if the beginning * of the list has been reached when performing cursor based pagination. */ - firstSortFieldValues?: string[]; + firstSortFieldValues?: Array; /** * The number of items that match the provided filters */ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 25d232958b..bf5c7f8242 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -338,7 +338,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const limit = request?.limit ?? 20; const cursor: Omit & { - sortFieldValues?: string[]; + sortFieldValues?: (string | null)[]; } = { sortFields: [defaultSortField], isPrevious: false, @@ -689,5 +689,5 @@ function invertOrder(order: EntitySortField['order']) { } function sortFieldsFromRow(row: DbSearchRow) { - return [row.value!, row.entity_id]; + return [row.value, row.entity_id]; } From 7c47a38cc1680cc9dc755eaabcd3d0633151ea65 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 24 Jan 2023 11:25:57 +0100 Subject: [PATCH 021/417] catalog: improve sort fields namings Signed-off-by: Vincenzo Scamporlino --- .../src/service/DefaultEntitiesCatalog.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index bf5c7f8242..53e30e663e 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -356,8 +356,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { ...cursor.sortFields[0], }; - const [sortFieldValue, metadataSortFieldValue] = - cursor.sortFieldValues || []; + const [prevItemSortFieldValue, prevItemUid] = cursor.sortFieldValues || []; const dbQuery = db('search') .join('final_entities', 'search.entity_id', 'final_entities.entity_id') @@ -379,17 +378,17 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isOrderingDescending = sortField.order === 'desc'; - if (sortFieldValue) { + if (prevItemSortFieldValue) { dbQuery.andWhere( 'value', isFetchingBackwards !== isOrderingDescending ? '<' : '>', - sortFieldValue, + prevItemSortFieldValue, ); dbQuery.orWhere(function nested() { - this.where('value', '=', sortFieldValue).andWhere( + this.where('value', '=', prevItemSortFieldValue).andWhere( 'search.entity_id', isFetchingBackwards !== isOrderingDescending ? '<' : '>', - metadataSortFieldValue, + prevItemUid, ); }); } From 959a728e71e7c165e68d267678d82d60fa7caf1a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 27 Jan 2023 14:44:22 +0100 Subject: [PATCH 022/417] catalog-backend: dependencies fix Signed-off-by: Vincenzo Scamporlino --- .../catalog-backend/src/integration.test.ts | 6 ++- .../service/DefaultEntitiesCatalog.test.ts | 42 ++++++++++++------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/plugins/catalog-backend/src/integration.test.ts b/plugins/catalog-backend/src/integration.test.ts index 4ba046834b..05fedd13de 100644 --- a/plugins/catalog-backend/src/integration.test.ts +++ b/plugins/catalog-backend/src/integration.test.ts @@ -258,7 +258,11 @@ class TestHarness { legacySingleProcessorValidation: false, }); const stitcher = new Stitcher(db, logger); - const catalog = new DefaultEntitiesCatalog(db, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: db, + logger, + stitcher, + }); const proxyProgressTracker = new ProxyProgressTracker( new NoopProgressTracker(), ); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 48ac1c4b0c..1a24747bf3 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -571,7 +571,7 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'can order and combine with filtering, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); const entity1: Entity = { apiVersion: 'a', @@ -597,12 +597,16 @@ describe('DefaultEntitiesCatalog', () => { metadata: { name: 'n4' }, spec: { a: 'baz', b: 'only' }, }; - await addEntityToSearch(knex, entity1); - await addEntityToSearch(knex, entity2); - await addEntityToSearch(knex, entity3); - await addEntityToSearch(knex, entity4); + await addEntityToSearch(entity1); + await addEntityToSearch(entity2); + await addEntityToSearch(entity3); + await addEntityToSearch(entity4); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); function f(request: EntitiesRequest): Promise { return catalog @@ -665,10 +669,9 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'queries for entities by ref, including duplicates, and gracefully returns null for missing entities, %p', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); await addEntity( - knex, { apiVersion: 'a', kind: 'k', @@ -679,7 +682,6 @@ describe('DefaultEntitiesCatalog', () => { [], ); await addEntity( - knex, { apiVersion: 'a', kind: 'k', @@ -690,7 +692,11 @@ describe('DefaultEntitiesCatalog', () => { [], ); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); const { items } = await catalog.entitiesBatch({ entityRefs: [ @@ -1148,6 +1154,7 @@ describe('DefaultEntitiesCatalog', () => { const catalog = new DefaultEntitiesCatalog({ database: knex, logger: getVoidLogger(), + stitcher, }); const limit = 2; @@ -1250,6 +1257,7 @@ describe('DefaultEntitiesCatalog', () => { const catalog = new DefaultEntitiesCatalog({ database: knex, logger: getVoidLogger(), + stitcher, }); const limit = 2; @@ -1563,9 +1571,9 @@ describe('DefaultEntitiesCatalog', () => { it.each(databases.eachSupportedId())( 'can match relations', async databaseId => { - const { knex } = await createDatabase(databaseId); + await createDatabase(databaseId); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { @@ -1580,7 +1588,7 @@ describe('DefaultEntitiesCatalog', () => { }, ], }); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { @@ -1599,7 +1607,7 @@ describe('DefaultEntitiesCatalog', () => { }, ], }); - await addEntityToSearch(knex, { + await addEntityToSearch({ apiVersion: 'a', kind: 'k', metadata: { @@ -1615,7 +1623,11 @@ describe('DefaultEntitiesCatalog', () => { ], }); - const catalog = new DefaultEntitiesCatalog(knex, stitcher); + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); await expect( catalog.facets({ From 9c214ee62941220339eb93939571fd406b9d95ba Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 27 Jan 2023 22:38:28 +0100 Subject: [PATCH 023/417] catalog-backend: fix missing uid from search Signed-off-by: Vincenzo Scamporlino --- .../service/DefaultEntitiesCatalog.test.ts | 130 +++++++----------- .../src/service/DefaultEntitiesCatalog.ts | 2 +- 2 files changed, 54 insertions(+), 78 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 1a24747bf3..75d120e421 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -90,7 +90,8 @@ describe('DefaultEntitiesCatalog', () => { return id; } - async function addEntityToSearch(entity: Entity, id = uuid()) { + async function addEntityToSearch(entity: Entity) { + const id = entity.metadata.uid || v4(); const entityRef = stringifyEntityRef(entity); const entityJson = JSON.stringify(entity); @@ -728,17 +729,8 @@ describe('DefaultEntitiesCatalog', () => { async databaseId => { await createDatabase(databaseId); - function entityFrom(name: string) { - return { - apiVersion: 'a', - kind: 'k', - metadata: { name }, - spec: { should_include_this: 'yes' }, - }; - } - const names = ['B', 'F', 'A', 'G', 'D', 'C', 'E']; - const entities: Entity[] = names.map(entityFrom); + const entities: Entity[] = names.map(name => entityFrom(name)); const notFoundEntities: Entity[] = [ { @@ -882,17 +874,8 @@ describe('DefaultEntitiesCatalog', () => { async databaseId => { await createDatabase(databaseId); - function entityFrom(name: string) { - return { - apiVersion: 'a', - kind: 'k', - metadata: { name }, - spec: { should_include_this: 'yes' }, - }; - } - const names = ['B', 'F', 'A', 'G', 'D', 'C', 'E']; - const entities: Entity[] = names.map(entityFrom); + const entities: Entity[] = names.map(name => entityFrom(name)); const notFoundEntities: Entity[] = [ { @@ -1037,17 +1020,8 @@ describe('DefaultEntitiesCatalog', () => { async databaseId => { await createDatabase(databaseId); - function entityFrom(name: string) { - return { - apiVersion: 'a', - kind: 'k', - metadata: { name }, - spec: { should_include_this: 'yes' }, - }; - } - const names = ['lion', 'cat', 'atcatss', 'dog', 'dogcat', 'aa', 's']; - const entities: Entity[] = names.map(entityFrom); + const entities: Entity[] = names.map(name => entityFrom(name)); const notFoundEntities: Entity[] = [ { @@ -1133,20 +1107,11 @@ describe('DefaultEntitiesCatalog', () => { async databaseId => { await createDatabase(databaseId); - function entityFrom(name: string, namespace?: string) { - return { - apiVersion: 'a', - kind: 'k', - metadata: { name, ...(!!namespace && { namespace }) }, - spec: { should_include_this: 'yes' }, - }; - } - await Promise.all([ addEntityToSearch(entityFrom('AA')), - addEntityToSearch(entityFrom('AA', 'namespace2')), - addEntityToSearch(entityFrom('AA', 'namespace3')), - addEntityToSearch(entityFrom('AA', 'namespace4')), + addEntityToSearch(entityFrom('AA', { namespace: 'namespace2' })), + addEntityToSearch(entityFrom('AA', { namespace: 'namespace3' })), + addEntityToSearch(entityFrom('AA', { namespace: 'namespace4' })), addEntityToSearch(entityFrom('CC')), addEntityToSearch(entityFrom('DD')), ]); @@ -1236,22 +1201,19 @@ describe('DefaultEntitiesCatalog', () => { async databaseId => { await createDatabase(databaseId); - function entityFrom(name: string, namespace?: string) { - return { - apiVersion: 'a', - kind: 'k', - metadata: { name, ...(!!namespace && { namespace }) }, - spec: { should_include_this: 'yes' }, - }; - } - await Promise.all([ - addEntityToSearch(entityFrom('AA'), 'id1'), - addEntityToSearch(entityFrom('CC'), 'id2'), - addEntityToSearch(entityFrom('AA', 'namespace2'), 'id4'), - addEntityToSearch(entityFrom('AA', 'namespace3'), 'id5'), - addEntityToSearch(entityFrom('AA', 'namespace4'), 'id6'), - addEntityToSearch(entityFrom('DD'), 'id3'), + addEntityToSearch(entityFrom('AA', { uid: 'id1' })), + addEntityToSearch(entityFrom('CC', { uid: 'id2' })), + addEntityToSearch( + entityFrom('AA', { namespace: 'namespace2', uid: 'id4' }), + ), + addEntityToSearch( + entityFrom('AA', { namespace: 'namespace3', uid: 'id5' }), + ), + addEntityToSearch( + entityFrom('AA', { namespace: 'namespace4', uid: 'id6' }), + ), + addEntityToSearch(entityFrom('DD', { uid: 'id3' })), ]); const catalog = new DefaultEntitiesCatalog({ @@ -1283,7 +1245,7 @@ describe('DefaultEntitiesCatalog', () => { const response2 = await catalog.paginatedEntities(request2); expect(response2.entities).toMatchObject([ entityFrom('DD'), - entityFrom('AA', 'namespace2'), + entityFrom('AA', { namespace: 'namespace2' }), ]); expect(response2.nextCursor).toBeDefined(); expect(response2.prevCursor).toBeDefined(); @@ -1295,9 +1257,9 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response3 = await catalog.paginatedEntities(request3); - expect(response3.entities).toEqual([ - entityFrom('AA', 'namespace3'), - entityFrom('AA', 'namespace4'), + expect(response3.entities).toMatchObject([ + entityFrom('AA', { namespace: 'namespace3' }), + entityFrom('AA', { namespace: 'namespace4' }), ]); expect(response3.nextCursor).toBeUndefined(); expect(response3.prevCursor).toBeDefined(); @@ -1311,7 +1273,7 @@ describe('DefaultEntitiesCatalog', () => { const response4 = await catalog.paginatedEntities(request4); expect(response4.entities).toMatchObject([ entityFrom('DD'), - entityFrom('AA', 'namespace2'), + entityFrom('AA', { namespace: 'namespace2' }), ]); expect(response4.nextCursor).toBeDefined(); expect(response4.prevCursor).toBeDefined(); @@ -1387,20 +1349,18 @@ describe('DefaultEntitiesCatalog', () => { await addEntity(unrelated1, []); await addEntity(unrelated2, []); await knex('refresh_state').update({ result_hash: 'not-changed' }); - - // TODO(vinzscam): check whether this is needed - // await knex('relations').insert({ - // originating_entity_id: uid, - // type: 't', - // source_entity_ref: 'k:default/root', - // target_entity_ref: 'k:default/unrelated1', - // }); - // await knex('relations').insert({ - // originating_entity_id: uid, - // type: 't', - // source_entity_ref: 'k:default/unrelated2', - // target_entity_ref: 'k:default/root', - // }); + await knex('relations').insert({ + originating_entity_id: uid, + type: 't', + source_entity_ref: 'k:default/root', + target_entity_ref: 'k:default/unrelated1', + }); + await knex('relations').insert({ + originating_entity_id: uid, + type: 't', + source_entity_ref: 'k:default/unrelated2', + target_entity_ref: 'k:default/root', + }); const catalog = new DefaultEntitiesCatalog({ database: knex, @@ -1645,3 +1605,19 @@ describe('DefaultEntitiesCatalog', () => { ); }); }); + +function entityFrom( + name: string, + { uid, namespace }: { uid?: string; namespace?: string } = {}, +) { + return { + apiVersion: 'a', + kind: 'k', + metadata: { + name, + ...(!!namespace && { namespace }), + ...(!!uid && { uid }), + }, + spec: { should_include_this: 'yes' }, + }; +} diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 53e30e663e..37245876aa 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -113,7 +113,7 @@ function addCondition( // make a lot of sense. However, it had abysmal performance on sqlite // when datasets grew large, so we're using IN instead. const matchQuery = db('search') - .select(entityIdField) + .select('search.entity_id') .where({ key: filter.key.toLowerCase() }) .andWhere(function keyFilter() { if (filter.values) { From d3b3065a76b0749e65212f8028041fe6db143601 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 27 Jan 2023 23:31:26 +0100 Subject: [PATCH 024/417] catalog-backend: reuse EntityOrderQuery Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 10 ++-------- .../src/service/DefaultEntitiesCatalog.test.ts | 6 +++--- .../src/service/DefaultEntitiesCatalog.ts | 8 ++++---- .../src/service/request/parseEntitySortFieldParams.ts | 4 ++-- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index dc85e44e7a..c5da9726c2 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -46,12 +46,6 @@ export type EntityOrder = { order: 'asc' | 'desc'; }; -// TODO(vinzscam): remove this type in favor of EntityOrder -export type EntitySortField = { - field: string; - order?: 'asc' | 'desc' | undefined; -}; - /** * Matches rows in the search table. * @public @@ -240,7 +234,7 @@ export interface PaginatedEntitiesInitialRequest { fields?: (entity: Entity) => Entity; limit?: number; filter?: EntityFilter; - sortFields?: EntitySortField[]; + sortFields?: EntityOrder[]; query?: string; } @@ -291,7 +285,7 @@ export type Cursor = { * An array of fields used for sorting the data. * For example, [ { field: 'metadata.name', order: 'asc' } ] */ - sortFields: EntitySortField[]; + sortFields: EntityOrder[]; /** * The values of the fields of a specific item used for paginating the data. */ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 75d120e421..c2f1843845 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -767,7 +767,7 @@ describe('DefaultEntitiesCatalog', () => { const request1: PaginatedEntitiesInitialRequest = { filter, limit, - sortFields: [{ field: 'metadata.name' }], + sortFields: [{ field: 'metadata.name', order: 'asc' }], }; const response1 = await catalog.paginatedEntities(request1); expect(response1.entities).toEqual([entityFrom('A'), entityFrom('B')]); @@ -1056,7 +1056,7 @@ describe('DefaultEntitiesCatalog', () => { filter, limit: 100, - sortFields: [{ field: 'metadata.name' }], + sortFields: [{ field: 'metadata.name', order: 'asc' }], query: 'cAt ', }; const response = await catalog.paginatedEntities(request); @@ -1127,7 +1127,7 @@ describe('DefaultEntitiesCatalog', () => { // initial request const request1: PaginatedEntitiesInitialRequest = { limit, - sortFields: [{ field: 'metadata.name' }], + sortFields: [{ field: 'metadata.name', order: 'asc' }], }; const response1 = await catalog.paginatedEntities(request1); expect(response1.entities).toMatchObject([ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 37245876aa..43e0de026d 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -36,9 +36,9 @@ import { EntityFacetsResponse, EntityFilter, EntityPagination, - EntitySortField, PaginatedEntitiesRequest, PaginatedEntitiesResponse, + EntityOrder, } from '../catalog/types'; import { DbFinalEntitiesRow, @@ -56,7 +56,7 @@ import { isPaginatedEntitiesInitialRequest, } from './util'; -const defaultSortField: EntitySortField = { +const defaultSortField: EntityOrder = { field: 'metadata.uid', order: 'asc', }; @@ -351,7 +351,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { this.logger.warn(`Only one sort field is supported, ignoring the rest`); } - const sortField: EntitySortField = { + const sortField: EntityOrder = { ...defaultSortField, ...cursor.sortFields[0], }; @@ -683,7 +683,7 @@ function parseCursorFromRequest( return {}; } -function invertOrder(order: EntitySortField['order']) { +function invertOrder(order: EntityOrder['order']) { return order === 'asc' ? 'desc' : 'asc'; } diff --git a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts b/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts index d16295aa30..5efa2de05e 100644 --- a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts +++ b/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts @@ -15,12 +15,12 @@ */ import { InputError } from '@backstage/errors'; -import { EntitySortField } from '../../catalog/types'; +import { EntityOrder } from '../../catalog/types'; import { parseStringsParam } from './common'; export function parseEntitySortFieldParams( params: Record, -): EntitySortField[] | undefined { +): EntityOrder[] | undefined { const sortFieldStrings = parseStringsParam(params.sortField, 'sortField'); if (!sortFieldStrings) { return undefined; From d1ed81af930cf59cdde2df86bc8d24eb28cc9aec Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 27 Jan 2023 23:34:57 +0100 Subject: [PATCH 025/417] catalog-client: reuse EntityOrderQuery Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 8 +------- packages/catalog-client/src/CatalogClient.ts | 4 ++-- packages/catalog-client/src/types/api.ts | 9 +-------- packages/catalog-client/src/types/index.ts | 1 - 4 files changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index 22afa0457e..b9c9543801 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -188,12 +188,6 @@ export type EntityOrderQuery = order: 'asc' | 'desc'; }>; -// @public -export type EntitySortField = { - field: string; - order: 'asc' | 'desc'; -}; - // @public export interface GetEntitiesByRefsRequest { entityRefs: string[]; @@ -268,7 +262,7 @@ export type GetPaginatedEntitiesInitialRequest = fields?: string[]; limit?: number; filter?: EntitiesFilter; - sortFields?: EntitySortField[]; + sortFields?: EntityOrderQuery; query?: string; } | undefined; diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 18b614fd2e..a76a66577c 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -224,8 +224,8 @@ export class CatalogClient implements CatalogApi { params.push(`limit=${limit}`); } if (sortFields !== undefined) { - sortFields.forEach(({ field, order }) => - params.push(`sortField=${field},${order}`), + (Array.isArray(sortFields) ? sortFields : [sortFields]).forEach( + ({ field, order }) => params.push(`sortField=${field},${order}`), ); } if (fields.length) { diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 26c16af64d..103c990783 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -366,13 +366,6 @@ export type EntitiesFilter = | Record | undefined; -/** - * Used for sorting the entities. - * - * @public - */ -export type EntitySortField = { field: string; order: 'asc' | 'desc' }; - /** * The response type for {@link CatalogClient.addLocation}. * @@ -418,7 +411,7 @@ export type GetPaginatedEntitiesInitialRequest = fields?: string[]; limit?: number; filter?: EntitiesFilter; - sortFields?: EntitySortField[]; + sortFields?: EntityOrderQuery; query?: string; } | undefined; diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts index 61a993eb19..e85b86f4af 100644 --- a/packages/catalog-client/src/types/index.ts +++ b/packages/catalog-client/src/types/index.ts @@ -26,7 +26,6 @@ export type { GetEntitiesByRefsRequest, GetEntitiesByRefsResponse, EntitiesFilter, - EntitySortField, GetEntitiesRequest, GetEntitiesResponse, GetEntityAncestorsRequest, From c2bd94e82a3b1c68a2c58681ec015b2a95526fa5 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 27 Jan 2023 23:46:31 +0100 Subject: [PATCH 026/417] catalog-client: reuse EntityFilterQuery Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 10 ++-------- packages/catalog-client/src/CatalogClient.ts | 4 ++-- packages/catalog-client/src/types/api.ts | 14 ++------------ packages/catalog-client/src/types/index.ts | 1 - 4 files changed, 6 insertions(+), 23 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index b9c9543801..416f1bc4fd 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -159,12 +159,6 @@ export interface CatalogRequestOptions { token?: string; } -// @public -export type EntitiesFilter = - | Record[] - | Record - | undefined; - // @public export const ENTITY_STATUS_CATALOG_PROCESSING_TYPE = 'backstage.io/catalog-processing'; @@ -235,7 +229,7 @@ export interface GetEntityAncestorsResponse { // @public export interface GetEntityFacetsRequest { facets: string[]; - filter?: EntitiesFilter; + filter?: EntityFilterQuery; } // @public @@ -261,7 +255,7 @@ export type GetPaginatedEntitiesInitialRequest = | { fields?: string[]; limit?: number; - filter?: EntitiesFilter; + filter?: EntityFilterQuery; sortFields?: EntityOrderQuery; query?: string; } diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index a76a66577c..ba410beb92 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -41,7 +41,7 @@ import { GetEntitiesByRefsResponse, GetPaginatedEntitiesRequest, GetPaginatedEntitiesResponse, - EntitiesFilter, + EntityFilterQuery, GetPaginatedEntitiesCursorRequest, } from './types/api'; import { DiscoveryApi } from './types/discovery'; @@ -522,7 +522,7 @@ export class CatalogClient implements CatalogApi { return await response.json(); } - private getParams(filter: EntitiesFilter = []) { + private getParams(filter: EntityFilterQuery = []) { const params: string[] = []; // filter param can occur multiple times, for example // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 103c990783..d6aeba5d1d 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -287,7 +287,7 @@ export interface GetEntityFacetsRequest { * (exported from this package), which means that you assert on the existence * of that key, no matter what its value is. */ - filter?: EntitiesFilter; + filter?: EntityFilterQuery; /** * Dot separated paths for the facets to extract from each entity. * @@ -356,16 +356,6 @@ export type AddLocationRequest = { dryRun?: boolean; }; -/** - * Used for filtering entities that match the given patterns. - * - * @public - */ -export type EntitiesFilter = - | Record[] - | Record - | undefined; - /** * The response type for {@link CatalogClient.addLocation}. * @@ -410,7 +400,7 @@ export type GetPaginatedEntitiesInitialRequest = | { fields?: string[]; limit?: number; - filter?: EntitiesFilter; + filter?: EntityFilterQuery; sortFields?: EntityOrderQuery; query?: string; } diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts index e85b86f4af..715639e1c3 100644 --- a/packages/catalog-client/src/types/index.ts +++ b/packages/catalog-client/src/types/index.ts @@ -25,7 +25,6 @@ export type { EntityOrderQuery, GetEntitiesByRefsRequest, GetEntitiesByRefsResponse, - EntitiesFilter, GetEntitiesRequest, GetEntitiesResponse, GetEntityAncestorsRequest, From 2f2baf4b6513d671425296994c99bc5a9d790171 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Sat, 28 Jan 2023 00:04:46 +0100 Subject: [PATCH 027/417] catalog-client: remove undefined from GetPaginatedEntitiesInitialRequest Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 16 +++++++--------- packages/catalog-client/src/CatalogClient.ts | 4 ++-- packages/catalog-client/src/types/api.ts | 16 +++++++--------- packages/catalog-client/src/utils.ts | 3 --- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index 416f1bc4fd..47c6ff7f36 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -251,15 +251,13 @@ export type GetPaginatedEntitiesCursorRequest = { }; // @alpha -export type GetPaginatedEntitiesInitialRequest = - | { - fields?: string[]; - limit?: number; - filter?: EntityFilterQuery; - sortFields?: EntityOrderQuery; - query?: string; - } - | undefined; +export type GetPaginatedEntitiesInitialRequest = { + fields?: string[]; + limit?: number; + filter?: EntityFilterQuery; + sortFields?: EntityOrderQuery; + query?: string; +}; // @alpha export type GetPaginatedEntitiesRequest = diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index ba410beb92..7347535ca6 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -211,13 +211,13 @@ export class CatalogClient implements CatalogApi { * @alpha */ async getPaginatedEntities?( - request?: GetPaginatedEntitiesRequest, + request: GetPaginatedEntitiesRequest = {}, options?: CatalogRequestOptions, ): Promise { const params: string[] = []; if (isPaginatedEntitiesInitialRequest(request)) { - const { fields = [], filter, limit, sortFields, query } = request ?? {}; + const { fields = [], filter, limit, sortFields, query } = request; params.push(...this.getParams(filter)); if (limit !== undefined) { diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index d6aeba5d1d..4e7f679072 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -396,15 +396,13 @@ export type GetPaginatedEntitiesRequest = * * @alpha */ -export type GetPaginatedEntitiesInitialRequest = - | { - fields?: string[]; - limit?: number; - filter?: EntityFilterQuery; - sortFields?: EntityOrderQuery; - query?: string; - } - | undefined; +export type GetPaginatedEntitiesInitialRequest = { + fields?: string[]; + limit?: number; + filter?: EntityFilterQuery; + sortFields?: EntityOrderQuery; + query?: string; +}; /** * A request type for {@link CatalogClient.getPaginatedEntities}. diff --git a/packages/catalog-client/src/utils.ts b/packages/catalog-client/src/utils.ts index 5a26053fb9..8a2eb9c06d 100644 --- a/packages/catalog-client/src/utils.ts +++ b/packages/catalog-client/src/utils.ts @@ -23,9 +23,6 @@ import { export function isPaginatedEntitiesInitialRequest( request: GetPaginatedEntitiesInitialRequest, ): request is GetPaginatedEntitiesInitialRequest { - if (!request) { - return true; - } return !(request as GetPaginatedEntitiesCursorRequest).cursor; } From 9b71a220dcf4b24a680f71abff493acd08442b3a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Sat, 28 Jan 2023 00:33:24 +0100 Subject: [PATCH 028/417] catalog-backend: cleanup test Signed-off-by: Vincenzo Scamporlino --- .../service/DefaultEntitiesCatalog.test.ts | 76 ------------------- 1 file changed, 76 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index c2f1843845..bde55ef9bb 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1527,82 +1527,6 @@ describe('DefaultEntitiesCatalog', () => { }, 60_000, ); - - it.each(databases.eachSupportedId())( - 'can match relations', - async databaseId => { - await createDatabase(databaseId); - - await addEntityToSearch({ - apiVersion: 'a', - kind: 'k', - metadata: { - name: 'one', - tags: ['java', 'rust'], - }, - spec: {}, - relations: [ - { - targetRef: 'targetRef', - type: 'ownedBy', - }, - ], - }); - await addEntityToSearch({ - apiVersion: 'a', - kind: 'k', - metadata: { - name: 'two', - tags: ['java', 'node'], - }, - spec: {}, - relations: [ - { - targetRef: 'anotherTargetRef', - type: 'ownedBy', - }, - { - targetRef: 'tt', - type: 'somethingelse', - }, - ], - }); - await addEntityToSearch({ - apiVersion: 'a', - kind: 'k', - metadata: { - name: 'three', - tags: ['go'], - }, - spec: {}, - relations: [ - { - targetRef: 'targetRef', - type: 'ownedBy', - }, - ], - }); - - const catalog = new DefaultEntitiesCatalog({ - database: knex, - logger: getVoidLogger(), - stitcher, - }); - - await expect( - catalog.facets({ - facets: ['relations.ownedBy'], - }), - ).resolves.toEqual({ - facets: { - 'relations.ownedBy': [ - { count: 1, value: 'anotherTargetRef' }, - { count: 2, value: 'targetRef' }, - ], - }, - }); - }, - ); }); }); From 690905b78b723c8ad884855d1c26dfe05e210966 Mon Sep 17 00:00:00 2001 From: bogdannechyporenko Date: Tue, 31 Jan 2023 12:50:46 +0100 Subject: [PATCH 029/417] Described how to configure jest tests in IntelliJ Signed-off-by: bogdannechyporenko --- docs/local-dev/cli-build-system.md | 13 +++++++++++++ docs/plugins/testing.md | 12 +----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index cc364d0ca5..ba65bedb9f 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -595,6 +595,19 @@ If you also want to enable source maps when debugging tests, you can do so by se } ``` +### Debugging Jest Tests + +To configure the debugging of your tests in IntelliJ, you have to: + +1. Update Jest configuration template by: + +- Click on "Edit Configurations" on top panel +- In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. +- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest +- In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` + +2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. + ## Publishing Package publishing is an optional part of the Backstage build system and not diff --git a/docs/plugins/testing.md b/docs/plugins/testing.md index baee47c695..2fa086c444 100644 --- a/docs/plugins/testing.md +++ b/docs/plugins/testing.md @@ -371,14 +371,4 @@ Note: wrapping in the test application **requires** you to do a `find()` or # Debugging Jest Tests -Currently, debugging Jest tests using IntelliJ or `node-debugger` is possible -but can be -[problematic to set up.](https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000634564-Debugging-Jest-unit-tests) - -It is possible, but you might spend a decent amount of time configuring your -IDE. - -In most cases, we have found that using `console.log` works well. - -Note: if your console.logs are not being displayed, focus your specific unit -test from the command line by running them like so `yarn test MyTest`. +You can find it [here](https://backstage.io/docs/local-dev/cli-build-system#debugging-jest-tests) From 9615da8726bd6461a35d5f745f603a7dee72029e Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 31 Jan 2023 23:07:21 +0100 Subject: [PATCH 030/417] catalog-backend: fix mysql query issue Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 43e0de026d..0cc791e5de 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -368,8 +368,8 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const normalizedQueryByName = cursor.query?.trim(); if (normalizedQueryByName) { - dbQuery.andWhereLike( - 'value', + dbQuery.andWhereRaw( + 'value like ?', `%${normalizedQueryByName.toLocaleLowerCase('en-US')}%`, ); } From 362145175e8dfaaf87b47cafacc68f90dce2cb72 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 09:56:33 +0100 Subject: [PATCH 031/417] catalog-backend: remove alpha methods Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index c5da9726c2..451f757e65 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -177,7 +177,6 @@ export interface EntitiesCatalog { /** * Fetch entities and scroll back and forth between entities. * - * @alpha * @param request */ paginatedEntities( @@ -215,8 +214,6 @@ export interface EntitiesCatalog { /** * The request shape for {@link EntitiesCatalog.paginatedEntities}. - * - * @alpha */ export type PaginatedEntitiesRequest = | PaginatedEntitiesInitialRequest @@ -226,8 +223,6 @@ export type PaginatedEntitiesRequest = * The initial request for {@link EntitiesCatalog.paginatedEntities}. * The request take immutable properties that are going to be bound * for the current and the next pagination requests. - * - * @alpha */ export interface PaginatedEntitiesInitialRequest { authorizationToken?: string; @@ -241,8 +236,6 @@ export interface PaginatedEntitiesInitialRequest { /** * Request for {@link EntitiesCatalog.paginatedEntities} used to * move forward or backward on the data. - * - * @alpha */ export interface PaginatedEntitiesCursorRequest { authorizationToken?: string; @@ -253,8 +246,6 @@ export interface PaginatedEntitiesCursorRequest { /** * The response shape for {@link EntitiesCatalog.paginatedEntities}. - * - * @alpha */ export interface PaginatedEntitiesResponse { /** @@ -277,8 +268,6 @@ export interface PaginatedEntitiesResponse { /** * The Cursor used internally by the catalog. - * - * @alpha */ export type Cursor = { /** From f79df8ab24cfcd96ada154bac1a29642aae9109e Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Wed, 25 Jan 2023 09:39:46 +0000 Subject: [PATCH 032/417] Initial easyauth work Signed-off-by: Alex Crome --- docs/auth/microsoft/azure-easyauth.md | 120 +++++++ mkdocs.yml | 1 + .../src/providers/azure-easyauth/index.ts | 18 ++ .../providers/azure-easyauth/provider.test.ts | 292 ++++++++++++++++++ .../src/providers/azure-easyauth/provider.ts | 202 ++++++++++++ 5 files changed, 633 insertions(+) create mode 100644 docs/auth/microsoft/azure-easyauth.md create mode 100644 plugins/auth-backend/src/providers/azure-easyauth/index.ts create mode 100644 plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts create mode 100644 plugins/auth-backend/src/providers/azure-easyauth/provider.ts diff --git a/docs/auth/microsoft/azure-easyauth.md b/docs/auth/microsoft/azure-easyauth.md new file mode 100644 index 0000000000..00d798dce9 --- /dev/null +++ b/docs/auth/microsoft/azure-easyauth.md @@ -0,0 +1,120 @@ +--- +id: azure-easy-auth +title: Azure EasyAuth Provider +sidebar_label: Azure EasyAuth +description: Adding Azure's EasyAuth Proxy as an authentication provider in Backstage +--- + +## Backstage Changes + +Add the following into your `app-config.yaml` or `app-config.production.yaml` file + +Add a `providerFactories` entry to the router in +`packages/backend/src/plugins/auth.ts`. + +```ts +import { providers } from '@backstage/plugin-auth-backend'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const authProviderFactories = { + 'azure-easyAuth': providers.easyAuth.create({ + signIn: { + resolver: async (info, ctx) => { + const { + fullProfile: { id }, + } = info.result; + + if (!id) { + throw new Error('User profile contained no id'); + } + + return await ctx.signInWithCatalogUser({ + annotations: { + 'graph.microsoft.com/user-id': id, + }, + }); + }, + }, + }), + }; + + return await createRouter({ + logger: env.logger, + config: env.config, + database: env.database, + discovery: env.discovery, + tokenManager: env.tokenManager, + providerFactories: authProviderFactories, + }); +} +``` + +Now the backend is ready to serve auth requests on the +`/api/auth/azure-easyAuth/refresh` endpoint. All that's left is to update the frontend +sign-in mechanism to poll that endpoint through the IAP, on the user's behalf. + +## Frontend Changes + +It is recommended to use the `ProxiedSignInPage` for this provider, which is +installed in `packages/app/src/App.tsx` like this: + +```diff ++import { ProxiedSignInPage } from '@backstage/core-components'; + + const app = createApp({ + components: { ++ SignInPage: props => , +``` + +See the [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) section for more information. + +## Azure Configuration + +How to configure azure depends on the service you're enable AAD auth on the app service. + +### Azure App Services + +To use EasyAuth with App Services, turn on Active Directory authentication +You must also enable the token store. + +The following example shows how to do this via a bicep template: + +```bicep +resource webApp 'Microsoft.Web/sites@2022-03-01' existing = { + name: 'MY-WEBAPP-NAME' + + resource authConfig 'config' = { + name: 'authsettingsV2' + properties: { + globalValidation: { + redirectToProvider: 'AzureActiveDirectory' + requireAuthentication: true + unauthenticatedClientAction: 'RedirectToLoginPage' + } + login: { + tokenStore: { + enabled: true + } + } + platform: { + enabled: true + } + identityProviders: { + azureActiveDirectory: { + enabled: true + login: { + loginParameters: [ 'domain_hint=MYCOMPANY.COM' ] + } + registration: { + clientId: 'CLIENT-ID' + clientSecretSettingName: 'CLIENT-SECRET-NAME' + openIdIssuer: 'https://sts.windows.net/${tenant().tenantId}/v2.0' + } + } + } + } + } +} +``` diff --git a/mkdocs.yml b/mkdocs.yml index 38369f4748..4b5c2cf7a2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -154,6 +154,7 @@ nav: - Included providers: - Auth0: 'auth/auth0/provider.md' - Azure: 'auth/microsoft/provider.md' + - Azure EasyAuth: 'auth/microsoft/azure-easyauth.md' - GitHub: 'auth/github/provider.md' - GitLab: 'auth/gitlab/provider.md' - Google: 'auth/google/provider.md' diff --git a/plugins/auth-backend/src/providers/azure-easyauth/index.ts b/plugins/auth-backend/src/providers/azure-easyauth/index.ts new file mode 100644 index 0000000000..698092d73f --- /dev/null +++ b/plugins/auth-backend/src/providers/azure-easyauth/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 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 { easyAuth } from './provider'; +export type { EasyAuthResponse } from './provider'; diff --git a/plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts b/plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts new file mode 100644 index 0000000000..f9f0796f7a --- /dev/null +++ b/plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts @@ -0,0 +1,292 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AuthHandler, AuthResolverContext } from '../types'; +import { makeProfileInfo } from '../../lib/passport'; +import { + easyAuth, + ACCESS_TOKEN_HEADER, + EasyAuthAuthProvider, + EasyAuthResult, + ID_TOKEN_HEADER, +} from './provider'; +import { Request, Response } from 'express'; +import { SignJWT, JWTPayload, errors as JoseErrors } from 'jose'; +import { randomBytes } from 'crypto'; + +const jwtSecret = randomBytes(48); + +async function buildJwt(claims: JWTPayload) { + return await new SignJWT(claims) + .setProtectedHeader({ alg: 'HS256' }) + .sign(jwtSecret); +} + +const backstageIdentityTokenClaims = { + sub: 'user:default/alice', + ent: ['user:default/alice'], +}; + +describe('EasyAuthAuthProvider', () => { + const authHandler: AuthHandler = async ({ fullProfile }) => ({ + profile: makeProfileInfo(fullProfile), + }); + const resolverContext: AuthResolverContext = {} as AuthResolverContext; + async function signInResolver() { + return { + id: 'user.name', + token: await buildJwt(backstageIdentityTokenClaims), + }; + } + + const provider = new EasyAuthAuthProvider({ + authHandler, + signInResolver, + resolverContext, + }); + + function mockRequest(headers?: Record) { + return { + header: (name: string) => headers?.[name], + } as unknown as Request; + } + + describe('should succeed when', () => { + it('id_token is valid and identity is resolved successfully', async () => { + const claims = { + ver: '2.0', + oid: 'c43063d4-0650-4f3e-ba6b-307473d24dfd', + name: 'Alice Bob', + email: 'alice@bob.com', + preferred_username: 'Another name', + }; + const response = { + end: jest.fn(), + header: () => jest.fn(), + json: jest.fn(), + status: jest.fn(), + } as unknown as Response; + + const request = mockRequest({ + [ID_TOKEN_HEADER]: await buildJwt(claims), + }); + await provider.refresh(request, response); + + expect(response.json).toHaveBeenCalledWith({ + backstageIdentity: { + id: 'user.name', + token: await buildJwt(backstageIdentityTokenClaims), + identity: { + ownershipEntityRefs: ['user:default/alice'], + type: 'user', + userEntityRef: 'user:default/alice', + }, + }, + profile: { + displayName: claims.name, + email: claims.email, + picture: undefined, + }, + providerInfo: { + accessToken: undefined, + }, + }); + }); + + it('valid id_token and access_token provided', async () => { + const claims = { + ver: '2.0', + oid: 'c43063d4-0650-4f3e-ba6b-307473d24dfd', + name: 'Alice Bob', + email: 'alice@bob.com', + preferred_username: 'Another name', + }; + const response = { + end: jest.fn(), + header: () => jest.fn(), + json: jest.fn(), + status: jest.fn(), + } as unknown as Response; + + const request = mockRequest({ + [ID_TOKEN_HEADER]: await buildJwt(claims), + [ACCESS_TOKEN_HEADER]: 'ACCESS_TOKEN', + }); + await provider.refresh(request, response); + + expect(response.json).toHaveBeenCalledWith( + expect.objectContaining({ + providerInfo: { + accessToken: 'ACCESS_TOKEN', + }, + }), + ); + }); + }); + + describe('should fail when', () => { + const response = {} as Response; + + it('Access token is missing', async () => { + const request = mockRequest(); + + await expect(provider.refresh(request, response)).rejects.toThrow( + 'Missing x-ms-token-aad-id-token header', + ); + }); + + it('id token is invalid', async () => { + const request = mockRequest({ + [ID_TOKEN_HEADER]: 'not-a-jwt', + }); + + await expect(provider.refresh(request, response)).rejects.toThrow( + JoseErrors.JWTInvalid, + ); + }); + + it('id token is v1', async () => { + const request = mockRequest({ + [ID_TOKEN_HEADER]: await buildJwt({ ver: '1.0' }), + }); + + await expect(provider.refresh(request, response)).rejects.toThrow( + 'id_token is not version 2.0', + ); + }); + + it('SignInResolver rejects', async () => { + const request = mockRequest({ + [ID_TOKEN_HEADER]: await buildJwt({ ver: '2.0' }), + }); + + const rejectProvider = new EasyAuthAuthProvider({ + authHandler, + signInResolver: async () => { + throw new Error('REJECTED!!'); + }, + resolverContext, + }); + + await expect(rejectProvider.refresh(request, response)).rejects.toThrow( + 'REJECTED!!', + ); + }); + + it('AuthHanlder rejects', async () => { + const request = mockRequest({ + [ID_TOKEN_HEADER]: await buildJwt({ ver: '2.0' }), + }); + + const rejectProvider = new EasyAuthAuthProvider({ + authHandler: async () => { + throw new Error('OBJECTION!!'); + }, + signInResolver, + resolverContext, + }); + + await expect(rejectProvider.refresh(request, response)).rejects.toThrow( + 'OBJECTION!!', + ); + }); + }); +}); + +describe('easyAuth factory', () => { + const env = process.env; + beforeEach(() => { + jest.resetModules(); + process.env = { ...env }; + }); + + afterEach(() => { + process.env = env; + }); + + it('should fail when run outside of Azure App Services', async () => { + const factory = easyAuth.create({ + signIn: { + resolver: jest.fn(), + }, + }); + + expect(() => factory({} as any)).toThrow( + 'Backstage is not running on Azure App Services', + ); + }); + + it('should fail when Azure App Services Auth is not enabled', async () => { + process.env.WEBSITE_SKU = 'Standard'; + process.env.WEBSITE_AUTH_ENABLED = 'False'; + + const factory = easyAuth.create({ + signIn: { + resolver: jest.fn(), + }, + }); + + expect(() => factory({} as any)).toThrow( + 'Azure App Services does not have authentication enabled', + ); + }); + + it('should fail when Azure App Services Auth is not AAD', async () => { + process.env.WEBSITE_SKU = 'Standard'; + process.env.WEBSITE_AUTH_ENABLED = 'True'; + process.env.WEBSITE_AUTH_DEFAULT_PROVIDER = 'Facebook'; + + const factory = easyAuth.create({ + signIn: { + resolver: jest.fn(), + }, + }); + + expect(() => factory({} as any)).toThrow( + 'Authentication provider is not Azure Active Directory', + ); + }); + + it('should fail when Token Store not enabled', async () => { + process.env.WEBSITE_SKU = 'Standard'; + process.env.WEBSITE_AUTH_ENABLED = 'True'; + process.env.WEBSITE_AUTH_DEFAULT_PROVIDER = 'AzureActiveDirectory'; + process.env.WEBSITE_AUTH_TOKEN_STORE = 'False'; + + const factory = easyAuth.create({ + signIn: { + resolver: jest.fn(), + }, + }); + + expect(() => factory({} as any)).toThrow('Token Store is not enabled'); + }); + + it('should return EasyAuthAuthProvider when running in Azure App Services with AAD Auth', async () => { + process.env.WEBSITE_SKU = 'Standard'; + process.env.WEBSITE_AUTH_ENABLED = 'True'; + process.env.WEBSITE_AUTH_DEFAULT_PROVIDER = 'AzureActiveDirectory'; + process.env.WEBSITE_AUTH_TOKEN_STORE = 'True'; + + const factory = easyAuth.create({ + signIn: { + resolver: jest.fn(), + }, + }); + + expect(factory({} as any)).toBeInstanceOf(EasyAuthAuthProvider); + }); +}); diff --git a/plugins/auth-backend/src/providers/azure-easyauth/provider.ts b/plugins/auth-backend/src/providers/azure-easyauth/provider.ts new file mode 100644 index 0000000000..8debc3afb6 --- /dev/null +++ b/plugins/auth-backend/src/providers/azure-easyauth/provider.ts @@ -0,0 +1,202 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AuthHandler, + AuthProviderRouteHandlers, + AuthResolverContext, + AuthResponse, + SignInResolver, +} from '../types'; +import { Request, Response } from 'express'; +import { makeProfileInfo } from '../../lib/passport'; +import { AuthenticationError } from '@backstage/errors'; +import { prepareBackstageIdentityResponse } from '../prepareBackstageIdentityResponse'; +import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; +import { Profile } from 'passport'; +import { decodeJwt } from 'jose'; + +export const ID_TOKEN_HEADER = 'x-ms-token-aad-id-token'; +export const ACCESS_TOKEN_HEADER = 'x-ms-token-aad-access-token'; + +type Options = { + authHandler: AuthHandler; + signInResolver: SignInResolver; + resolverContext: AuthResolverContext; +}; + +export type EasyAuthResult = { + fullProfile: Profile; + accessToken?: string; +}; + +export type EasyAuthResponse = AuthResponse<{}>; + +export class EasyAuthAuthProvider implements AuthProviderRouteHandlers { + private readonly resolverContext: AuthResolverContext; + private readonly authHandler: AuthHandler; + private readonly signInResolver: SignInResolver; + + constructor(options: Options) { + this.authHandler = options.authHandler; + this.signInResolver = options.signInResolver; + this.resolverContext = options.resolverContext; + } + + frameHandler(): Promise { + return Promise.resolve(undefined); + } + + async refresh(req: Request, res: Response): Promise { + const result = await this.getResult(req); + const response = await this.handleResult(result); + res.json(response); + } + + start(): Promise { + return Promise.resolve(undefined); + } + + private async getResult(req: Request): Promise { + const idToken = req.header(ID_TOKEN_HEADER); + const accessToken = req.header(ACCESS_TOKEN_HEADER); + if (idToken === undefined) { + throw new AuthenticationError(`Missing ${ID_TOKEN_HEADER} header`); + } + + return { + fullProfile: this.idTokenToProfile(idToken), + accessToken: accessToken, + }; + } + + private idTokenToProfile(idToken: string) { + const claims = decodeJwt(idToken); + + if (claims.ver !== '2.0') { + throw new Error('id_token is not version 2.0 '); + } + + return { + id: claims.oid, + displayName: claims.name, + provider: 'easyauth', + emails: [{ value: claims.email }], + username: claims.preferred_username, + } as Profile; + } + + private async handleResult( + result: EasyAuthResult, + ): Promise { + const { profile } = await this.authHandler(result, this.resolverContext); + + const backstageIdentity = await this.signInResolver( + { + result, + profile, + }, + this.resolverContext, + ); + + return { + providerInfo: { + accessToken: result.accessToken, + }, + backstageIdentity: prepareBackstageIdentityResponse(backstageIdentity), + profile, + }; + } +} + +/** + * Auth provider integration for Azure EasyAuth + * + * @public + */ +export const easyAuth = createAuthProviderIntegration({ + create(options?: { + /** + * The profile transformation function used to verify and convert the auth response + * into the profile that will be presented to the user. + */ + authHandler?: AuthHandler; + + /** + * Configure sign-in for this provider, without it the provider can not be used to sign users in. + */ + signIn: { + /** + * Maps an auth result to a Backstage identity for the user. + */ + resolver: SignInResolver; + }; + }) { + return ({ resolverContext }) => { + validateAppServiceConfiguration(process.env); + + if (options?.signIn.resolver === undefined) { + throw new Error( + 'SignInResolver is required to use this authentication provider', + ); + } + + const authHandler = + options.authHandler ?? + (async ({ fullProfile }) => ({ + profile: makeProfileInfo(fullProfile), + })); + + return new EasyAuthAuthProvider({ + signInResolver: options.signIn.resolver, + authHandler, + resolverContext, + }); + }; + }, +}); + +function validateAppServiceConfiguration(env: NodeJS.ProcessEnv) { + // Based on https://github.com/AzureAD/microsoft-identity-web/blob/f7403779d1a91f4a3fec0ed0993bd82f50f299e1/src/Microsoft.Identity.Web/AppServicesAuth/AppServicesAuthenticationInformation.cs#L38-L59 + // + // It's critical to validate we're really running in a correctly configured Azure App Services, + // As we rely on App Services to manage & validate the ID and Access Token headers + // Without that, this users can be trivially impersonated. + if (env.WEBSITE_SKU === undefined) { + throw new Error('Backstage is not running on Azure App Services'); + } + if (!isEqualCaseInsensitive(env.WEBSITE_AUTH_ENABLED, 'True')) { + throw new Error('Azure App Services does not have authentication enabled'); + } + if ( + !isEqualCaseInsensitive( + env.WEBSITE_AUTH_DEFAULT_PROVIDER, + 'AzureActiveDirectory', + ) + ) { + throw new Error('Authentication provider is not Azure Active Directory'); + } + if (!isEqualCaseInsensitive(process.env.WEBSITE_AUTH_TOKEN_STORE, 'True')) { + throw new Error('Token Store is not enabled'); + } +} + +function isEqualCaseInsensitive(left: string | undefined, right: string) { + return ( + left !== undefined && + right.localeCompare(left, undefined, { sensitivity: 'base' }) === 0 + ); +} From 529de8c421143e2f68a66539a2789d56f29ad426 Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Wed, 1 Feb 2023 12:05:59 +0000 Subject: [PATCH 033/417] Added changeset Signed-off-by: Alex Crome --- .changeset/twenty-jeans-speak.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/twenty-jeans-speak.md diff --git a/.changeset/twenty-jeans-speak.md b/.changeset/twenty-jeans-speak.md new file mode 100644 index 0000000000..c7385031e6 --- /dev/null +++ b/.changeset/twenty-jeans-speak.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': minor +--- + +Added authentication provider for Azure Easy Authentication. From 0d137f6fa5d7c31a06b1401ee7965d020bfa5abe Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 10:00:18 +0100 Subject: [PATCH 034/417] catalog-client: export types as public Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 9 ++++----- packages/catalog-client/src/CatalogClient.ts | 2 -- packages/catalog-client/src/types/api.ts | 10 +++++----- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index 47c6ff7f36..2e6b5b9203 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -58,7 +58,6 @@ export interface CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; - // @alpha getPaginatedEntities?( request?: GetPaginatedEntitiesRequest, options?: CatalogRequestOptions, @@ -243,14 +242,14 @@ export interface GetEntityFacetsResponse { >; } -// @alpha +// @public export type GetPaginatedEntitiesCursorRequest = { fields?: string[]; limit?: number; cursor: string; }; -// @alpha +// @public export type GetPaginatedEntitiesInitialRequest = { fields?: string[]; limit?: number; @@ -259,12 +258,12 @@ export type GetPaginatedEntitiesInitialRequest = { query?: string; }; -// @alpha +// @public export type GetPaginatedEntitiesRequest = | GetPaginatedEntitiesInitialRequest | GetPaginatedEntitiesCursorRequest; -// @alpha +// @public export type GetPaginatedEntitiesResponse = { entities: Entity[]; totalItems: number; diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 7347535ca6..dca46c3ab6 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -207,8 +207,6 @@ export class CatalogClient implements CatalogApi { /** * {@inheritdoc CatalogApi.getPaginatedEntities} - * - * @alpha */ async getPaginatedEntities?( request: GetPaginatedEntitiesRequest = {}, diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 4e7f679072..0f0d0fe63c 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -380,7 +380,7 @@ export type ValidateEntityResponse = /** * The request type for {@link CatalogClient.getPaginatedEntities}. * - * @alpha + * @public */ export type GetPaginatedEntitiesRequest = | GetPaginatedEntitiesInitialRequest @@ -394,7 +394,7 @@ export type GetPaginatedEntitiesRequest = * The properties filter, sortField, query and sortFieldOrder, are going * to be immutable for the entire lifecycle of the following requests. * - * @alpha + * @public */ export type GetPaginatedEntitiesInitialRequest = { fields?: string[]; @@ -409,7 +409,7 @@ export type GetPaginatedEntitiesInitialRequest = { * The method takes this type in a pagination request, following * the initial request. * - * @alpha + * @public */ export type GetPaginatedEntitiesCursorRequest = { fields?: string[]; @@ -420,7 +420,7 @@ export type GetPaginatedEntitiesCursorRequest = { /** * The response type for {@link CatalogClient.getPaginatedEntities}. * - * @alpha + * @public */ export type GetPaginatedEntitiesResponse = { /* The list of entities for the current request */ @@ -503,7 +503,7 @@ export interface CatalogApi { * with a prev function useful for navigating backwards and a next function * in case more entities matching the filters of the first request are present in the catalog. * - * @alpha + * @public * * @param request - Request parameters * @param options - Additional options From cf5c58a89fcc3bf4917ab52de7b201ac81910372 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 13:30:52 +0100 Subject: [PATCH 035/417] catalog-backend: validate cursor Signed-off-by: Vincenzo Scamporlino --- .../service/DefaultEntitiesCatalog.test.ts | 20 +++++++++++ .../src/service/DefaultEntitiesCatalog.ts | 34 ++++++++++++++++--- plugins/catalog-backend/src/service/util.ts | 10 +++--- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index bde55ef9bb..a25cbf2240 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1294,6 +1294,26 @@ describe('DefaultEntitiesCatalog', () => { expect(response5.totalItems).toBe(6); }, ); + + it('should throw in case of malformed cursor', async () => { + const catalog = new DefaultEntitiesCatalog({ + database: knex, + logger: getVoidLogger(), + stitcher, + }); + + const cursor = Buffer.from( + JSON.stringify({ filter: 'notavalidfilter' }), + 'utf8', + ).toString('base64'); + const request: PaginatedEntitiesCursorRequest = { + cursor, + }; + + await expect(catalog.paginatedEntities(request)).rejects.toThrow( + Error('Malformed cursor, could not be parsed'), + ); + }); }); describe('removeEntityByUid', () => { diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 0cc791e5de..67fe77cc8b 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -23,6 +23,7 @@ import { InputError, NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; import { isEqual, chunk as lodashChunk } from 'lodash'; import { Logger } from 'winston'; +import { z } from 'zod'; import { EntitiesBatchRequest, EntitiesBatchResponse, @@ -658,11 +659,39 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { } } +const entityFilterParser: z.ZodSchema = z.lazy(() => + z + .object({ + key: z.string(), + values: z.array(z.string()).optional(), + }) + .or(z.object({ not: entityFilterParser })) + .or(z.object({ anyOf: z.array(entityFilterParser) })) + .or(z.object({ allOf: z.array(entityFilterParser) })), +); + +export const cursorParser: z.ZodSchema = z.object({ + sortFields: z.array( + z.object({ field: z.string(), order: z.enum(['asc', 'desc']) }), + ), + sortFieldValues: z.array(z.string().or(z.null())), + filter: entityFilterParser.optional(), + isPrevious: z.boolean(), + query: z.string().optional(), + firstSortFieldValues: z.array(z.string().or(z.null())).optional(), + totalItems: z.number().optional(), +}); + function encodeCursor(cursor: Cursor) { const json = JSON.stringify(cursor); return Buffer.from(json, 'utf8').toString('base64'); } +function decodeCursor(encodedCursor: string) { + const json = Buffer.from(encodedCursor, 'base64').toString('utf8'); + return cursorParser.parse(JSON.parse(json)); +} + function parseCursorFromRequest( request?: PaginatedEntitiesRequest, ): Partial { @@ -672,10 +701,7 @@ function parseCursorFromRequest( } if (isPaginatedEntitiesCursorRequest(request)) { try { - const json = Buffer.from(request.cursor, 'base64').toString('utf8'); - const cursor = JSON.parse(json); - // TODO(vinzscam): validate the shit - return cursor as unknown as Cursor; + return decodeCursor(request.cursor); } catch { throw new InputError('Malformed cursor, could not be parsed'); } diff --git a/plugins/catalog-backend/src/service/util.ts b/plugins/catalog-backend/src/service/util.ts index bb86654565..958b4153f8 100644 --- a/plugins/catalog-backend/src/service/util.ts +++ b/plugins/catalog-backend/src/service/util.ts @@ -19,9 +19,9 @@ import { Request } from 'express'; import lodash from 'lodash'; import { z } from 'zod'; import { - EntitiesRequest, PaginatedEntitiesCursorRequest, PaginatedEntitiesInitialRequest, + PaginatedEntitiesRequest, } from '../catalog/types'; export async function requireRequestBody(req: Request): Promise { @@ -72,21 +72,19 @@ export function disallowReadonlyMode(readonly: boolean) { } export function isPaginatedEntitiesInitialRequest( - input: EntitiesRequest | undefined, + input: PaginatedEntitiesRequest | undefined, ): input is PaginatedEntitiesInitialRequest { if (!input) { return false; } - // TODO(vinzscam) expand this return !isPaginatedEntitiesCursorRequest(input); } export function isPaginatedEntitiesCursorRequest( - input: EntitiesRequest | undefined, + input: PaginatedEntitiesRequest | undefined, ): input is PaginatedEntitiesCursorRequest { if (!input) { return false; } - // TODO(vinzscam) expand this - return input?.hasOwnProperty('cursor') ?? false; + return !!(input as PaginatedEntitiesCursorRequest).cursor; } From fd173aac2ca6cf01d879e24e80dadba9e5cf711d Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 13:39:18 +0100 Subject: [PATCH 036/417] catalog-client: make paginated response serializable Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 9 ++---- .../catalog-client/src/CatalogClient.test.ts | 12 ++++---- packages/catalog-client/src/CatalogClient.ts | 30 ++++--------------- packages/catalog-client/src/types/api.ts | 12 +++----- 4 files changed, 18 insertions(+), 45 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index 2e6b5b9203..e39fa7eb8d 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -128,7 +128,6 @@ export class CatalogClient implements CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; - // @alpha getPaginatedEntities?( request?: GetPaginatedEntitiesRequest, options?: CatalogRequestOptions, @@ -267,12 +266,8 @@ export type GetPaginatedEntitiesRequest = export type GetPaginatedEntitiesResponse = { entities: Entity[]; totalItems: number; - next?( - request?: Omit, - ): Promise; - prev?( - request?: Omit, - ): Promise; + nextCursor?: string; + prevCursor?: string; }; // @public diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 4e5065e089..ed27bb0016 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -310,8 +310,8 @@ describe('CatalogClient', () => { const response = await client.getPaginatedEntities?.({}, { token }); expect(response?.entities).toEqual(defaultClientResponse.entities); expect(response?.totalItems).toEqual(defaultClientResponse.totalItems); - expect(response?.next).toBeDefined(); - expect(response?.prev).toBeDefined(); + expect(response?.nextCursor).toBeDefined(); + expect(response?.prevCursor).toBeDefined(); }); it('builds multiple entity search filters properly', async () => { @@ -429,15 +429,15 @@ describe('CatalogClient', () => { }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe('?limit=2'); - expect(response?.next).toBeDefined(); - expect(response?.prev).toBeDefined(); + expect(response?.nextCursor).toBeDefined(); + expect(response?.prevCursor).toBeDefined(); - await response?.next?.(); + await client.getPaginatedEntities?.({ cursor: response!.nextCursor! }); expect(mockedEndpoint.mock.calls[1][0].url.search).toBe( '?cursor=nextcursor', ); - await response?.prev?.(); + await client.getPaginatedEntities?.({ cursor: response!.prevCursor! }); expect(mockedEndpoint.mock.calls[2][0].url.search).toBe( '?cursor=prevcursor', ); diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index dca46c3ab6..52ed2fd8fc 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -42,7 +42,6 @@ import { GetPaginatedEntitiesRequest, GetPaginatedEntitiesResponse, EntityFilterQuery, - GetPaginatedEntitiesCursorRequest, } from './types/api'; import { DiscoveryApi } from './types/discovery'; import { FetchApi } from './types/fetch'; @@ -247,18 +246,12 @@ export class CatalogClient implements CatalogApi { } const query = params.length ? `?${params.join('&')}` : ''; - const { entities, totalItems, nextCursor, prevCursor } = - await this.requestRequired<{ - entities: Entity[]; - totalItems: number; - nextCursor?: string; - prevCursor?: string; - }>('GET', `/v2beta1/entities${query}`, options); - - const next = this.getEntitiesFromCursor(nextCursor, options); - const prev = this.getEntitiesFromCursor(prevCursor, options); - - return { entities, totalItems, next, prev }; + return this.requestRequired<{ + entities: Entity[]; + totalItems: number; + nextCursor?: string; + prevCursor?: string; + }>('GET', `/v2beta1/entities${query}`, options); } /** @@ -546,15 +539,4 @@ export class CatalogClient implements CatalogApi { } return params; } - - private getEntitiesFromCursor( - cursor: string | undefined, - options?: CatalogRequestOptions, - ) { - if (!cursor) { - return undefined; - } - return (request: Omit = {}) => - this.getPaginatedEntities!({ ...request, cursor }, options); - } } diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 0f0d0fe63c..fbee3d6afb 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -427,14 +427,10 @@ export type GetPaginatedEntitiesResponse = { entities: Entity[]; /* The number of entities among all the requests */ totalItems: number; - /* A method returning a promise containing the next batch of entities. */ - next?( - request?: Omit, - ): Promise; - /* A method returning a promise containing the previous batch of entities. */ - prev?( - request?: Omit, - ): Promise; + /* The cursor for the next batch of entities */ + nextCursor?: string; + /* The cursor for the previous batch of entities */ + prevCursor?: string; }; /** From c5494cf09b835940fc1863b30a3a5cd7e4975435 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 13:42:05 +0100 Subject: [PATCH 037/417] catalog: move paginated endpoint Signed-off-by: Vincenzo Scamporlino --- .changeset/silly-suits-run.md | 2 +- packages/catalog-client/src/CatalogClient.test.ts | 10 +++++----- packages/catalog-client/src/CatalogClient.ts | 2 +- .../catalog-backend/src/service/createRouter.test.ts | 10 ++++------ plugins/catalog-backend/src/service/createRouter.ts | 2 +- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.changeset/silly-suits-run.md b/.changeset/silly-suits-run.md index ed0961a584..812e6ee933 100644 --- a/.changeset/silly-suits-run.md +++ b/.changeset/silly-suits-run.md @@ -3,6 +3,6 @@ '@backstage/plugin-catalog-backend': minor --- -Add /v2beta1/entities endpoint returning paginated entities. +Add /v2/entities endpoint returning paginated entities. The endpoint supports cursor base pagination and server side sorting of the entities by name or uid. diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index ed27bb0016..9dc60da193 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -300,7 +300,7 @@ describe('CatalogClient', () => { beforeEach(() => { server.use( - rest.get(`${mockBaseUrl}/v2beta1/entities`, (_, res, ctx) => { + rest.get(`${mockBaseUrl}/v2/entities`, (_, res, ctx) => { return res(ctx.json(defaultServiceResponse)); }), ); @@ -321,7 +321,7 @@ describe('CatalogClient', () => { res(ctx.json({ entities: [], totalItems: 0 })), ); - server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); const response = await client.getPaginatedEntities?.( { @@ -356,7 +356,7 @@ describe('CatalogClient', () => { res(ctx.json({ entities: [], totalItems: 0 })), ); - server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); await client.getPaginatedEntities?.({ fields: ['a', 'b'], @@ -379,7 +379,7 @@ describe('CatalogClient', () => { res(ctx.json({ entities: [], totalItems: 0 })), ); - server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); await client.getPaginatedEntities?.({ fields: ['a', 'b'], @@ -422,7 +422,7 @@ describe('CatalogClient', () => { ), ); - server.use(rest.get(`${mockBaseUrl}/v2beta1/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); const response = await client.getPaginatedEntities?.({ limit: 2, diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 52ed2fd8fc..8af2a40ccd 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -251,7 +251,7 @@ export class CatalogClient implements CatalogApi { totalItems: number; nextCursor?: string; prevCursor?: string; - }>('GET', `/v2beta1/entities${query}`, options); + }>('GET', `/v2/entities${query}`, options); } /** diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index c3b96fbfd8..0fe32c02b1 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -136,7 +136,7 @@ describe('createRouter readonly disabled', () => { }); }); - describe('GET /v2beta1/entities', () => { + describe('GET /v2/entities', () => { it('happy path: lists entities', async () => { const entities: Entity[] = [ { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, @@ -148,7 +148,7 @@ describe('createRouter readonly disabled', () => { nextCursor: 'something', }); - const response = await request(app).get('/v2beta1/entities'); + const response = await request(app).get('/v2/entities'); expect(response.status).toEqual(200); expect(response.body).toEqual({ entities, @@ -163,7 +163,7 @@ describe('createRouter readonly disabled', () => { totalItems: 0, }); const response = await request(app).get( - '/v2beta1/entities?filter=a=1,a=2,b=3&filter=c=4&sortField=metadata.name,asc&sortField=metadata.uid,desc', + '/v2/entities?filter=a=1,a=2,b=3&filter=c=4&sortField=metadata.name,asc&sortField=metadata.uid,desc', ); expect(response.status).toEqual(200); @@ -198,9 +198,7 @@ describe('createRouter readonly disabled', () => { nextCursor: 'next', }); - const response = await request(app).get( - '/v2beta1/entities?cursor=something', - ); + const response = await request(app).get('/v2/entities?cursor=something'); expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledTimes(1); expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledWith({ cursor: 'something', diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index a7f5373a03..c4c2c87bad 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -131,7 +131,7 @@ export async function createRouter( // TODO(freben): encode the pageInfo in the response res.json(entities); }) - .get('/v2beta1/entities', async (req, res) => { + .get('/v2/entities', async (req, res) => { const response = await entitiesCatalog.paginatedEntities({ ...parsePaginatedEntitiesParams(req.query), authorizationToken: getBearerToken(req.header('authorization')), From 47bcc6cf33bf78b43cea99c9914bd00f2183711a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 13:54:04 +0100 Subject: [PATCH 038/417] catalog-client: improve docs Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/src/types/api.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index fbee3d6afb..168dbbcaff 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -479,8 +479,7 @@ export interface CatalogApi { * filter: [{ kind: 'group' }], * limit: 20, * query: 'A', - * sortField: 'metadata.name', - * sortFieldOrder: 'asc' + * sortFields: { field: 'metadata.name' order: 'asc' }, * }); * ``` * @@ -488,16 +487,16 @@ export interface CatalogApi { * with 'A', ordered by name ascending. * * The response will contain a maximum of 20 entities. In case - * more than 20 entities exist, the response will contain a next function, invocable - * using: + * more than 20 entities exist, the response will contain a nextCursor + * property that can be used to fetch the next batch of entities. * * ``` - * const secondBatchResponse = await response.next({ limit: 20 }); + * const secondBatchResponse = await catalogClient + * .getPaginatedEntities({ cursor: response.nextCursor }); * ``` * - * secondBatchResponse will contain the next batch of maximum 20 entities, together - * with a prev function useful for navigating backwards and a next function - * in case more entities matching the filters of the first request are present in the catalog. + * secondBatchResponse will contain the next batch of (maximum) 20 entities, + * together with a prevCursor property, useful to fetch the previous batch. * * @public * From b33cfbbce404ae179160be3375500ece1a4647c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 13:17:35 +0000 Subject: [PATCH 039/417] fix(deps): update dependency humanize-duration to v3.28.0 Signed-off-by: Renovate Bot --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4e56cb9839..3f27b3574a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5600,7 +5600,7 @@ __metadata: "@types/luxon": ^3.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - humanize-duration: ^3.27.1 + humanize-duration: ^3.27.0 luxon: ^3.0.0 msw: ^0.49.0 react-use: ^17.2.4 @@ -6520,7 +6520,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - humanize-duration: ^3.26.0 + humanize-duration: ^3.27.0 luxon: ^3.0.0 msw: ^0.49.0 react-use: ^17.2.4 @@ -7508,7 +7508,7 @@ __metadata: cross-fetch: ^3.1.5 event-source-polyfill: 1.0.25 git-url-parse: ^13.0.0 - humanize-duration: ^3.25.1 + humanize-duration: ^3.27.0 immer: ^9.0.1 json-schema: ^0.4.0 json-schema-library: ^7.3.9 @@ -24945,7 +24945,7 @@ __metadata: languageName: node linkType: hard -"humanize-duration@npm:^3.25.1, humanize-duration@npm:^3.26.0, humanize-duration@npm:^3.27.0, humanize-duration@npm:^3.27.1": +"humanize-duration@npm:^3.27.0": version: 3.27.3 resolution: "humanize-duration@npm:3.27.3" checksum: 17193537334676cbff156a5f60ea6349e4e981f33062fdae901ac10ed096d4f05e7b8839d362cbda7a06ade2a499f0a655e3c1bf9da6d4a234d99ed0498ba516 From 885f1b22fa6f87eb3f4d54c7ab5cda05b8581543 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 1 Feb 2023 14:47:04 +0100 Subject: [PATCH 040/417] chore: fix yarn install Signed-off-by: blam --- yarn.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3f27b3574a..93ed5d5663 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5600,7 +5600,7 @@ __metadata: "@types/luxon": ^3.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - humanize-duration: ^3.27.0 + humanize-duration: ^3.27.1 luxon: ^3.0.0 msw: ^0.49.0 react-use: ^17.2.4 @@ -6520,7 +6520,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - humanize-duration: ^3.27.0 + humanize-duration: ^3.26.0 luxon: ^3.0.0 msw: ^0.49.0 react-use: ^17.2.4 @@ -7508,7 +7508,7 @@ __metadata: cross-fetch: ^3.1.5 event-source-polyfill: 1.0.25 git-url-parse: ^13.0.0 - humanize-duration: ^3.27.0 + humanize-duration: ^3.25.1 immer: ^9.0.1 json-schema: ^0.4.0 json-schema-library: ^7.3.9 @@ -24945,10 +24945,10 @@ __metadata: languageName: node linkType: hard -"humanize-duration@npm:^3.27.0": - version: 3.27.3 - resolution: "humanize-duration@npm:3.27.3" - checksum: 17193537334676cbff156a5f60ea6349e4e981f33062fdae901ac10ed096d4f05e7b8839d362cbda7a06ade2a499f0a655e3c1bf9da6d4a234d99ed0498ba516 +"humanize-duration@npm:^3.25.1, humanize-duration@npm:^3.26.0, humanize-duration@npm:^3.27.0, humanize-duration@npm:^3.27.1": + version: 3.28.0 + resolution: "humanize-duration@npm:3.28.0" + checksum: dde595ab4729d82147db41d8ca0afa86bf3f20d74cd1323ea52f299091a4f1dcb2a45b2d27ce78ab9bb0d9e66d8eb8f2628a67be36a535af645eb282a963ff7f languageName: node linkType: hard From 9bb980d23f854d00ee65dc3fb69ecdaf3913c989 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 1 Feb 2023 20:58:51 +0100 Subject: [PATCH 041/417] catalog-client: make getPaginatedEntities non optional Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 4 ++-- packages/catalog-client/src/CatalogClient.test.ts | 14 +++++++------- packages/catalog-client/src/CatalogClient.ts | 2 +- packages/catalog-client/src/types/api.ts | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index e39fa7eb8d..1abc90d24c 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -58,7 +58,7 @@ export interface CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; - getPaginatedEntities?( + getPaginatedEntities( request?: GetPaginatedEntitiesRequest, options?: CatalogRequestOptions, ): Promise; @@ -128,7 +128,7 @@ export class CatalogClient implements CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; - getPaginatedEntities?( + getPaginatedEntities( request?: GetPaginatedEntitiesRequest, options?: CatalogRequestOptions, ): Promise; diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 9dc60da193..fde54adeb6 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -307,7 +307,7 @@ describe('CatalogClient', () => { }); it('should fetch entities from correct endpoint', async () => { - const response = await client.getPaginatedEntities?.({}, { token }); + const response = await client.getPaginatedEntities({}, { token }); expect(response?.entities).toEqual(defaultClientResponse.entities); expect(response?.totalItems).toEqual(defaultClientResponse.totalItems); expect(response?.nextCursor).toBeDefined(); @@ -323,7 +323,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); - const response = await client.getPaginatedEntities?.( + const response = await client.getPaginatedEntities( { filter: [ { @@ -358,7 +358,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); - await client.getPaginatedEntities?.({ + await client.getPaginatedEntities({ fields: ['a', 'b'], limit: 100, query: 'query', @@ -381,7 +381,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); - await client.getPaginatedEntities?.({ + await client.getPaginatedEntities({ fields: ['a', 'b'], limit: 100, query: 'query', @@ -424,7 +424,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); - const response = await client.getPaginatedEntities?.({ + const response = await client.getPaginatedEntities({ limit: 2, }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe('?limit=2'); @@ -432,12 +432,12 @@ describe('CatalogClient', () => { expect(response?.nextCursor).toBeDefined(); expect(response?.prevCursor).toBeDefined(); - await client.getPaginatedEntities?.({ cursor: response!.nextCursor! }); + await client.getPaginatedEntities({ cursor: response!.nextCursor! }); expect(mockedEndpoint.mock.calls[1][0].url.search).toBe( '?cursor=nextcursor', ); - await client.getPaginatedEntities?.({ cursor: response!.prevCursor! }); + await client.getPaginatedEntities({ cursor: response!.prevCursor! }); expect(mockedEndpoint.mock.calls[2][0].url.search).toBe( '?cursor=prevcursor', ); diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 8af2a40ccd..6d7188edbb 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -207,7 +207,7 @@ export class CatalogClient implements CatalogApi { /** * {@inheritdoc CatalogApi.getPaginatedEntities} */ - async getPaginatedEntities?( + async getPaginatedEntities( request: GetPaginatedEntitiesRequest = {}, options?: CatalogRequestOptions, ): Promise { diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 168dbbcaff..667bc3d8f0 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -503,7 +503,7 @@ export interface CatalogApi { * @param request - Request parameters * @param options - Additional options */ - getPaginatedEntities?( + getPaginatedEntities( request?: GetPaginatedEntitiesRequest, options?: CatalogRequestOptions, ): Promise; From b17bc0191385f235b927fb88afdcc62186301ce0 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 2 Feb 2023 11:10:44 +0100 Subject: [PATCH 042/417] catalog-backend: move endpoint to /entities/by-query Signed-off-by: Vincenzo Scamporlino --- .changeset/silly-suits-run.md | 2 +- packages/catalog-client/src/CatalogClient.test.ts | 10 +++++----- packages/catalog-client/src/CatalogClient.ts | 2 +- .../catalog-backend/src/service/createRouter.test.ts | 10 ++++++---- plugins/catalog-backend/src/service/createRouter.ts | 2 +- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.changeset/silly-suits-run.md b/.changeset/silly-suits-run.md index 812e6ee933..2fc731f2a4 100644 --- a/.changeset/silly-suits-run.md +++ b/.changeset/silly-suits-run.md @@ -3,6 +3,6 @@ '@backstage/plugin-catalog-backend': minor --- -Add /v2/entities endpoint returning paginated entities. +Add /entities/by-query endpoint returning paginated entities. The endpoint supports cursor base pagination and server side sorting of the entities by name or uid. diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index fde54adeb6..cd8a0c48da 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -300,7 +300,7 @@ describe('CatalogClient', () => { beforeEach(() => { server.use( - rest.get(`${mockBaseUrl}/v2/entities`, (_, res, ctx) => { + rest.get(`${mockBaseUrl}/entities/by-query`, (_, res, ctx) => { return res(ctx.json(defaultServiceResponse)); }), ); @@ -321,7 +321,7 @@ describe('CatalogClient', () => { res(ctx.json({ entities: [], totalItems: 0 })), ); - server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); const response = await client.getPaginatedEntities( { @@ -356,7 +356,7 @@ describe('CatalogClient', () => { res(ctx.json({ entities: [], totalItems: 0 })), ); - server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); await client.getPaginatedEntities({ fields: ['a', 'b'], @@ -379,7 +379,7 @@ describe('CatalogClient', () => { res(ctx.json({ entities: [], totalItems: 0 })), ); - server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); await client.getPaginatedEntities({ fields: ['a', 'b'], @@ -422,7 +422,7 @@ describe('CatalogClient', () => { ), ); - server.use(rest.get(`${mockBaseUrl}/v2/entities`, mockedEndpoint)); + server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); const response = await client.getPaginatedEntities({ limit: 2, diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 6d7188edbb..757d6eaa15 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -251,7 +251,7 @@ export class CatalogClient implements CatalogApi { totalItems: number; nextCursor?: string; prevCursor?: string; - }>('GET', `/v2/entities${query}`, options); + }>('GET', `/entities/by-query${query}`, options); } /** diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 0fe32c02b1..8f5aeab2a0 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -136,7 +136,7 @@ describe('createRouter readonly disabled', () => { }); }); - describe('GET /v2/entities', () => { + describe('GET /entities/by-query', () => { it('happy path: lists entities', async () => { const entities: Entity[] = [ { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, @@ -148,7 +148,7 @@ describe('createRouter readonly disabled', () => { nextCursor: 'something', }); - const response = await request(app).get('/v2/entities'); + const response = await request(app).get('/entities/by-query'); expect(response.status).toEqual(200); expect(response.body).toEqual({ entities, @@ -163,7 +163,7 @@ describe('createRouter readonly disabled', () => { totalItems: 0, }); const response = await request(app).get( - '/v2/entities?filter=a=1,a=2,b=3&filter=c=4&sortField=metadata.name,asc&sortField=metadata.uid,desc', + '/entities/by-query?filter=a=1,a=2,b=3&filter=c=4&sortField=metadata.name,asc&sortField=metadata.uid,desc', ); expect(response.status).toEqual(200); @@ -198,7 +198,9 @@ describe('createRouter readonly disabled', () => { nextCursor: 'next', }); - const response = await request(app).get('/v2/entities?cursor=something'); + const response = await request(app).get( + '/entities/by-query?cursor=something', + ); expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledTimes(1); expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledWith({ cursor: 'something', diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index c4c2c87bad..994b676345 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -131,7 +131,7 @@ export async function createRouter( // TODO(freben): encode the pageInfo in the response res.json(entities); }) - .get('/v2/entities', async (req, res) => { + .get('/entities/by-query', async (req, res) => { const response = await entitiesCatalog.paginatedEntities({ ...parsePaginatedEntitiesParams(req.query), authorizationToken: getBearerToken(req.header('authorization')), From cdbe702d35a62ec741600c26733399ed6b73615d Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 2 Feb 2023 11:17:49 +0100 Subject: [PATCH 043/417] catalog:client rename method to queryEntities Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 40 +++++++++---------- .../catalog-client/src/CatalogClient.test.ts | 16 ++++---- packages/catalog-client/src/CatalogClient.ts | 12 +++--- packages/catalog-client/src/types/api.ts | 30 +++++++------- packages/catalog-client/src/types/index.ts | 8 ++-- packages/catalog-client/src/utils.ts | 16 ++++---- 6 files changed, 61 insertions(+), 61 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index 1abc90d24c..b8a6a17a09 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -58,10 +58,10 @@ export interface CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; - getPaginatedEntities( - request?: GetPaginatedEntitiesRequest, + queryEntities( + request?: QueryEntitiesRequest, options?: CatalogRequestOptions, - ): Promise; + ): Promise; refreshEntity( entityRef: string, options?: CatalogRequestOptions, @@ -128,10 +128,10 @@ export class CatalogClient implements CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise; - getPaginatedEntities( - request?: GetPaginatedEntitiesRequest, + queryEntities( + request?: QueryEntitiesRequest, options?: CatalogRequestOptions, - ): Promise; + ): Promise; refreshEntity( entityRef: string, options?: CatalogRequestOptions, @@ -242,14 +242,22 @@ export interface GetEntityFacetsResponse { } // @public -export type GetPaginatedEntitiesCursorRequest = { +type Location_2 = { + id: string; + type: string; + target: string; +}; +export { Location_2 as Location }; + +// @public +export type QueryEntitiesCursorRequest = { fields?: string[]; limit?: number; cursor: string; }; // @public -export type GetPaginatedEntitiesInitialRequest = { +export type QueryEntitiesInitialRequest = { fields?: string[]; limit?: number; filter?: EntityFilterQuery; @@ -258,26 +266,18 @@ export type GetPaginatedEntitiesInitialRequest = { }; // @public -export type GetPaginatedEntitiesRequest = - | GetPaginatedEntitiesInitialRequest - | GetPaginatedEntitiesCursorRequest; +export type QueryEntitiesRequest = + | QueryEntitiesInitialRequest + | QueryEntitiesCursorRequest; // @public -export type GetPaginatedEntitiesResponse = { +export type QueryEntitiesResponse = { entities: Entity[]; totalItems: number; nextCursor?: string; prevCursor?: string; }; -// @public -type Location_2 = { - id: string; - type: string; - target: string; -}; -export { Location_2 as Location }; - // @public export type ValidateEntityResponse = | { diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index cd8a0c48da..bc041ffd19 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -249,7 +249,7 @@ describe('CatalogClient', () => { }); }); - describe('getPaginatedEntities', () => { + describe('queryEntities', () => { const defaultServiceResponse = { entities: [ { @@ -307,7 +307,7 @@ describe('CatalogClient', () => { }); it('should fetch entities from correct endpoint', async () => { - const response = await client.getPaginatedEntities({}, { token }); + const response = await client.queryEntities({}, { token }); expect(response?.entities).toEqual(defaultClientResponse.entities); expect(response?.totalItems).toEqual(defaultClientResponse.totalItems); expect(response?.nextCursor).toBeDefined(); @@ -323,7 +323,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); - const response = await client.getPaginatedEntities( + const response = await client.queryEntities( { filter: [ { @@ -358,7 +358,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); - await client.getPaginatedEntities({ + await client.queryEntities({ fields: ['a', 'b'], limit: 100, query: 'query', @@ -381,7 +381,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); - await client.getPaginatedEntities({ + await client.queryEntities({ fields: ['a', 'b'], limit: 100, query: 'query', @@ -424,7 +424,7 @@ describe('CatalogClient', () => { server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); - const response = await client.getPaginatedEntities({ + const response = await client.queryEntities({ limit: 2, }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe('?limit=2'); @@ -432,12 +432,12 @@ describe('CatalogClient', () => { expect(response?.nextCursor).toBeDefined(); expect(response?.prevCursor).toBeDefined(); - await client.getPaginatedEntities({ cursor: response!.nextCursor! }); + await client.queryEntities({ cursor: response!.nextCursor! }); expect(mockedEndpoint.mock.calls[1][0].url.search).toBe( '?cursor=nextcursor', ); - await client.getPaginatedEntities({ cursor: response!.prevCursor! }); + await client.queryEntities({ cursor: response!.prevCursor! }); expect(mockedEndpoint.mock.calls[2][0].url.search).toBe( '?cursor=prevcursor', ); diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 757d6eaa15..adf23f861c 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -39,8 +39,8 @@ import { ValidateEntityResponse, GetEntitiesByRefsRequest, GetEntitiesByRefsResponse, - GetPaginatedEntitiesRequest, - GetPaginatedEntitiesResponse, + QueryEntitiesRequest, + QueryEntitiesResponse, EntityFilterQuery, } from './types/api'; import { DiscoveryApi } from './types/discovery'; @@ -205,12 +205,12 @@ export class CatalogClient implements CatalogApi { } /** - * {@inheritdoc CatalogApi.getPaginatedEntities} + * {@inheritdoc CatalogApi.queryEntities} */ - async getPaginatedEntities( - request: GetPaginatedEntitiesRequest = {}, + async queryEntities( + request: QueryEntitiesRequest = {}, options?: CatalogRequestOptions, - ): Promise { + ): Promise { const params: string[] = []; if (isPaginatedEntitiesInitialRequest(request)) { diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 667bc3d8f0..09a67c8bce 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -378,16 +378,16 @@ export type ValidateEntityResponse = | { valid: false; errors: SerializedError[] }; /** - * The request type for {@link CatalogClient.getPaginatedEntities}. + * The request type for {@link CatalogClient.queryEntities}. * * @public */ -export type GetPaginatedEntitiesRequest = - | GetPaginatedEntitiesInitialRequest - | GetPaginatedEntitiesCursorRequest; +export type QueryEntitiesRequest = + | QueryEntitiesInitialRequest + | QueryEntitiesCursorRequest; /** - * A request type for {@link CatalogClient.getPaginatedEntities}. + * A request type for {@link CatalogClient.queryEntities}. * The method takes this type in an initial pagination request, * when requesting the first batch of entities. * @@ -396,7 +396,7 @@ export type GetPaginatedEntitiesRequest = * * @public */ -export type GetPaginatedEntitiesInitialRequest = { +export type QueryEntitiesInitialRequest = { fields?: string[]; limit?: number; filter?: EntityFilterQuery; @@ -405,24 +405,24 @@ export type GetPaginatedEntitiesInitialRequest = { }; /** - * A request type for {@link CatalogClient.getPaginatedEntities}. + * A request type for {@link CatalogClient.queryEntities}. * The method takes this type in a pagination request, following * the initial request. * * @public */ -export type GetPaginatedEntitiesCursorRequest = { +export type QueryEntitiesCursorRequest = { fields?: string[]; limit?: number; cursor: string; }; /** - * The response type for {@link CatalogClient.getPaginatedEntities}. + * The response type for {@link CatalogClient.queryEntities}. * * @public */ -export type GetPaginatedEntitiesResponse = { +export type QueryEntitiesResponse = { /* The list of entities for the current request */ entities: Entity[]; /* The number of entities among all the requests */ @@ -475,7 +475,7 @@ export interface CatalogApi { * Example: * * ``` - * const response = await catalogClient.getPaginatedEntities({ + * const response = await catalogClient.queryEntities({ * filter: [{ kind: 'group' }], * limit: 20, * query: 'A', @@ -492,7 +492,7 @@ export interface CatalogApi { * * ``` * const secondBatchResponse = await catalogClient - * .getPaginatedEntities({ cursor: response.nextCursor }); + * .queryEntities({ cursor: response.nextCursor }); * ``` * * secondBatchResponse will contain the next batch of (maximum) 20 entities, @@ -503,10 +503,10 @@ export interface CatalogApi { * @param request - Request parameters * @param options - Additional options */ - getPaginatedEntities( - request?: GetPaginatedEntitiesRequest, + queryEntities( + request?: QueryEntitiesRequest, options?: CatalogRequestOptions, - ): Promise; + ): Promise; /** * Gets entity ancestor information, i.e. the hierarchy of parent entities diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts index 715639e1c3..9bf35886c8 100644 --- a/packages/catalog-client/src/types/index.ts +++ b/packages/catalog-client/src/types/index.ts @@ -33,9 +33,9 @@ export type { GetEntityFacetsResponse, Location, ValidateEntityResponse, - GetPaginatedEntitiesCursorRequest, - GetPaginatedEntitiesInitialRequest, - GetPaginatedEntitiesRequest, - GetPaginatedEntitiesResponse, + QueryEntitiesCursorRequest, + QueryEntitiesInitialRequest, + QueryEntitiesRequest, + QueryEntitiesResponse, } from './api'; export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status'; diff --git a/packages/catalog-client/src/utils.ts b/packages/catalog-client/src/utils.ts index 8a2eb9c06d..d6131b79d2 100644 --- a/packages/catalog-client/src/utils.ts +++ b/packages/catalog-client/src/utils.ts @@ -15,19 +15,19 @@ */ import { - GetPaginatedEntitiesCursorRequest, - GetPaginatedEntitiesInitialRequest, - GetPaginatedEntitiesRequest, + QueryEntitiesCursorRequest, + QueryEntitiesInitialRequest, + QueryEntitiesRequest, } from './types/api'; export function isPaginatedEntitiesInitialRequest( - request: GetPaginatedEntitiesInitialRequest, -): request is GetPaginatedEntitiesInitialRequest { - return !(request as GetPaginatedEntitiesCursorRequest).cursor; + request: QueryEntitiesInitialRequest, +): request is QueryEntitiesInitialRequest { + return !(request as QueryEntitiesCursorRequest).cursor; } export function isPaginatedEntitiesCursorRequest( - request: GetPaginatedEntitiesRequest, -): request is GetPaginatedEntitiesCursorRequest { + request: QueryEntitiesRequest, +): request is QueryEntitiesCursorRequest { return !isPaginatedEntitiesInitialRequest(request); } From 67e44a0023b8a30f1d9019fa398ea5545b41a5f1 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 2 Feb 2023 16:38:01 +0000 Subject: [PATCH 044/417] feat: Add StackStorm plugin Signed-off-by: pamelin --- app-config.yaml | 8 + microsite/data/plugins/stackstorm.yaml | 13 ++ packages/app/package.json | 1 + packages/app/src/App.tsx | 2 + plugins/stackstorm/.eslintrc.js | 1 + plugins/stackstorm/README.md | 60 +++++++ plugins/stackstorm/config.d.ts | 38 ++++ plugins/stackstorm/dev/index.tsx | 27 +++ plugins/stackstorm/package.json | 65 +++++++ .../stackstorm/src/api/StackStormClient.ts | 78 +++++++++ plugins/stackstorm/src/api/index.ts | 24 +++ plugins/stackstorm/src/api/types.ts | 59 +++++++ .../components/ActionsList/ActionsList.tsx | 161 +++++++++++++++++ .../src/components/ActionsList/index.ts | 16 ++ .../ExecutionsTable/ExecutionPanel.tsx | 165 ++++++++++++++++++ .../ExecutionsTable/ExecutionsTable.tsx | 130 ++++++++++++++ .../src/components/ExecutionsTable/Status.tsx | 57 ++++++ .../src/components/ExecutionsTable/index.ts | 16 ++ .../src/components/PacksTable/PacksTable.tsx | 59 +++++++ .../src/components/PacksTable/index.ts | 16 ++ .../StackStormHome/StackStormHome.test.tsx | 38 ++++ .../StackStormHome/StackStormHome.tsx | 68 ++++++++ .../src/components/StackStormHome/index.ts | 16 ++ plugins/stackstorm/src/index.ts | 16 ++ plugins/stackstorm/src/plugin.test.ts | 22 +++ plugins/stackstorm/src/plugin.ts | 55 ++++++ plugins/stackstorm/src/routes.ts | 20 +++ plugins/stackstorm/src/setupTests.ts | 17 ++ yarn.lock | 27 +++ 29 files changed, 1275 insertions(+) create mode 100644 microsite/data/plugins/stackstorm.yaml create mode 100644 plugins/stackstorm/.eslintrc.js create mode 100644 plugins/stackstorm/README.md create mode 100644 plugins/stackstorm/config.d.ts create mode 100644 plugins/stackstorm/dev/index.tsx create mode 100644 plugins/stackstorm/package.json create mode 100644 plugins/stackstorm/src/api/StackStormClient.ts create mode 100644 plugins/stackstorm/src/api/index.ts create mode 100644 plugins/stackstorm/src/api/types.ts create mode 100644 plugins/stackstorm/src/components/ActionsList/ActionsList.tsx create mode 100644 plugins/stackstorm/src/components/ActionsList/index.ts create mode 100644 plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx create mode 100644 plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx create mode 100644 plugins/stackstorm/src/components/ExecutionsTable/Status.tsx create mode 100644 plugins/stackstorm/src/components/ExecutionsTable/index.ts create mode 100644 plugins/stackstorm/src/components/PacksTable/PacksTable.tsx create mode 100644 plugins/stackstorm/src/components/PacksTable/index.ts create mode 100644 plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx create mode 100644 plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx create mode 100644 plugins/stackstorm/src/components/StackStormHome/index.ts create mode 100644 plugins/stackstorm/src/index.ts create mode 100644 plugins/stackstorm/src/plugin.test.ts create mode 100644 plugins/stackstorm/src/plugin.ts create mode 100644 plugins/stackstorm/src/routes.ts create mode 100644 plugins/stackstorm/src/setupTests.ts diff --git a/app-config.yaml b/app-config.yaml index dd72051189..17bc057bac 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -118,6 +118,11 @@ proxy: headers: Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' + '/stackstorm': + target: https://your.stackstorm.instance.com/api + headers: + St2-Api-Key: ${ST2_API_KEY} + organization: name: My Company @@ -443,3 +448,6 @@ gocd: permission: enabled: true + +stackstorm: + webUrl: 'https://your.stackstorm.webui.com' diff --git a/microsite/data/plugins/stackstorm.yaml b/microsite/data/plugins/stackstorm.yaml new file mode 100644 index 0000000000..282117d1fe --- /dev/null +++ b/microsite/data/plugins/stackstorm.yaml @@ -0,0 +1,13 @@ +--- +title: StackStorm +author: ExpediaGroup +authorUrl: https://github.com/ExpediaGroup +category: Automation +description: Manage StackStorm workflow executions from within Backstage. +documentation: https://github.com/backstage/backstage/tree/master/plugins/stackstorm +npmPackageName: '@backstage/plugin-stackstorm' +tags: + - stackstorm + - st2 + - automation + - workflow diff --git a/packages/app/package.json b/packages/app/package.json index f6631ed05b..8ae7164e0a 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -56,6 +56,7 @@ "@backstage/plugin-sentry": "workspace:^", "@backstage/plugin-shortcuts": "workspace:^", "@backstage/plugin-stack-overflow": "workspace:^", + "@backstage/plugin-stackstorm": "workspace:^", "@backstage/plugin-tech-insights": "workspace:^", "@backstage/plugin-tech-radar": "workspace:^", "@backstage/plugin-techdocs": "workspace:^", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 8984a69259..a39430a5eb 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -107,6 +107,7 @@ import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common' import { PlaylistIndexPage } from '@backstage/plugin-playlist'; import { TwoColumnLayout } from './components/scaffolder/customScaffolderLayouts'; import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card'; +import { StackstormPage } from '@backstage/plugin-stackstorm'; const app = createApp({ apis, @@ -279,6 +280,7 @@ const routes = ( } /> } /> } /> + } /> ); diff --git a/plugins/stackstorm/.eslintrc.js b/plugins/stackstorm/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/stackstorm/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/stackstorm/README.md b/plugins/stackstorm/README.md new file mode 100644 index 0000000000..1671e6150f --- /dev/null +++ b/plugins/stackstorm/README.md @@ -0,0 +1,60 @@ +# StackStorm Plugin + +Welcome to the StackStorm plugin! + +A Backstage integration for the [StackStorm](https://docs.stackstorm.com/overview.html). +This plugin allows you to display a list of executions, view execution details, +browse installed packs, actions and more. + +## Getting started + +To get started, first you need a running instance of StackStorm. +One of the quickest ways is [running StackStorm with Docker](https://docs.stackstorm.com/install/docker.html). + +### Installation + +1. Install the plugin with `yarn` in the root of your Backstage directory + +```bash +yarn --cwd packages/app add @backstage/plugin-stackstorm +``` + +2. Import and use the plugin in `packages/app/src/App.tsx` + +```tsx +import { StackstormPage } from '@backstage/plugin-stackstorm'; + +const routes = ( + + {/* ...other routes */} + } /> + +``` + +### Configuration + +1. Configure `webUrl` for links to the StackStorm Web UI in `app-config.yaml`. + +```yaml +stackstorm: + webUrl: 'https://your.stackstorm.webui.com' +``` + +2. Configure `stackstorm` proxy + This plugin uses the Backstage proxy to securely communicate with StackStorm API. + Add the following to your `app-config.yaml` to enable this configuration: + +```yaml +proxy: + '/stackstorm': + target: https://your.stackstorm.instance.com/api + headers: + St2-Api-Key: ${ST2_API_KEY} +``` + +In your production deployment of Backstage, you would also need to ensure that +you've set the `ST2_API_KEY` environment variable before starting +the backend. + +Read more about how to find or generate this key in the +[StackStorm Authentication Documentation](https://docs.stackstorm.com/authentication.html#api-keys). diff --git a/plugins/stackstorm/config.d.ts b/plugins/stackstorm/config.d.ts new file mode 100644 index 0000000000..cf7a2e2253 --- /dev/null +++ b/plugins/stackstorm/config.d.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface Config { + stackstorm?: { + /** + * StackStorm API base url + * Used for local testing to bypass CORS + * @visibility frontend + */ + baseUrl?: string; + /** + * StackStorm API key + * Used for local testing to bypass CORS + * Do not set this in production deployment + * @visibility frontend + */ + key?: string; + /** + * StackStorm Web UI url + * Used in links to StackStorm web UI + * @visibility frontend + */ + webUrl?: string; + }; +} diff --git a/plugins/stackstorm/dev/index.tsx b/plugins/stackstorm/dev/index.tsx new file mode 100644 index 0000000000..33bd89adda --- /dev/null +++ b/plugins/stackstorm/dev/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { createDevApp } from '@backstage/dev-utils'; +import { stackstormPlugin, StackstormPage } from '../src/plugin'; + +createDevApp() + .registerPlugin(stackstormPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/stackstorm', + }) + .render(); diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json new file mode 100644 index 0000000000..921cb07c29 --- /dev/null +++ b/plugins/stackstorm/package.json @@ -0,0 +1,65 @@ +{ + "name": "@backstage/plugin-stackstorm", + "description": "A Backstage plugin that integrates towards StackStorm", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/stackstorm" + }, + "keywords": [ + "backstage", + "stackstorm", + "st2" + ], + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/theme": "workspace:^", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "^4.0.0-alpha.57", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^0.49.0" + }, + "files": [ + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/stackstorm/src/api/StackStormClient.ts b/plugins/stackstorm/src/api/StackStormClient.ts new file mode 100644 index 0000000000..c93901ce43 --- /dev/null +++ b/plugins/stackstorm/src/api/StackStormClient.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Action, Execution, Pack, StackStormApi } from './types'; +import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; + +export class StackStormClient implements StackStormApi { + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + + constructor({ + discoveryApi, + identityApi, + }: { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + }) { + this.discoveryApi = discoveryApi; + this.identityApi = identityApi; + } + + private async get(input: string): Promise { + const { token: idToken } = await this.identityApi.getCredentials(); + const apiUrl = `${await this.discoveryApi.getBaseUrl('proxy')}/stackstorm`; + const response = await fetch(`${apiUrl}${input}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + ...(idToken && { Authorization: `Bearer ${idToken}` }), + }, + }); + + if (!response.ok) throw new Error(`Unable to get data: ${response.status}`); + return await response.json(); + } + + async getExecutions(limit?: number, offset?: number): Promise { + const params = { + limit: limit?.toString() || '25', + offset: offset?.toString() || '0', + include_attributes: + 'id,status,start_timestamp,action.ref,action.name,rule.ref', + parent: 'null', + }; + const path = `/executions?${new URLSearchParams(params)}`; + return this.get(path); + } + + async getExecution(id: string): Promise { + const path = `/executions/${id}`; + return this.get(path); + } + + async getPacks(): Promise { + return this.get('/packs'); + } + + async getActions(pack: string): Promise { + const params = { + include_attributes: 'id,ref,name,pack,description,runner_type', + pack: pack, + }; + const path = `/actions?${new URLSearchParams(params)}`; + return this.get(path); + } +} diff --git a/plugins/stackstorm/src/api/index.ts b/plugins/stackstorm/src/api/index.ts new file mode 100644 index 0000000000..2291fb1f73 --- /dev/null +++ b/plugins/stackstorm/src/api/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { stackStormApiRef } from './types'; +export type { + Action, + Execution, + ExecutionLog, + Pack, + StackStormApi, +} from './types'; +export { StackStormClient } from './StackStormClient'; diff --git a/plugins/stackstorm/src/api/types.ts b/plugins/stackstorm/src/api/types.ts new file mode 100644 index 0000000000..8a3036d3ca --- /dev/null +++ b/plugins/stackstorm/src/api/types.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createApiRef } from '@backstage/core-plugin-api'; + +export const stackStormApiRef = createApiRef({ + id: 'plugin.stackstorm.service', +}); + +export type Execution = { + id: string; + action: Action; + status: string; + start_timestamp: Date; + end_timestamp: Date; + result: object; + parameters: object; + elapsed_seconds: number; + log: ExecutionLog[]; +}; + +export type ExecutionLog = { + status: string; + timestamp: Date; +}; + +export type Action = { + id: string; + name: string; + ref: string; + pack: string; + description: string; + runner_type: string; +}; + +export type Pack = { + ref: string; + description: string; + version: string; +}; + +export interface StackStormApi { + getExecutions(limit: number, offset: number): Promise; + getExecution(id: string): Promise; + getPacks(): Promise; + getActions(pack: string): Promise; +} diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx new file mode 100644 index 0000000000..014e8c31a3 --- /dev/null +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx @@ -0,0 +1,161 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import { Progress } from '@backstage/core-components'; +import { useApi, configApiRef } from '@backstage/core-plugin-api'; +import { + List, + ListItemText, + Collapse, + ListItem, + ListItemSecondaryAction, + ListItemIcon, +} from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import ExpandMore from '@material-ui/icons/ExpandMore'; +import ExpandLess from '@material-ui/icons/ExpandLess'; +import { Alert } from '@material-ui/lab'; +import { Action, Pack, stackStormApiRef } from '../../api'; + +const useStyles = makeStyles(theme => ({ + root: { + width: '100%', + backgroundColor: theme.palette.background.paper, + }, + actions: { + borderBottom: `2px solid ${theme.palette.divider}`, + }, + nested: { + paddingLeft: theme.spacing(8), + paddingRight: theme.spacing(4), + }, + icon: { + minWidth: '34px', + }, +})); + +type ActionItemsProps = { + pack: Pack; +}; + +export const ActionItems = ({ pack }: ActionItemsProps) => { + const classes = useStyles(); + const st2 = useApi(stackStormApiRef); + const config = useApi(configApiRef); + + const { value, loading, error } = useAsync(async (): Promise => { + const data = await st2.getActions(pack.ref); + return data; + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + return ( + + {(value || []).map(a => { + return ( + + window.open( + `${config.getString('stackstorm.webUrl')}/?#/actions/${a.ref}`, + '_blank', + ) + } + > + + {a.runner_type} + + ); + })} + + ); +}; + +type PackListItemProps = { + pack: Pack; + opened: boolean; + onClick: (ref: string) => any; +}; + +export const PackListItem = ({ pack, opened, onClick }: PackListItemProps) => { + const classes = useStyles(); + + return ( + <> + onClick(pack.ref)}> + + {opened ? : } + + + + version: {pack.version} + + + + + + + ); +}; + +export const ActionsList = () => { + const st2 = useApi(stackStormApiRef); + + const classes = useStyles(); + const [expanded, setExpanded] = useState([]); + + const onClick = (ref: string) => { + setExpanded(refs => + refs.includes(ref) ? refs.filter(r => r !== ref) : refs.concat(ref), + ); + }; + + const { value, loading, error } = useAsync(async (): Promise => { + const data = await st2.getPacks(); + return data; + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + return ( + + {(value || []).map(p => { + return ( + + ); + })} + + ); +}; diff --git a/plugins/stackstorm/src/components/ActionsList/index.ts b/plugins/stackstorm/src/components/ActionsList/index.ts new file mode 100644 index 0000000000..1606d1be3d --- /dev/null +++ b/plugins/stackstorm/src/components/ActionsList/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { ActionsList } from './ActionsList'; diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx new file mode 100644 index 0000000000..76f11aaf73 --- /dev/null +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx @@ -0,0 +1,165 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { CodeSnippet, Progress } from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { Execution, stackStormApiRef } from '../../api'; +import useAsync from 'react-use/lib/useAsync'; +import { Alert } from '@material-ui/lab'; +import { + Button, + Card, + CardActions, + CardContent, + makeStyles, + Table, + TableBody, + TableCell, + TableRow, + Typography, + withStyles, +} from '@material-ui/core'; +import { Status } from './Status'; + +const useStyles = makeStyles(theme => ({ + table: { + maxWidth: '50%', + flex: 'i', + }, + title: { + paddingTop: theme.spacing(2), + fontSize: 14, + fontWeight: 'bold', + textTransform: 'uppercase', + }, + card: { + borderBottom: `2px solid ${theme.palette.divider}`, + }, +})); + +const THead = withStyles(() => ({ + root: { + paddingLeft: 0, + }, +}))(TableCell); + +const TRow = withStyles(theme => ({ + root: { + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.background.paper, + }, + }, +}))(TableRow); + +const ExecutionCard = ({ e }: { e: Execution }) => { + const config = useApi(configApiRef); + const classes = useStyles(); + + const webUrl = `${config.getString('stackstorm.webUrl')}/?#/history/${e.id}`; + + return ( + + + + + + + Name + + {e.action.ref} + + + + Status + + + + + + + + Execution ID + + {e.id} + + + + Started + + {new Date(e.start_timestamp).toUTCString()} + + + + Finished + + {new Date(e.end_timestamp).toUTCString()} + + + + Execution Time + + {Math.round(e.elapsed_seconds)} s + + + + Runner + + {e.action.runner_type} + + +
+ + Action Output + + + + Action Input + + +
+ + + +
+ ); +}; + +export const ExecutionPanel = ({ id }: { id: string }) => { + const st2 = useApi(stackStormApiRef); + + const { value, loading, error } = useAsync(async (): Promise => { + const data = await st2.getExecution(id); + return data; + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + return ; +}; diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx new file mode 100644 index 0000000000..4dbd64399f --- /dev/null +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx @@ -0,0 +1,130 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { useEffect, useState } from 'react'; +import { Link, Table, TableColumn } from '@backstage/core-components'; +import { useApi, configApiRef, errorApiRef } from '@backstage/core-plugin-api'; +import { Execution, stackStormApiRef } from '../../api'; +import { Status } from './Status'; +import { ExecutionPanel } from './ExecutionPanel'; + +type DenseTableProps = { + executions: Execution[]; + loading: boolean; + page: number; + pageSize: number; + onPageChange: (page: number) => void; + onRowsPerPageChange: (rows: number) => void; +}; + +export const DenseTable = ({ + executions, + loading, + page, + pageSize, + onPageChange, + onRowsPerPageChange, +}: DenseTableProps) => { + const config = useApi(configApiRef); + + const columns: TableColumn[] = [ + { + title: 'Status', + field: 'status', + render: e => , + }, + { + title: 'Time', + field: 'start_timestamp', + render: e => `${new Date(e.start_timestamp).toUTCString()}`, + }, + { title: 'Name', field: 'action.ref' }, + { + title: 'Execution ID', + field: 'id', + render: e => ( + + {e.id} + + ), + }, + ]; + + const count = + pageSize > executions.length + ? (page + 1) * pageSize + executions.length - pageSize + : (page + 1) * pageSize + 1; + + return ( + { + return ; + }} + /> + ); +}; + +export const ExecutionsTable = () => { + const st2 = useApi(stackStormApiRef); + const errorApi = useApi(errorApiRef); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(10); + const [data, setData] = useState([]); + const [loading, setLoading] = useState(false); + + useEffect(() => { + const getData = async () => { + setLoading(true); + await st2 + .getExecutions(rowsPerPage, page * rowsPerPage) + .then(d => { + setData(d); + }) + .catch(err => { + errorApi.post(err); + }); + setLoading(false); + }; + getData(); + }, [errorApi, page, rowsPerPage, st2]); + + return ( + + ); +}; diff --git a/plugins/stackstorm/src/components/ExecutionsTable/Status.tsx b/plugins/stackstorm/src/components/ExecutionsTable/Status.tsx new file mode 100644 index 0000000000..99a94df2c8 --- /dev/null +++ b/plugins/stackstorm/src/components/ExecutionsTable/Status.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + StatusOK, + StatusError, + StatusRunning, + StatusWarning, +} from '@backstage/core-components'; +import React from 'react'; + +export const Status = ({ status }: { status: string | undefined }) => { + if (status === undefined) return null; + const st = status.toLocaleLowerCase('en-US'); + switch (status) { + case 'succeeded': + case 'enabled': + case 'complete': + return ( + <> + {st} + + ); + case 'scheduled': + case 'running': + return ( + <> + {st} + + ); + case 'failed': + case 'error': + return ( + <> + {st} + + ); + default: + return ( + <> + {st} + + ); + } +}; diff --git a/plugins/stackstorm/src/components/ExecutionsTable/index.ts b/plugins/stackstorm/src/components/ExecutionsTable/index.ts new file mode 100644 index 0000000000..402d8e557d --- /dev/null +++ b/plugins/stackstorm/src/components/ExecutionsTable/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { ExecutionsTable } from './ExecutionsTable'; diff --git a/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx new file mode 100644 index 0000000000..b150aeec4d --- /dev/null +++ b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx @@ -0,0 +1,59 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { Progress, Table, TableColumn } from '@backstage/core-components'; +import { Alert } from '@material-ui/lab'; +import useAsync from 'react-use/lib/useAsync'; +import { useApi } from '@backstage/core-plugin-api'; +import { Pack, stackStormApiRef } from '../../api'; + +type DenseTableProps = { + packs: Pack[]; +}; + +export const DenseTable = ({ packs }: DenseTableProps) => { + const columns: TableColumn[] = [ + { title: 'Name', field: 'ref' }, + { title: 'Description', field: 'description' }, + { title: 'Version', field: 'version' }, + ]; + + return ( +
+ ); +}; + +export const PacksTable = () => { + const st2 = useApi(stackStormApiRef); + + const { value, loading, error } = useAsync(async (): Promise => { + const data = await st2.getPacks(); + return data; + }, []); + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + return ; +}; diff --git a/plugins/stackstorm/src/components/PacksTable/index.ts b/plugins/stackstorm/src/components/PacksTable/index.ts new file mode 100644 index 0000000000..378e32a5d5 --- /dev/null +++ b/plugins/stackstorm/src/components/PacksTable/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { PacksTable } from './PacksTable'; diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx new file mode 100644 index 0000000000..6249fa71e8 --- /dev/null +++ b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx @@ -0,0 +1,38 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { StackStormHome } from './StackStormHome'; +import { screen } from '@testing-library/react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { StackStormApi, stackStormApiRef } from '../../api'; + +describe('StackStormHome', () => { + const mockApi: jest.Mocked = { + getExecutions: jest.fn().mockResolvedValue([]), + getExecution: jest.fn().mockResolvedValue({}), + getPacks: jest.fn().mockResolvedValue([]), + getActions: jest.fn().mockResolvedValue([]), + } as any; + + it('should render', async () => { + await renderInTestApp( + + + , + ); + expect(screen.getByText('Welcome to StackStorm!')).toBeInTheDocument(); + }); +}); diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx new file mode 100644 index 0000000000..a059505c2b --- /dev/null +++ b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { Grid, IconButton } from '@material-ui/core'; +import { + Header, + Page, + HeaderLabel, + TabbedLayout, + Content, +} from '@backstage/core-components'; +import LibraryBooks from '@material-ui/icons/LibraryBooks'; +import { ExecutionsTable } from '../ExecutionsTable'; +import { PacksTable } from '../PacksTable/PacksTable'; +import { ActionsList } from '../ActionsList'; + +export const StackStormHome = () => ( + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+); diff --git a/plugins/stackstorm/src/components/StackStormHome/index.ts b/plugins/stackstorm/src/components/StackStormHome/index.ts new file mode 100644 index 0000000000..27c6db48ab --- /dev/null +++ b/plugins/stackstorm/src/components/StackStormHome/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { StackStormHome } from './StackStormHome'; diff --git a/plugins/stackstorm/src/index.ts b/plugins/stackstorm/src/index.ts new file mode 100644 index 0000000000..aff9e2d78a --- /dev/null +++ b/plugins/stackstorm/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { stackstormPlugin, StackstormPage } from './plugin'; diff --git a/plugins/stackstorm/src/plugin.test.ts b/plugins/stackstorm/src/plugin.test.ts new file mode 100644 index 0000000000..9ef2f438c1 --- /dev/null +++ b/plugins/stackstorm/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { stackstormPlugin } from './plugin'; + +describe('stackstorm', () => { + it('should export plugin', () => { + expect(stackstormPlugin).toBeDefined(); + }); +}); diff --git a/plugins/stackstorm/src/plugin.ts b/plugins/stackstorm/src/plugin.ts new file mode 100644 index 0000000000..012c78372b --- /dev/null +++ b/plugins/stackstorm/src/plugin.ts @@ -0,0 +1,55 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + createApiFactory, + createPlugin, + createRoutableExtension, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { stackStormApiRef, StackStormClient } from './api'; + +import { rootRouteRef } from './routes'; + +export const stackstormPlugin = createPlugin({ + id: 'stackstorm', + apis: [ + createApiFactory({ + api: stackStormApiRef, + deps: { + discoveryApi: discoveryApiRef, + identityApi: identityApiRef, + }, + factory: ({ discoveryApi, identityApi }) => + new StackStormClient({ + discoveryApi, + identityApi, + }), + }), + ], + routes: { + root: rootRouteRef, + }, +}); + +export const StackstormPage = stackstormPlugin.provide( + createRoutableExtension({ + name: 'StackstormPage', + component: () => + import('./components/StackStormHome').then(m => m.StackStormHome), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/stackstorm/src/routes.ts b/plugins/stackstorm/src/routes.ts new file mode 100644 index 0000000000..90cf7760bc --- /dev/null +++ b/plugins/stackstorm/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'stackstorm', +}); diff --git a/plugins/stackstorm/src/setupTests.ts b/plugins/stackstorm/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/stackstorm/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/yarn.lock b/yarn.lock index 4e56cb9839..5c8cdcad98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7955,6 +7955,32 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-stackstorm@workspace:^, @backstage/plugin-stackstorm@workspace:plugins/stackstorm": + version: 0.0.0-use.local + resolution: "@backstage/plugin-stackstorm@workspace:plugins/stackstorm" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": ^4.0.0-alpha.57 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + msw: ^0.49.0 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-tech-insights-backend-module-jsonfc@workspace:^, @backstage/plugin-tech-insights-backend-module-jsonfc@workspace:plugins/tech-insights-backend-module-jsonfc": version: 0.0.0-use.local resolution: "@backstage/plugin-tech-insights-backend-module-jsonfc@workspace:plugins/tech-insights-backend-module-jsonfc" @@ -22492,6 +22518,7 @@ __metadata: "@backstage/plugin-sentry": "workspace:^" "@backstage/plugin-shortcuts": "workspace:^" "@backstage/plugin-stack-overflow": "workspace:^" + "@backstage/plugin-stackstorm": "workspace:^" "@backstage/plugin-tech-insights": "workspace:^" "@backstage/plugin-tech-radar": "workspace:^" "@backstage/plugin-techdocs": "workspace:^" From 6c70919f1ad6412d1d7f8bba5e20a184428c965c Mon Sep 17 00:00:00 2001 From: Christopher Kruse Date: Mon, 30 Jan 2023 10:58:49 -0800 Subject: [PATCH 045/417] fix: better error around github teams not found Adds a literate error around the `createGithubRepoWithCollaboratorsAndTopics` function in order to provide that error in the scaffolder logs. Prior to this, the only thing returned was "Not Found," which didn't provide much information for someone trying to determine what failed in the background. Fixes #10160 Signed-off-by: Christopher Kruse --- .changeset/olive-ads-peel.md | 5 ++++ .../actions/builtin/github/helpers.ts | 23 +++++++++++------ .../actions/builtin/publish/github.test.ts | 25 +++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 .changeset/olive-ads-peel.md diff --git a/.changeset/olive-ads-peel.md b/.changeset/olive-ads-peel.md new file mode 100644 index 0000000000..7a7c73ddb7 --- /dev/null +++ b/.changeset/olive-ads-peel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Provide better error messaging when GitHub fails due to missing team definitions diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts index dae5e16374..25f343da9e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts @@ -190,13 +190,22 @@ export async function createGithubRepoWithCollaboratorsAndTopics( if (access?.startsWith(`${owner}/`)) { const [, team] = access.split('/'); - await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: team, - owner, - repo, - permission: 'admin', - }); + try { + await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ + org: owner, + team_slug: team, + owner, + repo, + permission: 'admin', + }); + } catch (e) { + if (e.data.message === 'Not Found') { + const message = `Received 'Not Found' from the API; one of org: + ${owner}, team: ${team} or repo: ${repo} was not found within GitHub.`; + logger.warn(message); + throw new Error(message, { cause: e }); + } + } // No need to add access if it's the person who owns the personal account } else if (access && access !== owner) { await client.rest.repos.addCollaborator({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 8ead489ea4..0edeafecfd 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -518,6 +518,31 @@ describe('publish:github', () => { }); }); + it('should provide an adequate failure message when adding access', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg.mockRejectedValue({ + status: 404, + data: { + message: 'Not Found', + documentation_url: + 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + }, + }); + await expect(action.handler(mockContext)).rejects.toThrow( + "Received 'Not Found' from the API;", + ); + }); + it('should add outside collaborators when provided', async () => { mockOctokit.rest.users.getByUsername.mockResolvedValue({ data: { type: 'User' }, From 8cd21b9b596f78758c46a249fd8fde979390c4d2 Mon Sep 17 00:00:00 2001 From: Christopher Kruse Date: Thu, 2 Feb 2023 11:40:44 -0800 Subject: [PATCH 046/417] fix: check for teams before creating repository Shifts the team check for the 'access' parameter to happen prior to the repo creation, so that repositories are not created and have no permissions set on them due to missing teams. Signed-off-by: Christopher Kruse --- .../builtin/github/githubRepoCreate.test.ts | 8 +++ .../actions/builtin/github/helpers.ts | 46 +++++++++------ .../actions/builtin/publish/github.test.ts | 56 ++++++++++++++----- 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts index f15747fd6b..a9ef8c3daa 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubRepoCreate.test.ts @@ -42,6 +42,7 @@ const mockOctokit = { }, teams: { addOrUpdateRepoPermissionsInOrg: jest.fn(), + getByName: jest.fn(), }, }, }; @@ -96,6 +97,13 @@ describe('github:repo:create', () => { data: { type: 'Organization' }, }); + mockOctokit.rest.teams.getByName.mockResolvedValue({ + data: { + name: 'blam', + id: 42, + }, + }); + mockOctokit.rest.repos.createInOrg.mockResolvedValue({ data: {} }); await action.handler(mockContext); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts index 25f343da9e..dc8c4cd856 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts @@ -135,6 +135,10 @@ export async function createGithubRepoWithCollaboratorsAndTopics( username: owner, }); + if (access?.startsWith(`${owner}/`)) { + await validateAccessTeam(client, access); + } + const repoCreationPromise = user.data.type === 'Organization' ? client.rest.repos.createInOrg({ @@ -190,22 +194,13 @@ export async function createGithubRepoWithCollaboratorsAndTopics( if (access?.startsWith(`${owner}/`)) { const [, team] = access.split('/'); - try { - await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: team, - owner, - repo, - permission: 'admin', - }); - } catch (e) { - if (e.data.message === 'Not Found') { - const message = `Received 'Not Found' from the API; one of org: - ${owner}, team: ${team} or repo: ${repo} was not found within GitHub.`; - logger.warn(message); - throw new Error(message, { cause: e }); - } - } + await client.rest.teams.addOrUpdateRepoPermissionsInOrg({ + org: owner, + team_slug: team, + owner, + repo, + permission: 'admin', + }); // No need to add access if it's the person who owns the personal account } else if (access && access !== owner) { await client.rest.repos.addCollaborator({ @@ -360,3 +355,22 @@ function extractCollaboratorName( if ('user' in collaborator) return collaborator.user; return collaborator.team; } + +async function validateAccessTeam(client: Octokit, access: string) { + const [org, team_slug] = access.split('/'); + try { + // Below rule disabled because of a 'getByName' check for a different library + // incorrectly triggers here. + // eslint-disable-next-line testing-library/no-await-sync-query + await client.rest.teams.getByName({ + org, + team_slug, + }); + } catch (e) { + if (e.response.data.message === 'Not Found') { + const message = `Received 'Not Found' from the API; one of org: + ${org} or team: ${team_slug} was not found within GitHub.`; + throw new Error(message, { cause: e }); + } + } +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 0edeafecfd..94b51f3e94 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -45,6 +45,7 @@ const mockOctokit = { replaceAllTopics: jest.fn(), }, teams: { + getByName: jest.fn(), addOrUpdateRepoPermissionsInOrg: jest.fn(), }, }, @@ -96,11 +97,41 @@ describe('publish:github', () => { }); }); + it('should fail to create if the team is not found in the org', async () => { + mockOctokit.rest.users.getByUsername.mockResolvedValue({ + data: { type: 'Organization' }, + }); + + mockOctokit.rest.teams.getByName.mockRejectedValue({ + response: { + status: 404, + data: { + message: 'Not Found', + documentation_url: + 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + }, + }, + }); + + await expect(action.handler(mockContext)).rejects.toThrow( + "Received 'Not Found' from the API;", + ); + + expect(mockOctokit.rest.repos.createInOrg).not.toHaveBeenCalled(); + }); + it('should call the githubApis with the correct values for createInOrg', async () => { mockOctokit.rest.users.getByUsername.mockResolvedValue({ data: { type: 'Organization' }, }); + mockOctokit.rest.teams.getByName.mockResolvedValue({ + data: { + name: 'blam', + id: 42, + }, + }); + mockOctokit.rest.repos.createInOrg.mockResolvedValue({ data: {} }); await action.handler(mockContext); @@ -523,24 +554,23 @@ describe('publish:github', () => { data: { type: 'User' }, }); - mockOctokit.rest.repos.createForAuthenticatedUser.mockResolvedValue({ - data: { - clone_url: 'https://github.com/clone/url.git', - html_url: 'https://github.com/html/url', - }, - }); - - mockOctokit.rest.teams.addOrUpdateRepoPermissionsInOrg.mockRejectedValue({ - status: 404, - data: { - message: 'Not Found', - documentation_url: - 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + mockOctokit.rest.teams.getByName.mockRejectedValue({ + response: { + status: 404, + data: { + message: 'Not Found', + documentation_url: + 'https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions', + }, }, }); await expect(action.handler(mockContext)).rejects.toThrow( "Received 'Not Found' from the API;", ); + + expect( + mockOctokit.rest.repos.createForAuthenticatedUser, + ).not.toHaveBeenCalled(); }); it('should add outside collaborators when provided', async () => { From 5044821cb13e582b8e65b80fcea5b6395ce995ea Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 00:38:05 +0100 Subject: [PATCH 047/417] catalog-client: rename query entities request utilities Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/src/CatalogClient.ts | 4 ++-- packages/catalog-client/src/utils.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index adf23f861c..389f109989 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -45,7 +45,7 @@ import { } from './types/api'; import { DiscoveryApi } from './types/discovery'; import { FetchApi } from './types/fetch'; -import { isPaginatedEntitiesInitialRequest } from './utils'; +import { isQueryEntitiesInitialRequest } from './utils'; /** * A frontend and backend compatible client for communicating with the Backstage @@ -213,7 +213,7 @@ export class CatalogClient implements CatalogApi { ): Promise { const params: string[] = []; - if (isPaginatedEntitiesInitialRequest(request)) { + if (isQueryEntitiesInitialRequest(request)) { const { fields = [], filter, limit, sortFields, query } = request; params.push(...this.getParams(filter)); diff --git a/packages/catalog-client/src/utils.ts b/packages/catalog-client/src/utils.ts index d6131b79d2..de21cea0d4 100644 --- a/packages/catalog-client/src/utils.ts +++ b/packages/catalog-client/src/utils.ts @@ -20,14 +20,14 @@ import { QueryEntitiesRequest, } from './types/api'; -export function isPaginatedEntitiesInitialRequest( +export function isQueryEntitiesInitialRequest( request: QueryEntitiesInitialRequest, ): request is QueryEntitiesInitialRequest { return !(request as QueryEntitiesCursorRequest).cursor; } -export function isPaginatedEntitiesCursorRequest( +export function isQueryEntitiesCursorRequest( request: QueryEntitiesRequest, ): request is QueryEntitiesCursorRequest { - return !isPaginatedEntitiesInitialRequest(request); + return !isQueryEntitiesInitialRequest(request); } From 9ccbf8a08dc5cc20af0ad05e78921d9d51f0ce16 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 00:39:03 +0100 Subject: [PATCH 048/417] catalog-backend: rename paginatedEntities to queryEntities Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 24 ++-- .../service/AuthorizedEntitiesCatalog.test.ts | 2 +- .../src/service/AuthorizedEntitiesCatalog.ts | 18 +-- .../service/DefaultEntitiesCatalog.test.ts | 130 +++++++++--------- .../src/service/DefaultEntitiesCatalog.ts | 20 +-- .../src/service/createRouter.test.ts | 20 +-- .../src/service/createRouter.ts | 6 +- .../src/service/request/index.ts | 2 +- ...st.ts => parseQueryEntitiesParams.test.ts} | 32 ++--- ...sParams.ts => parseQueryEntitiesParams.ts} | 36 +++-- plugins/catalog-backend/src/service/util.ts | 22 +-- 11 files changed, 154 insertions(+), 158 deletions(-) rename plugins/catalog-backend/src/service/request/{parsePaginatedEntitiesParams.test.ts => parseQueryEntitiesParams.test.ts} (81%) rename plugins/catalog-backend/src/service/request/{parsePaginatedEntitiesParams.ts => parseQueryEntitiesParams.ts} (74%) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 451f757e65..93720e5a68 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -179,9 +179,7 @@ export interface EntitiesCatalog { * * @param request */ - paginatedEntities( - request?: PaginatedEntitiesRequest, - ): Promise; + queryEntities(request?: QueryEntitiesRequest): Promise; /** * Removes a single entity. @@ -213,18 +211,18 @@ export interface EntitiesCatalog { } /** - * The request shape for {@link EntitiesCatalog.paginatedEntities}. + * The request shape for {@link EntitiesCatalog.queryEntities}. */ -export type PaginatedEntitiesRequest = - | PaginatedEntitiesInitialRequest - | PaginatedEntitiesCursorRequest; +export type QueryEntitiesRequest = + | QueryEntitiesInitialRequest + | QueryEntitiesCursorRequest; /** - * The initial request for {@link EntitiesCatalog.paginatedEntities}. + * The initial request for {@link EntitiesCatalog.queryEntities}. * The request take immutable properties that are going to be bound * for the current and the next pagination requests. */ -export interface PaginatedEntitiesInitialRequest { +export interface QueryEntitiesInitialRequest { authorizationToken?: string; fields?: (entity: Entity) => Entity; limit?: number; @@ -234,10 +232,10 @@ export interface PaginatedEntitiesInitialRequest { } /** - * Request for {@link EntitiesCatalog.paginatedEntities} used to + * Request for {@link EntitiesCatalog.queryEntities} used to * move forward or backward on the data. */ -export interface PaginatedEntitiesCursorRequest { +export interface QueryEntitiesCursorRequest { authorizationToken?: string; fields?: (entity: Entity) => Entity; limit?: number; @@ -245,9 +243,9 @@ export interface PaginatedEntitiesCursorRequest { } /** - * The response shape for {@link EntitiesCatalog.paginatedEntities}. + * The response shape for {@link EntitiesCatalog.queryEntities}. */ -export interface PaginatedEntitiesResponse { +export interface QueryEntitiesResponse { /** * The entities for the current pagination request */ diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts index 8ee10fdbcb..e559f5fd49 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts @@ -30,7 +30,7 @@ describe('AuthorizedEntitiesCatalog', () => { facets: jest.fn(), refresh: jest.fn(), listAncestors: jest.fn(), - paginatedEntities: jest.fn(), + queryEntities: jest.fn(), }; const fakePermissionApi = { authorize: jest.fn(), diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index 5ae31158f8..2a5388c3d5 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -35,11 +35,11 @@ import { EntityFacetsRequest, EntityFacetsResponse, EntityFilter, - PaginatedEntitiesRequest, - PaginatedEntitiesResponse, + QueryEntitiesRequest, + QueryEntitiesResponse, } from '../catalog/types'; import { basicEntityFilter } from './request/basicEntityFilter'; -import { isPaginatedEntitiesInitialRequest } from './util'; +import { isQueryEntitiesInitialRequest } from './util'; export class AuthorizedEntitiesCatalog implements EntitiesCatalog { constructor( @@ -109,9 +109,9 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { return this.entitiesCatalog.entitiesBatch(request); } - async paginatedEntities( - request?: PaginatedEntitiesRequest, - ): Promise { + async queryEntities( + request?: QueryEntitiesRequest, + ): Promise { const authorizeDecision = ( await this.permissionApi.authorizeConditional( [{ permission: catalogEntityReadPermission }], @@ -131,9 +131,9 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { authorizeDecision.conditions, ); - return this.entitiesCatalog.paginatedEntities({ + return this.entitiesCatalog.queryEntities({ ...request, - ...(isPaginatedEntitiesInitialRequest(request) && { + ...(isQueryEntitiesInitialRequest(request) && { filter: request?.filter ? { allOf: [permissionFilter, request.filter] } : permissionFilter, @@ -141,7 +141,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { }); } - return this.entitiesCatalog.paginatedEntities(request); + return this.entitiesCatalog.queryEntities(request); } async removeEntityByUid( diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index a25cbf2240..92b2ecb3c5 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -20,8 +20,8 @@ import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { v4 as uuid, v4 } from 'uuid'; import { - PaginatedEntitiesCursorRequest, - PaginatedEntitiesInitialRequest, + QueryEntitiesCursorRequest, + QueryEntitiesInitialRequest, } from '../catalog/types'; import { applyDatabaseMigrations } from '../database/migrations'; import { @@ -723,7 +723,7 @@ describe('DefaultEntitiesCatalog', () => { ); }); - describe('paginatedEntities', () => { + describe('queryEntities', () => { it.each(databases.eachSupportedId())( 'should return paginated entities and scroll the items accordingly, %p', async databaseId => { @@ -764,89 +764,89 @@ describe('DefaultEntitiesCatalog', () => { const limit = 2; // initial request - const request1: PaginatedEntitiesInitialRequest = { + const request1: QueryEntitiesInitialRequest = { filter, limit, sortFields: [{ field: 'metadata.name', order: 'asc' }], }; - const response1 = await catalog.paginatedEntities(request1); + const response1 = await catalog.queryEntities(request1); expect(response1.entities).toEqual([entityFrom('A'), entityFrom('B')]); expect(response1.nextCursor).toBeDefined(); expect(response1.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(names.length); // second request (forward) - const request2: PaginatedEntitiesCursorRequest = { + const request2: QueryEntitiesCursorRequest = { cursor: response1.nextCursor!, limit, }; - const response2 = await catalog.paginatedEntities(request2); + const response2 = await catalog.queryEntities(request2); expect(response2.entities).toEqual([entityFrom('C'), entityFrom('D')]); expect(response2.nextCursor).toBeDefined(); expect(response2.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(names.length); // third request (forward) - const request3: PaginatedEntitiesCursorRequest = { + const request3: QueryEntitiesCursorRequest = { cursor: response2.nextCursor!, limit, }; - const response3 = await catalog.paginatedEntities(request3); + const response3 = await catalog.queryEntities(request3); expect(response3.entities).toEqual([entityFrom('E'), entityFrom('F')]); expect(response3.nextCursor).toBeDefined(); expect(response3.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(names.length); // fourth request (backwards) - const request4: PaginatedEntitiesCursorRequest = { + const request4: QueryEntitiesCursorRequest = { cursor: response3.prevCursor!, limit, }; - const response4 = await catalog.paginatedEntities(request4); + const response4 = await catalog.queryEntities(request4); expect(response4.entities).toEqual([entityFrom('C'), entityFrom('D')]); expect(response4.nextCursor).toBeDefined(); expect(response4.prevCursor).toBeDefined(); expect(response4.totalItems).toBe(names.length); // fifth request (backwards) - const request5: PaginatedEntitiesCursorRequest = { + const request5: QueryEntitiesCursorRequest = { cursor: response4.prevCursor!, limit, }; - const response5 = await catalog.paginatedEntities(request5); + const response5 = await catalog.queryEntities(request5); expect(response5.entities).toEqual([entityFrom('A'), entityFrom('B')]); expect(response5.nextCursor).toBeDefined(); expect(response5.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(names.length); // sixth request (forward) - const request6: PaginatedEntitiesCursorRequest = { + const request6: QueryEntitiesCursorRequest = { cursor: response5.nextCursor!, limit, }; - const response6 = await catalog.paginatedEntities(request6); + const response6 = await catalog.queryEntities(request6); expect(response6.entities).toEqual([entityFrom('C'), entityFrom('D')]); expect(response6.nextCursor).toBeDefined(); expect(response6.prevCursor).toBeDefined(); expect(response6.totalItems).toBe(names.length); // seventh request (forward) - const request7: PaginatedEntitiesCursorRequest = { + const request7: QueryEntitiesCursorRequest = { cursor: response6.nextCursor!, limit, }; - const response7 = await catalog.paginatedEntities(request7); + const response7 = await catalog.queryEntities(request7); expect(response7.entities).toEqual([entityFrom('E'), entityFrom('F')]); expect(response7.nextCursor).toBeDefined(); expect(response7.prevCursor).toBeDefined(); expect(response7.totalItems).toBe(names.length); // seventh.2 request (forward with a different limit) - const request7bis: PaginatedEntitiesCursorRequest = { + const request7bis: QueryEntitiesCursorRequest = { cursor: response6.nextCursor!, limit: limit + 1, }; - const response7bis = await catalog.paginatedEntities(request7bis); + const response7bis = await catalog.queryEntities(request7bis); expect(response7bis.entities).toEqual([ entityFrom('E'), entityFrom('F'), @@ -857,11 +857,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response7bis.totalItems).toBe(names.length); // last request (forward) - const request8: PaginatedEntitiesCursorRequest = { + const request8: QueryEntitiesCursorRequest = { cursor: response7.nextCursor!, limit, }; - const response8 = await catalog.paginatedEntities(request8); + const response8 = await catalog.queryEntities(request8); expect(response8.entities).toEqual([entityFrom('G')]); expect(response8.nextCursor).toBeUndefined(); expect(response8.prevCursor).toBeDefined(); @@ -909,45 +909,45 @@ describe('DefaultEntitiesCatalog', () => { const limit = 2; // initial request - const request1: PaginatedEntitiesInitialRequest = { + const request1: QueryEntitiesInitialRequest = { filter, limit, sortFields: [{ field: 'metadata.name', order: 'desc' }], }; - const response1 = await catalog.paginatedEntities(request1); + const response1 = await catalog.queryEntities(request1); expect(response1.entities).toEqual([entityFrom('G'), entityFrom('F')]); expect(response1.nextCursor).toBeDefined(); expect(response1.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(names.length); // second request (forward) - const request2: PaginatedEntitiesCursorRequest = { + const request2: QueryEntitiesCursorRequest = { cursor: response1.nextCursor!, limit, }; - const response2 = await catalog.paginatedEntities(request2); + const response2 = await catalog.queryEntities(request2); expect(response2.entities).toEqual([entityFrom('E'), entityFrom('D')]); expect(response2.nextCursor).toBeDefined(); expect(response2.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(names.length); // third request (forward) - const request3: PaginatedEntitiesCursorRequest = { + const request3: QueryEntitiesCursorRequest = { cursor: response2.nextCursor!, limit, }; - const response3 = await catalog.paginatedEntities(request3); + const response3 = await catalog.queryEntities(request3); expect(response3.entities).toEqual([entityFrom('C'), entityFrom('B')]); expect(response3.nextCursor).toBeDefined(); expect(response3.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(names.length); // fourth request (backwards) - const request4: PaginatedEntitiesCursorRequest = { + const request4: QueryEntitiesCursorRequest = { cursor: response3.prevCursor!, limit, }; - const response4 = await catalog.paginatedEntities(request4); + const response4 = await catalog.queryEntities(request4); expect(response4.entities).toEqual([entityFrom('E'), entityFrom('D')]); expect(response4.nextCursor).toBeDefined(); @@ -955,44 +955,44 @@ describe('DefaultEntitiesCatalog', () => { expect(response4.totalItems).toBe(names.length); // fifth request (backwards) - const request5: PaginatedEntitiesCursorRequest = { + const request5: QueryEntitiesCursorRequest = { cursor: response4.prevCursor!, limit, }; - const response5 = await catalog.paginatedEntities(request5); + const response5 = await catalog.queryEntities(request5); expect(response5.entities).toEqual([entityFrom('G'), entityFrom('F')]); expect(response5.nextCursor).toBeDefined(); expect(response5.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(names.length); // sixth request (forward) - const request6: PaginatedEntitiesCursorRequest = { + const request6: QueryEntitiesCursorRequest = { cursor: response5.nextCursor!, limit, }; - const response6 = await catalog.paginatedEntities(request6); + const response6 = await catalog.queryEntities(request6); expect(response6.entities).toEqual([entityFrom('E'), entityFrom('D')]); expect(response6.nextCursor).toBeDefined(); expect(response6.prevCursor).toBeDefined(); expect(response6.totalItems).toBe(names.length); // seventh request (forward) - const request7: PaginatedEntitiesCursorRequest = { + const request7: QueryEntitiesCursorRequest = { cursor: response6.nextCursor!, limit, }; - const response7 = await catalog.paginatedEntities(request7); + const response7 = await catalog.queryEntities(request7); expect(response7.entities).toEqual([entityFrom('C'), entityFrom('B')]); expect(response7.nextCursor).toBeDefined(); expect(response7.prevCursor).toBeDefined(); expect(response7.totalItems).toBe(names.length); // seventh.2 request (forward with a different limit) - const request7bis: PaginatedEntitiesCursorRequest = { + const request7bis: QueryEntitiesCursorRequest = { cursor: response6.nextCursor!, limit: limit + 1, }; - const response7bis = await catalog.paginatedEntities(request7bis); + const response7bis = await catalog.queryEntities(request7bis); expect(response7bis.entities).toEqual([ entityFrom('C'), entityFrom('B'), @@ -1003,11 +1003,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response7bis.totalItems).toBe(names.length); // last request (forward) - const request8: PaginatedEntitiesCursorRequest = { + const request8: QueryEntitiesCursorRequest = { cursor: response7.nextCursor!, limit, }; - const response8 = await catalog.paginatedEntities(request8); + const response8 = await catalog.queryEntities(request8); expect(response8.entities).toEqual([entityFrom('A')]); expect(response8.nextCursor).toBeUndefined(); expect(response8.prevCursor).toBeDefined(); @@ -1052,14 +1052,14 @@ describe('DefaultEntitiesCatalog', () => { key: 'spec.should_include_this', }; - const request: PaginatedEntitiesInitialRequest = { + const request: QueryEntitiesInitialRequest = { filter, limit: 100, sortFields: [{ field: 'metadata.name', order: 'asc' }], query: 'cAt ', }; - const response = await catalog.paginatedEntities(request); + const response = await catalog.queryEntities(request); expect(response.entities).toEqual([ entityFrom('atcatss'), entityFrom('cat'), @@ -1094,10 +1094,10 @@ describe('DefaultEntitiesCatalog', () => { stitcher, }); - const request: PaginatedEntitiesInitialRequest = { + const request: QueryEntitiesInitialRequest = { limit: 0, }; - const response = await catalog.paginatedEntities(request); + const response = await catalog.queryEntities(request); expect(response).toEqual({ totalItems: 20, entities: [] }); }, ); @@ -1125,11 +1125,11 @@ describe('DefaultEntitiesCatalog', () => { const limit = 2; // initial request - const request1: PaginatedEntitiesInitialRequest = { + const request1: QueryEntitiesInitialRequest = { limit, sortFields: [{ field: 'metadata.name', order: 'asc' }], }; - const response1 = await catalog.paginatedEntities(request1); + const response1 = await catalog.queryEntities(request1); expect(response1.entities).toMatchObject([ entityFrom('AA'), entityFrom('AA'), @@ -1139,11 +1139,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response1.totalItems).toBe(6); // second request (forward) - const request2: PaginatedEntitiesCursorRequest = { + const request2: QueryEntitiesCursorRequest = { cursor: response1.nextCursor!, limit, }; - const response2 = await catalog.paginatedEntities(request2); + const response2 = await catalog.queryEntities(request2); expect(response2.entities).toMatchObject([ entityFrom('AA'), entityFrom('AA'), @@ -1153,11 +1153,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response2.totalItems).toBe(6); // third request (forward) - const request3: PaginatedEntitiesCursorRequest = { + const request3: QueryEntitiesCursorRequest = { cursor: response2.nextCursor!, limit, }; - const response3 = await catalog.paginatedEntities(request3); + const response3 = await catalog.queryEntities(request3); expect(response3.entities).toEqual([ entityFrom('CC'), entityFrom('DD'), @@ -1167,11 +1167,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response3.totalItems).toBe(6); // forth request (backward) - const request4: PaginatedEntitiesCursorRequest = { + const request4: QueryEntitiesCursorRequest = { cursor: response3.prevCursor!, limit, }; - const response4 = await catalog.paginatedEntities(request4); + const response4 = await catalog.queryEntities(request4); expect(response4.entities).toMatchObject([ entityFrom('AA'), entityFrom('AA'), @@ -1181,11 +1181,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response4.totalItems).toBe(6); // fifth request (backward) - const request5: PaginatedEntitiesCursorRequest = { + const request5: QueryEntitiesCursorRequest = { cursor: response4.prevCursor!, limit, }; - const response5 = await catalog.paginatedEntities(request5); + const response5 = await catalog.queryEntities(request5); expect(response5.entities).toMatchObject([ entityFrom('AA'), entityFrom('AA'), @@ -1225,10 +1225,10 @@ describe('DefaultEntitiesCatalog', () => { const limit = 2; // initial request - const request1: PaginatedEntitiesInitialRequest = { + const request1: QueryEntitiesInitialRequest = { limit, }; - const response1 = await catalog.paginatedEntities(request1); + const response1 = await catalog.queryEntities(request1); expect(response1.entities).toMatchObject([ entityFrom('AA'), entityFrom('CC'), @@ -1238,11 +1238,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response1.totalItems).toBe(6); // second request (forward) - const request2: PaginatedEntitiesCursorRequest = { + const request2: QueryEntitiesCursorRequest = { cursor: response1.nextCursor!, limit, }; - const response2 = await catalog.paginatedEntities(request2); + const response2 = await catalog.queryEntities(request2); expect(response2.entities).toMatchObject([ entityFrom('DD'), entityFrom('AA', { namespace: 'namespace2' }), @@ -1252,11 +1252,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response2.totalItems).toBe(6); // third request (forward) - const request3: PaginatedEntitiesCursorRequest = { + const request3: QueryEntitiesCursorRequest = { cursor: response2.nextCursor!, limit, }; - const response3 = await catalog.paginatedEntities(request3); + const response3 = await catalog.queryEntities(request3); expect(response3.entities).toMatchObject([ entityFrom('AA', { namespace: 'namespace3' }), entityFrom('AA', { namespace: 'namespace4' }), @@ -1266,11 +1266,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response3.totalItems).toBe(6); // forth request (backward) - const request4: PaginatedEntitiesCursorRequest = { + const request4: QueryEntitiesCursorRequest = { cursor: response3.prevCursor!, limit, }; - const response4 = await catalog.paginatedEntities(request4); + const response4 = await catalog.queryEntities(request4); expect(response4.entities).toMatchObject([ entityFrom('DD'), entityFrom('AA', { namespace: 'namespace2' }), @@ -1280,11 +1280,11 @@ describe('DefaultEntitiesCatalog', () => { expect(response4.totalItems).toBe(6); // fifth request (backward) - const request5: PaginatedEntitiesCursorRequest = { + const request5: QueryEntitiesCursorRequest = { cursor: response4.prevCursor!, limit, }; - const response5 = await catalog.paginatedEntities(request5); + const response5 = await catalog.queryEntities(request5); expect(response5.entities).toMatchObject([ entityFrom('AA'), entityFrom('CC'), @@ -1306,11 +1306,11 @@ describe('DefaultEntitiesCatalog', () => { JSON.stringify({ filter: 'notavalidfilter' }), 'utf8', ).toString('base64'); - const request: PaginatedEntitiesCursorRequest = { + const request: QueryEntitiesCursorRequest = { cursor, }; - await expect(catalog.paginatedEntities(request)).rejects.toThrow( + await expect(catalog.queryEntities(request)).rejects.toThrow( Error('Malformed cursor, could not be parsed'), ); }); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 67fe77cc8b..fad5736f12 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -37,8 +37,8 @@ import { EntityFacetsResponse, EntityFilter, EntityPagination, - PaginatedEntitiesRequest, - PaginatedEntitiesResponse, + QueryEntitiesRequest, + QueryEntitiesResponse, EntityOrder, } from '../catalog/types'; import { @@ -53,8 +53,8 @@ import { import { Stitcher } from '../stitching/Stitcher'; import { - isPaginatedEntitiesCursorRequest, - isPaginatedEntitiesInitialRequest, + isQueryEntitiesCursorRequest, + isQueryEntitiesInitialRequest, } from './util'; const defaultSortField: EntityOrder = { @@ -332,9 +332,9 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { return { items }; } - async paginatedEntities( - request?: PaginatedEntitiesRequest, - ): Promise { + async queryEntities( + request?: QueryEntitiesRequest, + ): Promise { const db = this.database; const limit = request?.limit ?? 20; @@ -693,13 +693,13 @@ function decodeCursor(encodedCursor: string) { } function parseCursorFromRequest( - request?: PaginatedEntitiesRequest, + request?: QueryEntitiesRequest, ): Partial { - if (isPaginatedEntitiesInitialRequest(request)) { + if (isQueryEntitiesInitialRequest(request)) { const { filter, sortFields = [defaultSortField], query } = request; return { filter, sortFields, query }; } - if (isPaginatedEntitiesCursorRequest(request)) { + if (isQueryEntitiesCursorRequest(request)) { try { return decodeCursor(request.cursor); } catch { diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 8f5aeab2a0..d25d2b0cb4 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -52,7 +52,7 @@ describe('createRouter readonly disabled', () => { removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), facets: jest.fn(), - paginatedEntities: jest.fn(), + queryEntities: jest.fn(), }; locationService = { getLocation: jest.fn(), @@ -142,7 +142,7 @@ describe('createRouter readonly disabled', () => { { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, ]; - entitiesCatalog.paginatedEntities.mockResolvedValueOnce({ + entitiesCatalog.queryEntities.mockResolvedValueOnce({ entities, totalItems: 100, nextCursor: 'something', @@ -158,7 +158,7 @@ describe('createRouter readonly disabled', () => { }); it('parses initial request', async () => { - entitiesCatalog.paginatedEntities.mockResolvedValueOnce({ + entitiesCatalog.queryEntities.mockResolvedValueOnce({ entities: [], totalItems: 0, }); @@ -167,8 +167,8 @@ describe('createRouter readonly disabled', () => { ); expect(response.status).toEqual(200); - expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledWith({ + expect(entitiesCatalog.queryEntities).toHaveBeenCalledTimes(1); + expect(entitiesCatalog.queryEntities).toHaveBeenCalledWith({ filter: { anyOf: [ { @@ -192,7 +192,7 @@ describe('createRouter readonly disabled', () => { { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, ]; - entitiesCatalog.paginatedEntities.mockResolvedValueOnce({ + entitiesCatalog.queryEntities.mockResolvedValueOnce({ entities, totalItems: 100, nextCursor: 'next', @@ -201,8 +201,8 @@ describe('createRouter readonly disabled', () => { const response = await request(app).get( '/entities/by-query?cursor=something', ); - expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledTimes(1); - expect(entitiesCatalog.paginatedEntities).toHaveBeenCalledWith({ + expect(entitiesCatalog.queryEntities).toHaveBeenCalledTimes(1); + expect(entitiesCatalog.queryEntities).toHaveBeenCalledWith({ cursor: 'something', }); expect(response.status).toEqual(200); @@ -639,7 +639,7 @@ describe('createRouter readonly enabled', () => { removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), facets: jest.fn(), - paginatedEntities: jest.fn(), + queryEntities: jest.fn(), }; locationService = { getLocation: jest.fn(), @@ -830,7 +830,7 @@ describe('NextRouter permissioning', () => { removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), facets: jest.fn(), - paginatedEntities: jest.fn(), + queryEntities: jest.fn(), }; locationService = { getLocation: jest.fn(), diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index 994b676345..7603f6955d 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -39,7 +39,7 @@ import { parseEntityFilterParams, parseEntityPaginationParams, parseEntityTransformParams, - parsePaginatedEntitiesParams, + parseQueryEntitiesParams, } from './request'; import { parseEntityFacetParams } from './request/parseEntityFacetParams'; import { parseEntityOrderParams } from './request/parseEntityOrderParams'; @@ -132,8 +132,8 @@ export async function createRouter( res.json(entities); }) .get('/entities/by-query', async (req, res) => { - const response = await entitiesCatalog.paginatedEntities({ - ...parsePaginatedEntitiesParams(req.query), + const response = await entitiesCatalog.queryEntities({ + ...parseQueryEntitiesParams(req.query), authorizationToken: getBearerToken(req.header('authorization')), }); diff --git a/plugins/catalog-backend/src/service/request/index.ts b/plugins/catalog-backend/src/service/request/index.ts index 5a55c11ca0..d9297fc122 100644 --- a/plugins/catalog-backend/src/service/request/index.ts +++ b/plugins/catalog-backend/src/service/request/index.ts @@ -19,4 +19,4 @@ export { basicEntityFilter } from './basicEntityFilter'; export { parseEntityFilterParams } from './parseEntityFilterParams'; export { parseEntityPaginationParams } from './parseEntityPaginationParams'; export { parseEntityTransformParams } from './parseEntityTransformParams'; -export { parsePaginatedEntitiesParams } from './parsePaginatedEntitiesParams'; +export { parseQueryEntitiesParams } from './parseQueryEntitiesParams'; diff --git a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts similarity index 81% rename from plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts rename to plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts index 53d44c8ca5..ab702438c2 100644 --- a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts @@ -15,12 +15,12 @@ */ import { - PaginatedEntitiesCursorRequest, - PaginatedEntitiesInitialRequest, + QueryEntitiesCursorRequest, + QueryEntitiesInitialRequest, } from '../../catalog/types'; -import { parsePaginatedEntitiesParams } from './parsePaginatedEntitiesParams'; +import { parseQueryEntitiesParams } from './parseQueryEntitiesParams'; -describe('parsePaginatedEntitiesParams', () => { +describe('parseQueryEntitiesParams', () => { describe('initial request', () => { it('should parse all the defined params', () => { const validRequest = { @@ -31,9 +31,9 @@ describe('parsePaginatedEntitiesParams', () => { sortField: ['metadata.name,desc'], query: 'query', }; - const parsedObj = parsePaginatedEntitiesParams( + const parsedObj = parseQueryEntitiesParams( validRequest, - ) as PaginatedEntitiesInitialRequest; + ) as QueryEntitiesInitialRequest; expect(parsedObj.limit).toBe(3); expect(parsedObj.fields).toBeDefined(); expect(parsedObj.sortFields).toEqual([ @@ -45,9 +45,9 @@ describe('parsePaginatedEntitiesParams', () => { expect(parsedObj).not.toHaveProperty('cursor'); }); it('should ignore optional params', () => { - const parsedObj = parsePaginatedEntitiesParams( + const parsedObj = parseQueryEntitiesParams( {}, - ) as PaginatedEntitiesInitialRequest; + ) as QueryEntitiesInitialRequest; expect(parsedObj.limit).toBeUndefined(); expect(parsedObj.fields).toBeUndefined(); expect(parsedObj.sortFields).toBeUndefined(); @@ -66,7 +66,7 @@ describe('parsePaginatedEntitiesParams', () => { { fields: [4] }, { query: [] }, ])('should throw if some parameter is not valid %p', params => { - expect(() => parsePaginatedEntitiesParams(params)).toThrow(); + expect(() => parseQueryEntitiesParams(params)).toThrow(); }); }); @@ -78,9 +78,9 @@ describe('parsePaginatedEntitiesParams', () => { limit: '3', cursor: 'cursor', }; - const parsedObj = parsePaginatedEntitiesParams( + const parsedObj = parseQueryEntitiesParams( validRequest, - ) as PaginatedEntitiesCursorRequest; + ) as QueryEntitiesCursorRequest; expect(parsedObj.limit).toBe(3); expect(parsedObj.fields).toBeDefined(); expect(parsedObj.cursor).toBe('cursor'); @@ -97,9 +97,9 @@ describe('parsePaginatedEntitiesParams', () => { sortFieldOrder: 'desc', query: 'query', }; - const parsedObj = parsePaginatedEntitiesParams( + const parsedObj = parseQueryEntitiesParams( validRequest, - ) as PaginatedEntitiesCursorRequest; + ) as QueryEntitiesCursorRequest; expect(parsedObj.limit).toBe(3); expect(parsedObj.fields).toBeDefined(); expect(parsedObj.cursor).toBe('cursor'); @@ -110,9 +110,9 @@ describe('parsePaginatedEntitiesParams', () => { }); it('should ignore optional params', () => { - const parsedObj = parsePaginatedEntitiesParams( + const parsedObj = parseQueryEntitiesParams( {}, - ) as PaginatedEntitiesCursorRequest; + ) as QueryEntitiesCursorRequest; expect(parsedObj.limit).toBeUndefined(); expect(parsedObj.fields).toBeUndefined(); }); @@ -124,7 +124,7 @@ describe('parsePaginatedEntitiesParams', () => { { cursor: [] }, { fields: [4] }, ])('should throw if some parameter is not valid %p', params => { - expect(() => parsePaginatedEntitiesParams(params)).toThrow(); + expect(() => parseQueryEntitiesParams(params)).toThrow(); }); }); }); diff --git a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts similarity index 74% rename from plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts rename to plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts index f5730d3297..858189b0d2 100644 --- a/plugins/catalog-backend/src/service/request/parsePaginatedEntitiesParams.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts @@ -15,28 +15,27 @@ */ import { - PaginatedEntitiesCursorRequest, - PaginatedEntitiesInitialRequest, - PaginatedEntitiesRequest, + QueryEntitiesCursorRequest, + QueryEntitiesInitialRequest, + QueryEntitiesRequest, } from '../../catalog/types'; import { parseIntegerParam, parseStringParam } from './common'; import { parseEntityFilterParams } from './parseEntityFilterParams'; import { parseEntitySortFieldParams } from './parseEntitySortFieldParams'; import { parseEntityTransformParams } from './parseEntityTransformParams'; -export function parsePaginatedEntitiesParams( +export function parseQueryEntitiesParams( params: Record, -): Omit { +): Omit { const fields = parseEntityTransformParams(params); const limit = parseIntegerParam(params.limit, 'limit'); const cursor = parseStringParam(params.cursor, 'cursor'); if (cursor) { - const response: Omit = - { - cursor, - fields, - limit, - }; + const response: Omit = { + cursor, + fields, + limit, + }; return response; } @@ -44,14 +43,13 @@ export function parsePaginatedEntitiesParams( const query = parseStringParam(params.query, 'query'); const sortFields = parseEntitySortFieldParams(params); - const response: Omit = - { - fields, - filter, - limit, - sortFields, - query, - }; + const response: Omit = { + fields, + filter, + limit, + sortFields, + query, + }; return response; } diff --git a/plugins/catalog-backend/src/service/util.ts b/plugins/catalog-backend/src/service/util.ts index 958b4153f8..1ab154a86d 100644 --- a/plugins/catalog-backend/src/service/util.ts +++ b/plugins/catalog-backend/src/service/util.ts @@ -19,9 +19,9 @@ import { Request } from 'express'; import lodash from 'lodash'; import { z } from 'zod'; import { - PaginatedEntitiesCursorRequest, - PaginatedEntitiesInitialRequest, - PaginatedEntitiesRequest, + QueryEntitiesCursorRequest, + QueryEntitiesInitialRequest, + QueryEntitiesRequest, } from '../catalog/types'; export async function requireRequestBody(req: Request): Promise { @@ -71,20 +71,20 @@ export function disallowReadonlyMode(readonly: boolean) { } } -export function isPaginatedEntitiesInitialRequest( - input: PaginatedEntitiesRequest | undefined, -): input is PaginatedEntitiesInitialRequest { +export function isQueryEntitiesInitialRequest( + input: QueryEntitiesRequest | undefined, +): input is QueryEntitiesInitialRequest { if (!input) { return false; } - return !isPaginatedEntitiesCursorRequest(input); + return !isQueryEntitiesCursorRequest(input); } -export function isPaginatedEntitiesCursorRequest( - input: PaginatedEntitiesRequest | undefined, -): input is PaginatedEntitiesCursorRequest { +export function isQueryEntitiesCursorRequest( + input: QueryEntitiesRequest | undefined, +): input is QueryEntitiesCursorRequest { if (!input) { return false; } - return !!(input as PaginatedEntitiesCursorRequest).cursor; + return !!(input as QueryEntitiesCursorRequest).cursor; } From 0df4da9e714b4d2fb924dcb9748ff751b5f66683 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 10:55:36 +0100 Subject: [PATCH 049/417] catalog-client: move cursors to pageinfo Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/src/CatalogClient.test.ts | 12 ++++++------ packages/catalog-client/src/CatalogClient.ts | 13 ++++++------- packages/catalog-client/src/types/api.ts | 10 ++++++---- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index bc041ffd19..61fe1e4e19 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -310,8 +310,8 @@ describe('CatalogClient', () => { const response = await client.queryEntities({}, { token }); expect(response?.entities).toEqual(defaultClientResponse.entities); expect(response?.totalItems).toEqual(defaultClientResponse.totalItems); - expect(response?.nextCursor).toBeDefined(); - expect(response?.prevCursor).toBeDefined(); + expect(response?.pageInfo.nextCursor).toBeDefined(); + expect(response?.pageInfo.prevCursor).toBeDefined(); }); it('builds multiple entity search filters properly', async () => { @@ -429,15 +429,15 @@ describe('CatalogClient', () => { }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe('?limit=2'); - expect(response?.nextCursor).toBeDefined(); - expect(response?.prevCursor).toBeDefined(); + expect(response?.pageInfo.nextCursor).toBeDefined(); + expect(response?.pageInfo.prevCursor).toBeDefined(); - await client.queryEntities({ cursor: response!.nextCursor! }); + await client.queryEntities({ cursor: response!.pageInfo.nextCursor! }); expect(mockedEndpoint.mock.calls[1][0].url.search).toBe( '?cursor=nextcursor', ); - await client.queryEntities({ cursor: response!.prevCursor! }); + await client.queryEntities({ cursor: response!.pageInfo.prevCursor! }); expect(mockedEndpoint.mock.calls[2][0].url.search).toBe( '?cursor=prevcursor', ); diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 389f109989..c8bf7e57c2 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -210,7 +210,7 @@ export class CatalogClient implements CatalogApi { async queryEntities( request: QueryEntitiesRequest = {}, options?: CatalogRequestOptions, - ): Promise { + ) { const params: string[] = []; if (isQueryEntitiesInitialRequest(request)) { @@ -246,12 +246,11 @@ export class CatalogClient implements CatalogApi { } const query = params.length ? `?${params.join('&')}` : ''; - return this.requestRequired<{ - entities: Entity[]; - totalItems: number; - nextCursor?: string; - prevCursor?: string; - }>('GET', `/entities/by-query${query}`, options); + return this.requestRequired( + 'GET', + `/entities/by-query${query}`, + options, + ); } /** diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 09a67c8bce..5ef127660b 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -427,10 +427,12 @@ export type QueryEntitiesResponse = { entities: Entity[]; /* The number of entities among all the requests */ totalItems: number; - /* The cursor for the next batch of entities */ - nextCursor?: string; - /* The cursor for the previous batch of entities */ - prevCursor?: string; + pageInfo: { + /* The cursor for the next batch of entities */ + nextCursor?: string; + /* The cursor for the previous batch of entities */ + prevCursor?: string; + }; }; /** From 53c70b2f5e394519abda92c56ef17b7ff0c7ea99 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 10:55:54 +0100 Subject: [PATCH 050/417] catalog-backend: move cursors to pageinfo Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 19 +- .../src/service/AuthorizedEntitiesCatalog.ts | 1 + .../service/DefaultEntitiesCatalog.test.ts | 164 +++++++++--------- .../src/service/DefaultEntitiesCatalog.ts | 2 +- .../src/service/createRouter.test.ts | 3 +- 5 files changed, 97 insertions(+), 92 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 93720e5a68..8450e022cc 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -250,14 +250,17 @@ export interface QueryEntitiesResponse { * The entities for the current pagination request */ entities: Entity[]; - /** - * The cursor of the next pagination request. - */ - nextCursor?: string; - /** - * The cursor of the previous pagination request. - */ - prevCursor?: string; + + pageInfo: { + /** + * The cursor of the next pagination request. + */ + nextCursor?: string; + /** + * The cursor of the previous pagination request. + */ + prevCursor?: string; + }; /** * the total number of entities matching the current filters. */ diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index 2a5388c3d5..eea9a2ca68 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -122,6 +122,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { if (authorizeDecision.result === AuthorizeResult.DENY) { return { entities: [], + pageInfo: {}, totalItems: 0, }; } diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 92b2ecb3c5..f54773bb2d 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -771,79 +771,79 @@ describe('DefaultEntitiesCatalog', () => { }; const response1 = await catalog.queryEntities(request1); expect(response1.entities).toEqual([entityFrom('A'), entityFrom('B')]); - expect(response1.nextCursor).toBeDefined(); - expect(response1.prevCursor).toBeUndefined(); + expect(response1.pageInfo.nextCursor).toBeDefined(); + expect(response1.pageInfo.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(names.length); // second request (forward) const request2: QueryEntitiesCursorRequest = { - cursor: response1.nextCursor!, + cursor: response1.pageInfo.nextCursor!, limit, }; const response2 = await catalog.queryEntities(request2); expect(response2.entities).toEqual([entityFrom('C'), entityFrom('D')]); - expect(response2.nextCursor).toBeDefined(); - expect(response2.prevCursor).toBeDefined(); + expect(response2.pageInfo.nextCursor).toBeDefined(); + expect(response2.pageInfo.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(names.length); // third request (forward) const request3: QueryEntitiesCursorRequest = { - cursor: response2.nextCursor!, + cursor: response2.pageInfo.nextCursor!, limit, }; const response3 = await catalog.queryEntities(request3); expect(response3.entities).toEqual([entityFrom('E'), entityFrom('F')]); - expect(response3.nextCursor).toBeDefined(); - expect(response3.prevCursor).toBeDefined(); + expect(response3.pageInfo.nextCursor).toBeDefined(); + expect(response3.pageInfo.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(names.length); // fourth request (backwards) const request4: QueryEntitiesCursorRequest = { - cursor: response3.prevCursor!, + cursor: response3.pageInfo.prevCursor!, limit, }; const response4 = await catalog.queryEntities(request4); expect(response4.entities).toEqual([entityFrom('C'), entityFrom('D')]); - expect(response4.nextCursor).toBeDefined(); - expect(response4.prevCursor).toBeDefined(); + expect(response4.pageInfo.nextCursor).toBeDefined(); + expect(response4.pageInfo.prevCursor).toBeDefined(); expect(response4.totalItems).toBe(names.length); // fifth request (backwards) const request5: QueryEntitiesCursorRequest = { - cursor: response4.prevCursor!, + cursor: response4.pageInfo.prevCursor!, limit, }; const response5 = await catalog.queryEntities(request5); expect(response5.entities).toEqual([entityFrom('A'), entityFrom('B')]); - expect(response5.nextCursor).toBeDefined(); - expect(response5.prevCursor).toBeUndefined(); + expect(response5.pageInfo.nextCursor).toBeDefined(); + expect(response5.pageInfo.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(names.length); // sixth request (forward) const request6: QueryEntitiesCursorRequest = { - cursor: response5.nextCursor!, + cursor: response5.pageInfo.nextCursor!, limit, }; const response6 = await catalog.queryEntities(request6); expect(response6.entities).toEqual([entityFrom('C'), entityFrom('D')]); - expect(response6.nextCursor).toBeDefined(); - expect(response6.prevCursor).toBeDefined(); + expect(response6.pageInfo.nextCursor).toBeDefined(); + expect(response6.pageInfo.prevCursor).toBeDefined(); expect(response6.totalItems).toBe(names.length); // seventh request (forward) const request7: QueryEntitiesCursorRequest = { - cursor: response6.nextCursor!, + cursor: response6.pageInfo.nextCursor!, limit, }; const response7 = await catalog.queryEntities(request7); expect(response7.entities).toEqual([entityFrom('E'), entityFrom('F')]); - expect(response7.nextCursor).toBeDefined(); - expect(response7.prevCursor).toBeDefined(); + expect(response7.pageInfo.nextCursor).toBeDefined(); + expect(response7.pageInfo.prevCursor).toBeDefined(); expect(response7.totalItems).toBe(names.length); // seventh.2 request (forward with a different limit) const request7bis: QueryEntitiesCursorRequest = { - cursor: response6.nextCursor!, + cursor: response6.pageInfo.nextCursor!, limit: limit + 1, }; const response7bis = await catalog.queryEntities(request7bis); @@ -852,19 +852,19 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('F'), entityFrom('G'), ]); - expect(response7bis.nextCursor).toBeUndefined(); - expect(response7bis.prevCursor).toBeDefined(); + expect(response7bis.pageInfo.nextCursor).toBeUndefined(); + expect(response7bis.pageInfo.prevCursor).toBeDefined(); expect(response7bis.totalItems).toBe(names.length); // last request (forward) const request8: QueryEntitiesCursorRequest = { - cursor: response7.nextCursor!, + cursor: response7.pageInfo.nextCursor!, limit, }; const response8 = await catalog.queryEntities(request8); expect(response8.entities).toEqual([entityFrom('G')]); - expect(response8.nextCursor).toBeUndefined(); - expect(response8.prevCursor).toBeDefined(); + expect(response8.pageInfo.nextCursor).toBeUndefined(); + expect(response8.pageInfo.prevCursor).toBeDefined(); expect(response8.totalItems).toBe(names.length); }, ); @@ -916,80 +916,80 @@ describe('DefaultEntitiesCatalog', () => { }; const response1 = await catalog.queryEntities(request1); expect(response1.entities).toEqual([entityFrom('G'), entityFrom('F')]); - expect(response1.nextCursor).toBeDefined(); - expect(response1.prevCursor).toBeUndefined(); + expect(response1.pageInfo.nextCursor).toBeDefined(); + expect(response1.pageInfo.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(names.length); // second request (forward) const request2: QueryEntitiesCursorRequest = { - cursor: response1.nextCursor!, + cursor: response1.pageInfo.nextCursor!, limit, }; const response2 = await catalog.queryEntities(request2); expect(response2.entities).toEqual([entityFrom('E'), entityFrom('D')]); - expect(response2.nextCursor).toBeDefined(); - expect(response2.prevCursor).toBeDefined(); + expect(response2.pageInfo.nextCursor).toBeDefined(); + expect(response2.pageInfo.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(names.length); // third request (forward) const request3: QueryEntitiesCursorRequest = { - cursor: response2.nextCursor!, + cursor: response2.pageInfo.nextCursor!, limit, }; const response3 = await catalog.queryEntities(request3); expect(response3.entities).toEqual([entityFrom('C'), entityFrom('B')]); - expect(response3.nextCursor).toBeDefined(); - expect(response3.prevCursor).toBeDefined(); + expect(response3.pageInfo.nextCursor).toBeDefined(); + expect(response3.pageInfo.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(names.length); // fourth request (backwards) const request4: QueryEntitiesCursorRequest = { - cursor: response3.prevCursor!, + cursor: response3.pageInfo.prevCursor!, limit, }; const response4 = await catalog.queryEntities(request4); expect(response4.entities).toEqual([entityFrom('E'), entityFrom('D')]); - expect(response4.nextCursor).toBeDefined(); - expect(response4.prevCursor).toBeDefined(); + expect(response4.pageInfo.nextCursor).toBeDefined(); + expect(response4.pageInfo.prevCursor).toBeDefined(); expect(response4.totalItems).toBe(names.length); // fifth request (backwards) const request5: QueryEntitiesCursorRequest = { - cursor: response4.prevCursor!, + cursor: response4.pageInfo.prevCursor!, limit, }; const response5 = await catalog.queryEntities(request5); expect(response5.entities).toEqual([entityFrom('G'), entityFrom('F')]); - expect(response5.nextCursor).toBeDefined(); - expect(response5.prevCursor).toBeUndefined(); + expect(response5.pageInfo.nextCursor).toBeDefined(); + expect(response5.pageInfo.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(names.length); // sixth request (forward) const request6: QueryEntitiesCursorRequest = { - cursor: response5.nextCursor!, + cursor: response5.pageInfo.nextCursor!, limit, }; const response6 = await catalog.queryEntities(request6); expect(response6.entities).toEqual([entityFrom('E'), entityFrom('D')]); - expect(response6.nextCursor).toBeDefined(); - expect(response6.prevCursor).toBeDefined(); + expect(response6.pageInfo.nextCursor).toBeDefined(); + expect(response6.pageInfo.prevCursor).toBeDefined(); expect(response6.totalItems).toBe(names.length); // seventh request (forward) const request7: QueryEntitiesCursorRequest = { - cursor: response6.nextCursor!, + cursor: response6.pageInfo.nextCursor!, limit, }; const response7 = await catalog.queryEntities(request7); expect(response7.entities).toEqual([entityFrom('C'), entityFrom('B')]); - expect(response7.nextCursor).toBeDefined(); - expect(response7.prevCursor).toBeDefined(); + expect(response7.pageInfo.nextCursor).toBeDefined(); + expect(response7.pageInfo.prevCursor).toBeDefined(); expect(response7.totalItems).toBe(names.length); // seventh.2 request (forward with a different limit) const request7bis: QueryEntitiesCursorRequest = { - cursor: response6.nextCursor!, + cursor: response6.pageInfo.nextCursor!, limit: limit + 1, }; const response7bis = await catalog.queryEntities(request7bis); @@ -998,19 +998,19 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('B'), entityFrom('A'), ]); - expect(response7bis.nextCursor).toBeUndefined(); - expect(response7bis.prevCursor).toBeDefined(); + expect(response7bis.pageInfo.nextCursor).toBeUndefined(); + expect(response7bis.pageInfo.prevCursor).toBeDefined(); expect(response7bis.totalItems).toBe(names.length); // last request (forward) const request8: QueryEntitiesCursorRequest = { - cursor: response7.nextCursor!, + cursor: response7.pageInfo.nextCursor!, limit, }; const response8 = await catalog.queryEntities(request8); expect(response8.entities).toEqual([entityFrom('A')]); - expect(response8.nextCursor).toBeUndefined(); - expect(response8.prevCursor).toBeDefined(); + expect(response8.pageInfo.nextCursor).toBeUndefined(); + expect(response8.pageInfo.prevCursor).toBeDefined(); expect(response8.totalItems).toBe(names.length); }, ); @@ -1065,8 +1065,8 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('cat'), entityFrom('dogcat'), ]); - expect(response.nextCursor).toBeUndefined(); - expect(response.prevCursor).toBeUndefined(); + expect(response.pageInfo.nextCursor).toBeUndefined(); + expect(response.pageInfo.prevCursor).toBeUndefined(); expect(response.totalItems).toBe(3); }, ); @@ -1134,13 +1134,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('AA'), entityFrom('AA'), ]); - expect(response1.nextCursor).toBeDefined(); - expect(response1.prevCursor).toBeUndefined(); + expect(response1.pageInfo.nextCursor).toBeDefined(); + expect(response1.pageInfo.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(6); // second request (forward) const request2: QueryEntitiesCursorRequest = { - cursor: response1.nextCursor!, + cursor: response1.pageInfo.nextCursor!, limit, }; const response2 = await catalog.queryEntities(request2); @@ -1148,13 +1148,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('AA'), entityFrom('AA'), ]); - expect(response2.nextCursor).toBeDefined(); - expect(response2.prevCursor).toBeDefined(); + expect(response2.pageInfo.nextCursor).toBeDefined(); + expect(response2.pageInfo.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(6); // third request (forward) const request3: QueryEntitiesCursorRequest = { - cursor: response2.nextCursor!, + cursor: response2.pageInfo.nextCursor!, limit, }; const response3 = await catalog.queryEntities(request3); @@ -1162,13 +1162,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('CC'), entityFrom('DD'), ]); - expect(response3.nextCursor).toBeUndefined(); - expect(response3.prevCursor).toBeDefined(); + expect(response3.pageInfo.nextCursor).toBeUndefined(); + expect(response3.pageInfo.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(6); // forth request (backward) const request4: QueryEntitiesCursorRequest = { - cursor: response3.prevCursor!, + cursor: response3.pageInfo.prevCursor!, limit, }; const response4 = await catalog.queryEntities(request4); @@ -1176,13 +1176,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('AA'), entityFrom('AA'), ]); - expect(response4.nextCursor).toBeDefined(); - expect(response4.prevCursor).toBeDefined(); + expect(response4.pageInfo.nextCursor).toBeDefined(); + expect(response4.pageInfo.prevCursor).toBeDefined(); expect(response4.totalItems).toBe(6); // fifth request (backward) const request5: QueryEntitiesCursorRequest = { - cursor: response4.prevCursor!, + cursor: response4.pageInfo.prevCursor!, limit, }; const response5 = await catalog.queryEntities(request5); @@ -1190,8 +1190,8 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('AA'), entityFrom('AA'), ]); - expect(response5.nextCursor).toBeDefined(); - expect(response5.prevCursor).toBeUndefined(); + expect(response5.pageInfo.nextCursor).toBeDefined(); + expect(response5.pageInfo.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(6); }, ); @@ -1233,13 +1233,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('AA'), entityFrom('CC'), ]); - expect(response1.nextCursor).toBeDefined(); - expect(response1.prevCursor).toBeUndefined(); + expect(response1.pageInfo.nextCursor).toBeDefined(); + expect(response1.pageInfo.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(6); // second request (forward) const request2: QueryEntitiesCursorRequest = { - cursor: response1.nextCursor!, + cursor: response1.pageInfo.nextCursor!, limit, }; const response2 = await catalog.queryEntities(request2); @@ -1247,13 +1247,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('DD'), entityFrom('AA', { namespace: 'namespace2' }), ]); - expect(response2.nextCursor).toBeDefined(); - expect(response2.prevCursor).toBeDefined(); + expect(response2.pageInfo.nextCursor).toBeDefined(); + expect(response2.pageInfo.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(6); // third request (forward) const request3: QueryEntitiesCursorRequest = { - cursor: response2.nextCursor!, + cursor: response2.pageInfo.nextCursor!, limit, }; const response3 = await catalog.queryEntities(request3); @@ -1261,13 +1261,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('AA', { namespace: 'namespace3' }), entityFrom('AA', { namespace: 'namespace4' }), ]); - expect(response3.nextCursor).toBeUndefined(); - expect(response3.prevCursor).toBeDefined(); + expect(response3.pageInfo.nextCursor).toBeUndefined(); + expect(response3.pageInfo.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(6); // forth request (backward) const request4: QueryEntitiesCursorRequest = { - cursor: response3.prevCursor!, + cursor: response3.pageInfo.prevCursor!, limit, }; const response4 = await catalog.queryEntities(request4); @@ -1275,13 +1275,13 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('DD'), entityFrom('AA', { namespace: 'namespace2' }), ]); - expect(response4.nextCursor).toBeDefined(); - expect(response4.prevCursor).toBeDefined(); + expect(response4.pageInfo.nextCursor).toBeDefined(); + expect(response4.pageInfo.prevCursor).toBeDefined(); expect(response4.totalItems).toBe(6); // fifth request (backward) const request5: QueryEntitiesCursorRequest = { - cursor: response4.prevCursor!, + cursor: response4.pageInfo.prevCursor!, limit, }; const response5 = await catalog.queryEntities(request5); @@ -1289,8 +1289,8 @@ describe('DefaultEntitiesCatalog', () => { entityFrom('AA'), entityFrom('CC'), ]); - expect(response5.nextCursor).toBeDefined(); - expect(response5.prevCursor).toBeUndefined(); + expect(response5.pageInfo.nextCursor).toBeDefined(); + expect(response5.pageInfo.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(6); }, ); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index fad5736f12..0f68a7a3c1 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -475,7 +475,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { .map(e => JSON.parse(e.final_entity!)) .map(e => (request?.fields ? request.fields(e) : e)); - return { entities, prevCursor, nextCursor, totalItems }; + return { entities, pageInfo: { prevCursor, nextCursor }, totalItems }; } async removeEntityByUid(uid: string): Promise { diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index d25d2b0cb4..397d16f714 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -145,7 +145,7 @@ describe('createRouter readonly disabled', () => { entitiesCatalog.queryEntities.mockResolvedValueOnce({ entities, totalItems: 100, - nextCursor: 'something', + pageInfo: { nextCursor: 'something' }, }); const response = await request(app).get('/entities/by-query'); @@ -160,6 +160,7 @@ describe('createRouter readonly disabled', () => { it('parses initial request', async () => { entitiesCatalog.queryEntities.mockResolvedValueOnce({ entities: [], + pageInfo: {}, totalItems: 0, }); const response = await request(app).get( From f3a15259e912bf054a26fcf14d3221a2311c157b Mon Sep 17 00:00:00 2001 From: pamelin Date: Fri, 3 Feb 2023 11:12:47 +0000 Subject: [PATCH 051/417] fix: Add changeset Signed-off-by: pamelin --- .changeset/quick-tables-listen.md | 5 +++++ plugins/stackstorm/package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/quick-tables-listen.md diff --git a/.changeset/quick-tables-listen.md b/.changeset/quick-tables-listen.md new file mode 100644 index 0000000000..cb2e4eb064 --- /dev/null +++ b/.changeset/quick-tables-listen.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-stackstorm': minor +--- + +Add StackStorm plugin to Backstage which is interfacing with StackStorm API. It allows users to view workflow executions, packs and actions. For installation and configuration instyructions please view [README.md](https://github.com/backstage/backstage/tree/master/plugins/stackstorm/README.md) diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index 921cb07c29..03e65d21c5 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-stackstorm", "description": "A Backstage plugin that integrates towards StackStorm", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", From 68bac7113f490e91c58605608ed27afef7d29b6a Mon Sep 17 00:00:00 2001 From: pamelin Date: Fri, 3 Feb 2023 11:38:14 +0000 Subject: [PATCH 052/417] fix: Format app-config.yaml Signed-off-by: pamelin --- app-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-config.yaml b/app-config.yaml index 17bc057bac..743ca31c4b 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -450,4 +450,4 @@ permission: enabled: true stackstorm: - webUrl: 'https://your.stackstorm.webui.com' + webUrl: https://your.stackstorm.webui.com From 46649661a6b077b7f7b9384b25767962a0b6fe7f Mon Sep 17 00:00:00 2001 From: pamelin Date: Fri, 3 Feb 2023 11:43:39 +0000 Subject: [PATCH 053/417] fix: Typo in the changeset Signed-off-by: pamelin --- .changeset/quick-tables-listen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/quick-tables-listen.md b/.changeset/quick-tables-listen.md index cb2e4eb064..fab9ef7969 100644 --- a/.changeset/quick-tables-listen.md +++ b/.changeset/quick-tables-listen.md @@ -2,4 +2,4 @@ '@backstage/plugin-stackstorm': minor --- -Add StackStorm plugin to Backstage which is interfacing with StackStorm API. It allows users to view workflow executions, packs and actions. For installation and configuration instyructions please view [README.md](https://github.com/backstage/backstage/tree/master/plugins/stackstorm/README.md) +Add StackStorm plugin to Backstage which is interfacing with StackStorm API. It allows users to view workflow executions, packs and actions. For installation and configuration instructions please view [README.md](https://github.com/backstage/backstage/tree/master/plugins/stackstorm/README.md) From 6567b7cd585bda87fd676d8bbd0a56c7599aa206 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 12:55:39 +0100 Subject: [PATCH 054/417] catalog-backend: entities to items Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 2 +- .../src/service/AuthorizedEntitiesCatalog.ts | 2 +- .../service/DefaultEntitiesCatalog.test.ts | 61 +++++++++---------- .../src/service/DefaultEntitiesCatalog.ts | 4 +- .../src/service/createRouter.test.ts | 16 ++--- 5 files changed, 41 insertions(+), 44 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 8450e022cc..5591573ee2 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -249,7 +249,7 @@ export interface QueryEntitiesResponse { /** * The entities for the current pagination request */ - entities: Entity[]; + items: Entity[]; pageInfo: { /** diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index eea9a2ca68..f9ec058879 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -121,7 +121,7 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { if (authorizeDecision.result === AuthorizeResult.DENY) { return { - entities: [], + items: [], pageInfo: {}, totalItems: 0, }; diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index f54773bb2d..ab20c0942a 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -770,7 +770,7 @@ describe('DefaultEntitiesCatalog', () => { sortFields: [{ field: 'metadata.name', order: 'asc' }], }; const response1 = await catalog.queryEntities(request1); - expect(response1.entities).toEqual([entityFrom('A'), entityFrom('B')]); + expect(response1.items).toEqual([entityFrom('A'), entityFrom('B')]); expect(response1.pageInfo.nextCursor).toBeDefined(); expect(response1.pageInfo.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(names.length); @@ -781,7 +781,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response2 = await catalog.queryEntities(request2); - expect(response2.entities).toEqual([entityFrom('C'), entityFrom('D')]); + expect(response2.items).toEqual([entityFrom('C'), entityFrom('D')]); expect(response2.pageInfo.nextCursor).toBeDefined(); expect(response2.pageInfo.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(names.length); @@ -792,7 +792,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response3 = await catalog.queryEntities(request3); - expect(response3.entities).toEqual([entityFrom('E'), entityFrom('F')]); + expect(response3.items).toEqual([entityFrom('E'), entityFrom('F')]); expect(response3.pageInfo.nextCursor).toBeDefined(); expect(response3.pageInfo.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(names.length); @@ -803,7 +803,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response4 = await catalog.queryEntities(request4); - expect(response4.entities).toEqual([entityFrom('C'), entityFrom('D')]); + expect(response4.items).toEqual([entityFrom('C'), entityFrom('D')]); expect(response4.pageInfo.nextCursor).toBeDefined(); expect(response4.pageInfo.prevCursor).toBeDefined(); expect(response4.totalItems).toBe(names.length); @@ -814,7 +814,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response5 = await catalog.queryEntities(request5); - expect(response5.entities).toEqual([entityFrom('A'), entityFrom('B')]); + expect(response5.items).toEqual([entityFrom('A'), entityFrom('B')]); expect(response5.pageInfo.nextCursor).toBeDefined(); expect(response5.pageInfo.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(names.length); @@ -825,7 +825,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response6 = await catalog.queryEntities(request6); - expect(response6.entities).toEqual([entityFrom('C'), entityFrom('D')]); + expect(response6.items).toEqual([entityFrom('C'), entityFrom('D')]); expect(response6.pageInfo.nextCursor).toBeDefined(); expect(response6.pageInfo.prevCursor).toBeDefined(); expect(response6.totalItems).toBe(names.length); @@ -836,7 +836,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response7 = await catalog.queryEntities(request7); - expect(response7.entities).toEqual([entityFrom('E'), entityFrom('F')]); + expect(response7.items).toEqual([entityFrom('E'), entityFrom('F')]); expect(response7.pageInfo.nextCursor).toBeDefined(); expect(response7.pageInfo.prevCursor).toBeDefined(); expect(response7.totalItems).toBe(names.length); @@ -847,7 +847,7 @@ describe('DefaultEntitiesCatalog', () => { limit: limit + 1, }; const response7bis = await catalog.queryEntities(request7bis); - expect(response7bis.entities).toEqual([ + expect(response7bis.items).toEqual([ entityFrom('E'), entityFrom('F'), entityFrom('G'), @@ -862,7 +862,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response8 = await catalog.queryEntities(request8); - expect(response8.entities).toEqual([entityFrom('G')]); + expect(response8.items).toEqual([entityFrom('G')]); expect(response8.pageInfo.nextCursor).toBeUndefined(); expect(response8.pageInfo.prevCursor).toBeDefined(); expect(response8.totalItems).toBe(names.length); @@ -915,7 +915,7 @@ describe('DefaultEntitiesCatalog', () => { sortFields: [{ field: 'metadata.name', order: 'desc' }], }; const response1 = await catalog.queryEntities(request1); - expect(response1.entities).toEqual([entityFrom('G'), entityFrom('F')]); + expect(response1.items).toEqual([entityFrom('G'), entityFrom('F')]); expect(response1.pageInfo.nextCursor).toBeDefined(); expect(response1.pageInfo.prevCursor).toBeUndefined(); expect(response1.totalItems).toBe(names.length); @@ -926,7 +926,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response2 = await catalog.queryEntities(request2); - expect(response2.entities).toEqual([entityFrom('E'), entityFrom('D')]); + expect(response2.items).toEqual([entityFrom('E'), entityFrom('D')]); expect(response2.pageInfo.nextCursor).toBeDefined(); expect(response2.pageInfo.prevCursor).toBeDefined(); expect(response2.totalItems).toBe(names.length); @@ -937,7 +937,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response3 = await catalog.queryEntities(request3); - expect(response3.entities).toEqual([entityFrom('C'), entityFrom('B')]); + expect(response3.items).toEqual([entityFrom('C'), entityFrom('B')]); expect(response3.pageInfo.nextCursor).toBeDefined(); expect(response3.pageInfo.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(names.length); @@ -949,7 +949,7 @@ describe('DefaultEntitiesCatalog', () => { }; const response4 = await catalog.queryEntities(request4); - expect(response4.entities).toEqual([entityFrom('E'), entityFrom('D')]); + expect(response4.items).toEqual([entityFrom('E'), entityFrom('D')]); expect(response4.pageInfo.nextCursor).toBeDefined(); expect(response4.pageInfo.prevCursor).toBeDefined(); expect(response4.totalItems).toBe(names.length); @@ -960,7 +960,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response5 = await catalog.queryEntities(request5); - expect(response5.entities).toEqual([entityFrom('G'), entityFrom('F')]); + expect(response5.items).toEqual([entityFrom('G'), entityFrom('F')]); expect(response5.pageInfo.nextCursor).toBeDefined(); expect(response5.pageInfo.prevCursor).toBeUndefined(); expect(response5.totalItems).toBe(names.length); @@ -971,7 +971,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response6 = await catalog.queryEntities(request6); - expect(response6.entities).toEqual([entityFrom('E'), entityFrom('D')]); + expect(response6.items).toEqual([entityFrom('E'), entityFrom('D')]); expect(response6.pageInfo.nextCursor).toBeDefined(); expect(response6.pageInfo.prevCursor).toBeDefined(); expect(response6.totalItems).toBe(names.length); @@ -982,7 +982,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response7 = await catalog.queryEntities(request7); - expect(response7.entities).toEqual([entityFrom('C'), entityFrom('B')]); + expect(response7.items).toEqual([entityFrom('C'), entityFrom('B')]); expect(response7.pageInfo.nextCursor).toBeDefined(); expect(response7.pageInfo.prevCursor).toBeDefined(); expect(response7.totalItems).toBe(names.length); @@ -993,7 +993,7 @@ describe('DefaultEntitiesCatalog', () => { limit: limit + 1, }; const response7bis = await catalog.queryEntities(request7bis); - expect(response7bis.entities).toEqual([ + expect(response7bis.items).toEqual([ entityFrom('C'), entityFrom('B'), entityFrom('A'), @@ -1008,7 +1008,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response8 = await catalog.queryEntities(request8); - expect(response8.entities).toEqual([entityFrom('A')]); + expect(response8.items).toEqual([entityFrom('A')]); expect(response8.pageInfo.nextCursor).toBeUndefined(); expect(response8.pageInfo.prevCursor).toBeDefined(); expect(response8.totalItems).toBe(names.length); @@ -1060,7 +1060,7 @@ describe('DefaultEntitiesCatalog', () => { query: 'cAt ', }; const response = await catalog.queryEntities(request); - expect(response.entities).toEqual([ + expect(response.items).toEqual([ entityFrom('atcatss'), entityFrom('cat'), entityFrom('dogcat'), @@ -1130,7 +1130,7 @@ describe('DefaultEntitiesCatalog', () => { sortFields: [{ field: 'metadata.name', order: 'asc' }], }; const response1 = await catalog.queryEntities(request1); - expect(response1.entities).toMatchObject([ + expect(response1.items).toMatchObject([ entityFrom('AA'), entityFrom('AA'), ]); @@ -1144,7 +1144,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response2 = await catalog.queryEntities(request2); - expect(response2.entities).toMatchObject([ + expect(response2.items).toMatchObject([ entityFrom('AA'), entityFrom('AA'), ]); @@ -1158,10 +1158,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response3 = await catalog.queryEntities(request3); - expect(response3.entities).toEqual([ - entityFrom('CC'), - entityFrom('DD'), - ]); + expect(response3.items).toEqual([entityFrom('CC'), entityFrom('DD')]); expect(response3.pageInfo.nextCursor).toBeUndefined(); expect(response3.pageInfo.prevCursor).toBeDefined(); expect(response3.totalItems).toBe(6); @@ -1172,7 +1169,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response4 = await catalog.queryEntities(request4); - expect(response4.entities).toMatchObject([ + expect(response4.items).toMatchObject([ entityFrom('AA'), entityFrom('AA'), ]); @@ -1186,7 +1183,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response5 = await catalog.queryEntities(request5); - expect(response5.entities).toMatchObject([ + expect(response5.items).toMatchObject([ entityFrom('AA'), entityFrom('AA'), ]); @@ -1229,7 +1226,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response1 = await catalog.queryEntities(request1); - expect(response1.entities).toMatchObject([ + expect(response1.items).toMatchObject([ entityFrom('AA'), entityFrom('CC'), ]); @@ -1243,7 +1240,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response2 = await catalog.queryEntities(request2); - expect(response2.entities).toMatchObject([ + expect(response2.items).toMatchObject([ entityFrom('DD'), entityFrom('AA', { namespace: 'namespace2' }), ]); @@ -1257,7 +1254,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response3 = await catalog.queryEntities(request3); - expect(response3.entities).toMatchObject([ + expect(response3.items).toMatchObject([ entityFrom('AA', { namespace: 'namespace3' }), entityFrom('AA', { namespace: 'namespace4' }), ]); @@ -1271,7 +1268,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response4 = await catalog.queryEntities(request4); - expect(response4.entities).toMatchObject([ + expect(response4.items).toMatchObject([ entityFrom('DD'), entityFrom('AA', { namespace: 'namespace2' }), ]); @@ -1285,7 +1282,7 @@ describe('DefaultEntitiesCatalog', () => { limit, }; const response5 = await catalog.queryEntities(request5); - expect(response5.entities).toMatchObject([ + expect(response5.items).toMatchObject([ entityFrom('AA'), entityFrom('CC'), ]); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 0f68a7a3c1..ba242b7ab5 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -471,11 +471,11 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { }) : undefined; - const entities = rows + const items = rows .map(e => JSON.parse(e.final_entity!)) .map(e => (request?.fields ? request.fields(e) : e)); - return { entities, pageInfo: { prevCursor, nextCursor }, totalItems }; + return { items, pageInfo: { prevCursor, nextCursor }, totalItems }; } async removeEntityByUid(uid: string): Promise { diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 397d16f714..a35115ac58 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -138,12 +138,12 @@ describe('createRouter readonly disabled', () => { describe('GET /entities/by-query', () => { it('happy path: lists entities', async () => { - const entities: Entity[] = [ + const items: Entity[] = [ { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, ]; entitiesCatalog.queryEntities.mockResolvedValueOnce({ - entities, + items, totalItems: 100, pageInfo: { nextCursor: 'something' }, }); @@ -151,7 +151,7 @@ describe('createRouter readonly disabled', () => { const response = await request(app).get('/entities/by-query'); expect(response.status).toEqual(200); expect(response.body).toEqual({ - entities, + items, totalItems: 100, nextCursor: 'something', }); @@ -159,7 +159,7 @@ describe('createRouter readonly disabled', () => { it('parses initial request', async () => { entitiesCatalog.queryEntities.mockResolvedValueOnce({ - entities: [], + items: [], pageInfo: {}, totalItems: 0, }); @@ -189,14 +189,14 @@ describe('createRouter readonly disabled', () => { }); it('parses cursor request', async () => { - const entities: Entity[] = [ + const items: Entity[] = [ { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, ]; entitiesCatalog.queryEntities.mockResolvedValueOnce({ - entities, + items, totalItems: 100, - nextCursor: 'next', + pageInfo: { nextCursor: 'next' }, }); const response = await request(app).get( @@ -208,7 +208,7 @@ describe('createRouter readonly disabled', () => { }); expect(response.status).toEqual(200); expect(response.body).toEqual({ - entities, + items, totalItems: 100, nextCursor: 'next', }); From 58195a4813822ecf9320f1576b49ac2783c9fbf7 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 12:56:05 +0100 Subject: [PATCH 055/417] catalog-client: entities to items Signed-off-by: Vincenzo Scamporlino --- .../catalog-client/src/CatalogClient.test.ts | 64 +++++++------------ packages/catalog-client/src/types/api.ts | 2 +- 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 61fe1e4e19..4992b0d373 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -18,7 +18,11 @@ import { Entity } from '@backstage/catalog-model'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { CatalogClient } from './CatalogClient'; -import { CATALOG_FILTER_EXISTS, GetEntitiesResponse } from './types/api'; +import { + CATALOG_FILTER_EXISTS, + GetEntitiesResponse, + QueryEntitiesResponse, +} from './types/api'; import { DiscoveryApi } from './types/discovery'; const server = setupServer(); @@ -250,8 +254,8 @@ describe('CatalogClient', () => { }); describe('queryEntities', () => { - const defaultServiceResponse = { - entities: [ + const defaultResponse: QueryEntitiesResponse = { + items: [ { apiVersion: '1', kind: 'Component', @@ -269,47 +273,25 @@ describe('CatalogClient', () => { }, }, ], + pageInfo: { + nextCursor: 'next', + prevCursor: 'prev', + }, totalItems: 10, - nextCursor: 'next', - prevCursor: 'prev', - }; - - const defaultClientResponse = { - entities: [ - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'Test2', - namespace: 'test1', - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'Test1', - namespace: 'test1', - }, - }, - ], - totalItems: 10, - next: jest.fn(), - prev: jest.fn(), }; beforeEach(() => { server.use( rest.get(`${mockBaseUrl}/entities/by-query`, (_, res, ctx) => { - return res(ctx.json(defaultServiceResponse)); + return res(ctx.json(defaultResponse)); }), ); }); it('should fetch entities from correct endpoint', async () => { const response = await client.queryEntities({}, { token }); - expect(response?.entities).toEqual(defaultClientResponse.entities); - expect(response?.totalItems).toEqual(defaultClientResponse.totalItems); + expect(response?.items).toEqual(defaultResponse.items); + expect(response?.totalItems).toEqual(defaultResponse.totalItems); expect(response?.pageInfo.nextCursor).toBeDefined(); expect(response?.pageInfo.prevCursor).toBeDefined(); }); @@ -318,7 +300,7 @@ describe('CatalogClient', () => { const mockedEndpoint = jest .fn() .mockImplementation((_req, res, ctx) => - res(ctx.json({ entities: [], totalItems: 0 })), + res(ctx.json({ items: [], totalItems: 0 })), ); server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); @@ -342,7 +324,7 @@ describe('CatalogClient', () => { { token }, ); - expect(response).toEqual({ entities: [], totalItems: 0 }); + expect(response).toEqual({ items: [], totalItems: 0 }); expect(mockedEndpoint).toHaveBeenCalledTimes(1); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( '?filter=a=1,b=2,b=3,%C3%B6=%3D&filter=a=2&filter=c', @@ -353,7 +335,7 @@ describe('CatalogClient', () => { const mockedEndpoint = jest .fn() .mockImplementation((_req, res, ctx) => - res(ctx.json({ entities: [], totalItems: 0 })), + res(ctx.json({ items: [], totalItems: 0 })), ); server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); @@ -376,7 +358,7 @@ describe('CatalogClient', () => { const mockedEndpoint = jest .fn() .mockImplementation((_req, res, ctx) => - res(ctx.json({ entities: [], totalItems: 0 })), + res(ctx.json({ items: [], totalItems: 0 })), ); server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); @@ -397,7 +379,7 @@ describe('CatalogClient', () => { const mockedEndpoint = jest.fn().mockImplementation((_req, res, ctx) => res( ctx.json({ - entities: [ + items: [ { apiVersion: 'v1', kind: 'CustomKind', @@ -415,10 +397,12 @@ describe('CatalogClient', () => { }, }, ], - nextCursor: 'nextcursor', - prevCursor: 'prevcursor', + pageInfo: { + nextCursor: 'nextcursor', + prevCursor: 'prevcursor', + }, totalItems: 100, - }), + } as QueryEntitiesResponse), ), ); diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 5ef127660b..95998b3ed5 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -424,7 +424,7 @@ export type QueryEntitiesCursorRequest = { */ export type QueryEntitiesResponse = { /* The list of entities for the current request */ - entities: Entity[]; + items: Entity[]; /* The number of entities among all the requests */ totalItems: number; pageInfo: { From 7b370a5dadf45524510a2b809a937b64ede3daa6 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 13:18:27 +0100 Subject: [PATCH 056/417] catalog-client: sortFields to orderFields Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/src/CatalogClient.test.ts | 4 ++-- packages/catalog-client/src/CatalogClient.ts | 6 +++--- packages/catalog-client/src/types/api.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 4992b0d373..f11627d092 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -344,7 +344,7 @@ describe('CatalogClient', () => { fields: ['a', 'b'], limit: 100, query: 'query', - sortFields: [ + orderFields: [ { field: 'metadata.name', order: 'asc' }, { field: 'metadata.uid', order: 'desc' }, ], @@ -367,7 +367,7 @@ describe('CatalogClient', () => { fields: ['a', 'b'], limit: 100, query: 'query', - sortFields: [{ field: 'metadata.name', order: 'asc' }], + orderFields: [{ field: 'metadata.name', order: 'asc' }], cursor: 'cursor', }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index c8bf7e57c2..a380baf6e5 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -214,14 +214,14 @@ export class CatalogClient implements CatalogApi { const params: string[] = []; if (isQueryEntitiesInitialRequest(request)) { - const { fields = [], filter, limit, sortFields, query } = request; + const { fields = [], filter, limit, orderFields, query } = request; params.push(...this.getParams(filter)); if (limit !== undefined) { params.push(`limit=${limit}`); } - if (sortFields !== undefined) { - (Array.isArray(sortFields) ? sortFields : [sortFields]).forEach( + if (orderFields !== undefined) { + (Array.isArray(orderFields) ? orderFields : [orderFields]).forEach( ({ field, order }) => params.push(`sortField=${field},${order}`), ); } diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 95998b3ed5..4a727b7bf0 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -400,7 +400,7 @@ export type QueryEntitiesInitialRequest = { fields?: string[]; limit?: number; filter?: EntityFilterQuery; - sortFields?: EntityOrderQuery; + orderFields?: EntityOrderQuery; query?: string; }; From cf166f403021a7b5f5406eb37f7ebf760347643b Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 13:19:53 +0100 Subject: [PATCH 057/417] catalog-backend: sortFields to orderFields Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 6 +-- .../service/DefaultEntitiesCatalog.test.ts | 10 ++--- .../src/service/DefaultEntitiesCatalog.ts | 44 ++++++++++++------- .../src/service/createRouter.test.ts | 8 ++-- .../request/parseQueryEntitiesParams.test.ts | 4 +- .../request/parseQueryEntitiesParams.ts | 2 +- 6 files changed, 44 insertions(+), 30 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 5591573ee2..6b6ff5b92e 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -227,7 +227,7 @@ export interface QueryEntitiesInitialRequest { fields?: (entity: Entity) => Entity; limit?: number; filter?: EntityFilter; - sortFields?: EntityOrder[]; + orderFields?: EntityOrder[]; query?: string; } @@ -275,11 +275,11 @@ export type Cursor = { * An array of fields used for sorting the data. * For example, [ { field: 'metadata.name', order: 'asc' } ] */ - sortFields: EntityOrder[]; + orderFields: EntityOrder[]; /** * The values of the fields of a specific item used for paginating the data. */ - sortFieldValues: Array; + orderFieldValues: Array; /** * A filter to be applied to the full list of entities. */ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index ab20c0942a..2924c81106 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -767,7 +767,7 @@ describe('DefaultEntitiesCatalog', () => { const request1: QueryEntitiesInitialRequest = { filter, limit, - sortFields: [{ field: 'metadata.name', order: 'asc' }], + orderFields: [{ field: 'metadata.name', order: 'asc' }], }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toEqual([entityFrom('A'), entityFrom('B')]); @@ -912,7 +912,7 @@ describe('DefaultEntitiesCatalog', () => { const request1: QueryEntitiesInitialRequest = { filter, limit, - sortFields: [{ field: 'metadata.name', order: 'desc' }], + orderFields: [{ field: 'metadata.name', order: 'desc' }], }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toEqual([entityFrom('G'), entityFrom('F')]); @@ -1056,7 +1056,7 @@ describe('DefaultEntitiesCatalog', () => { filter, limit: 100, - sortFields: [{ field: 'metadata.name', order: 'asc' }], + orderFields: [{ field: 'metadata.name', order: 'asc' }], query: 'cAt ', }; const response = await catalog.queryEntities(request); @@ -1098,7 +1098,7 @@ describe('DefaultEntitiesCatalog', () => { limit: 0, }; const response = await catalog.queryEntities(request); - expect(response).toEqual({ totalItems: 20, entities: [] }); + expect(response).toEqual({ totalItems: 20, items: [], pageInfo: {} }); }, ); @@ -1127,7 +1127,7 @@ describe('DefaultEntitiesCatalog', () => { // initial request const request1: QueryEntitiesInitialRequest = { limit, - sortFields: [{ field: 'metadata.name', order: 'asc' }], + orderFields: [{ field: 'metadata.name', order: 'asc' }], }; const response1 = await catalog.queryEntities(request1); expect(response1.items).toMatchObject([ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index ba242b7ab5..959fba1851 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -338,26 +338,27 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const db = this.database; const limit = request?.limit ?? 20; - const cursor: Omit & { - sortFieldValues?: (string | null)[]; + const cursor: Omit & { + orderFieldValues?: (string | null)[]; } = { - sortFields: [defaultSortField], + orderFields: [defaultSortField], isPrevious: false, ...parseCursorFromRequest(request), }; const isFetchingBackwards = cursor.isPrevious; - if (cursor.sortFields.length > 1) { + if (cursor.orderFields.length > 1) { this.logger.warn(`Only one sort field is supported, ignoring the rest`); } const sortField: EntityOrder = { ...defaultSortField, - ...cursor.sortFields[0], + ...cursor.orderFields[0], }; - const [prevItemSortFieldValue, prevItemUid] = cursor.sortFieldValues || []; + const [prevItemOrderFieldValue, prevItemUid] = + cursor.orderFieldValues || []; const dbQuery = db('search') .join('final_entities', 'search.entity_id', 'final_entities.entity_id') @@ -379,14 +380,14 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const isOrderingDescending = sortField.order === 'desc'; - if (prevItemSortFieldValue) { + if (prevItemOrderFieldValue) { dbQuery.andWhere( 'value', isFetchingBackwards !== isOrderingDescending ? '<' : '>', - prevItemSortFieldValue, + prevItemOrderFieldValue, ); dbQuery.orWhere(function nested() { - this.where('value', '=', prevItemSortFieldValue).andWhere( + this.where('value', '=', prevItemOrderFieldValue).andWhere( 'search.entity_id', isFetchingBackwards !== isOrderingDescending ? '<' : '>', prevItemUid, @@ -451,7 +452,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { const nextCursor = hasMoreResults ? encodeCursor({ ...cursor, - sortFieldValues: sortFieldsFromRow(lastRow), + orderFieldValues: sortFieldsFromRow(lastRow), firstSortFieldValues, isPrevious: false, totalItems, @@ -464,7 +465,7 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { !isEqual(sortFieldsFromRow(firstRow), cursor.firstSortFieldValues) ? encodeCursor({ ...cursor, - sortFieldValues: sortFieldsFromRow(firstRow), + orderFieldValues: sortFieldsFromRow(firstRow), firstSortFieldValues: cursor.firstSortFieldValues, isPrevious: true, totalItems, @@ -475,7 +476,14 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { .map(e => JSON.parse(e.final_entity!)) .map(e => (request?.fields ? request.fields(e) : e)); - return { items, pageInfo: { prevCursor, nextCursor }, totalItems }; + return { + items, + pageInfo: { + ...(!!prevCursor && { prevCursor }), + ...(!!nextCursor && { nextCursor }), + }, + totalItems, + }; } async removeEntityByUid(uid: string): Promise { @@ -671,10 +679,10 @@ const entityFilterParser: z.ZodSchema = z.lazy(() => ); export const cursorParser: z.ZodSchema = z.object({ - sortFields: z.array( + orderFields: z.array( z.object({ field: z.string(), order: z.enum(['asc', 'desc']) }), ), - sortFieldValues: z.array(z.string().or(z.null())), + orderFieldValues: z.array(z.string().or(z.null())), filter: entityFilterParser.optional(), isPrevious: z.boolean(), query: z.string().optional(), @@ -696,8 +704,12 @@ function parseCursorFromRequest( request?: QueryEntitiesRequest, ): Partial { if (isQueryEntitiesInitialRequest(request)) { - const { filter, sortFields = [defaultSortField], query } = request; - return { filter, sortFields, query }; + const { + filter, + orderFields: sortFields = [defaultSortField], + query, + } = request; + return { filter, orderFields: sortFields, query }; } if (isQueryEntitiesCursorRequest(request)) { try { diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index a35115ac58..91ede00d51 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -153,7 +153,9 @@ describe('createRouter readonly disabled', () => { expect(response.body).toEqual({ items, totalItems: 100, - nextCursor: 'something', + pageInfo: { + nextCursor: 'something', + }, }); }); @@ -181,7 +183,7 @@ describe('createRouter readonly disabled', () => { { allOf: [{ key: 'c', values: ['4'] }] }, ], }, - sortFields: [ + orderFields: [ { field: 'metadata.name', order: 'asc' }, { field: 'metadata.uid', order: 'desc' }, ], @@ -210,7 +212,7 @@ describe('createRouter readonly disabled', () => { expect(response.body).toEqual({ items, totalItems: 100, - nextCursor: 'next', + pageInfo: { nextCursor: 'next' }, }); }); }); diff --git a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts index ab702438c2..3a8bf1b225 100644 --- a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts @@ -36,7 +36,7 @@ describe('parseQueryEntitiesParams', () => { ) as QueryEntitiesInitialRequest; expect(parsedObj.limit).toBe(3); expect(parsedObj.fields).toBeDefined(); - expect(parsedObj.sortFields).toEqual([ + expect(parsedObj.orderFields).toEqual([ { field: 'metadata.name', order: 'desc' }, ]); expect(parsedObj.filter).toBeDefined(); @@ -50,7 +50,7 @@ describe('parseQueryEntitiesParams', () => { ) as QueryEntitiesInitialRequest; expect(parsedObj.limit).toBeUndefined(); expect(parsedObj.fields).toBeUndefined(); - expect(parsedObj.sortFields).toBeUndefined(); + expect(parsedObj.orderFields).toBeUndefined(); expect(parsedObj.filter).toBeUndefined(); expect(parsedObj.query).toBeUndefined(); expect(parsedObj).not.toHaveProperty('authorizationToken'); diff --git a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts index 858189b0d2..0a3da2bd48 100644 --- a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts @@ -47,7 +47,7 @@ export function parseQueryEntitiesParams( fields, filter, limit, - sortFields, + orderFields: sortFields, query, }; From b02b6c3e053c008b9e66ab135f2852f15a697e07 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 13:58:05 +0100 Subject: [PATCH 058/417] catalog-client: move query to fullTextFilterTerm Signed-off-by: Vincenzo Scamporlino --- .../catalog-client/src/CatalogClient.test.ts | 10 +++++++--- packages/catalog-client/src/CatalogClient.ts | 17 +++++++++++++---- packages/catalog-client/src/types/api.ts | 5 ++++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index f11627d092..c235ff1592 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -343,14 +343,16 @@ describe('CatalogClient', () => { await client.queryEntities({ fields: ['a', 'b'], limit: 100, - query: 'query', + fullTextFilter: { + term: 'query', + }, orderFields: [ { field: 'metadata.name', order: 'asc' }, { field: 'metadata.uid', order: 'desc' }, ], }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( - '?limit=100&sortField=metadata.name,asc&sortField=metadata.uid,desc&fields=a,b&query=query', + '?limit=100&sortField=metadata.name,asc&sortField=metadata.uid,desc&fields=a,b&fullTextFilterTerm=query', ); }); @@ -366,7 +368,9 @@ describe('CatalogClient', () => { await client.queryEntities({ fields: ['a', 'b'], limit: 100, - query: 'query', + fullTextFilter: { + term: 'query', + }, orderFields: [{ field: 'metadata.name', order: 'asc' }], cursor: 'cursor', }); diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index a380baf6e5..4984d394d4 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -214,7 +214,13 @@ export class CatalogClient implements CatalogApi { const params: string[] = []; if (isQueryEntitiesInitialRequest(request)) { - const { fields = [], filter, limit, orderFields, query } = request; + const { + fields = [], + filter, + limit, + orderFields, + fullTextFilter, + } = request; params.push(...this.getParams(filter)); if (limit !== undefined) { @@ -229,9 +235,12 @@ export class CatalogClient implements CatalogApi { params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); } - const normalizedQuery = query?.trim(); - if (normalizedQuery) { - params.push(`query=${normalizedQuery}`); + const normalizedFullTextFilterTerm = fullTextFilter?.term?.trim(); + if (normalizedFullTextFilterTerm) { + params.push(`fullTextFilterTerm=${normalizedFullTextFilterTerm}`); + } + if (fullTextFilter?.fields?.length) { + params.push(`fullTextFilterFields=${fullTextFilter.fields.join(',')}`); } } else { const { fields = [], limit, cursor } = request; diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 4a727b7bf0..963e0521a0 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -401,7 +401,10 @@ export type QueryEntitiesInitialRequest = { limit?: number; filter?: EntityFilterQuery; orderFields?: EntityOrderQuery; - query?: string; + fullTextFilter?: { + term: string; + fields?: string[]; + }; }; /** From 5468b81811b82450f69514a497b8860647b3bcb7 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 13:59:50 +0100 Subject: [PATCH 059/417] catalog-backend: move query to fullTextFilterTerm Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 12 +++++-- .../service/DefaultEntitiesCatalog.test.ts | 2 +- .../src/service/DefaultEntitiesCatalog.ts | 10 +++--- .../src/service/createRouter.test.ts | 6 +++- ...ts => parseEntityOrderFieldParams.test.ts} | 34 +++++++++---------- ...rams.ts => parseEntityOrderFieldParams.ts} | 12 +++---- .../request/parseFullTextFilterFields.ts | 28 +++++++++++++++ .../request/parseQueryEntitiesParams.test.ts | 17 ++++++---- .../request/parseQueryEntitiesParams.ts | 19 ++++++++--- 9 files changed, 96 insertions(+), 44 deletions(-) rename plugins/catalog-backend/src/service/request/{parseEntitySortFieldParams.test.ts => parseEntityOrderFieldParams.test.ts} (53%) rename plugins/catalog-backend/src/service/request/{parseEntitySortFieldParams.ts => parseEntityOrderFieldParams.ts} (75%) create mode 100644 plugins/catalog-backend/src/service/request/parseFullTextFilterFields.ts diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 6b6ff5b92e..d182ffdc47 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -228,7 +228,10 @@ export interface QueryEntitiesInitialRequest { limit?: number; filter?: EntityFilter; orderFields?: EntityOrder[]; - query?: string; + fullTextFilter?: { + term: string; + fields?: string[]; + }; } /** @@ -289,9 +292,12 @@ export type Cursor = { */ isPrevious: boolean; /** - * Used for filtering the data by name. + * Used for performing full text filtering on the given fields. */ - query?: string; + fullTextFilter?: { + term: string; + fields?: string[]; + }; /** * The value of the fields of the first returned item used for paginating the data. * The catalog uses this field internally to understand if the beginning diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 2924c81106..5bfb0e0077 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1057,7 +1057,7 @@ describe('DefaultEntitiesCatalog', () => { limit: 100, orderFields: [{ field: 'metadata.name', order: 'asc' }], - query: 'cAt ', + fullTextFilter: { term: 'cAt ' }, }; const response = await catalog.queryEntities(request); expect(response.items).toEqual([ diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 959fba1851..ba59bc55c0 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -368,11 +368,11 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { parseFilter(cursor.filter, dbQuery, db, false, 'search.entity_id'); } - const normalizedQueryByName = cursor.query?.trim(); - if (normalizedQueryByName) { + const normalizedFullTextFilterTerm = cursor.fullTextFilter?.term?.trim(); + if (normalizedFullTextFilterTerm) { dbQuery.andWhereRaw( 'value like ?', - `%${normalizedQueryByName.toLocaleLowerCase('en-US')}%`, + `%${normalizedFullTextFilterTerm.toLocaleLowerCase('en-US')}%`, ); } @@ -707,9 +707,9 @@ function parseCursorFromRequest( const { filter, orderFields: sortFields = [defaultSortField], - query, + fullTextFilter, } = request; - return { filter, orderFields: sortFields, query }; + return { filter, orderFields: sortFields, fullTextFilter }; } if (isQueryEntitiesCursorRequest(request)) { try { diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 91ede00d51..5121e800da 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -166,7 +166,7 @@ describe('createRouter readonly disabled', () => { totalItems: 0, }); const response = await request(app).get( - '/entities/by-query?filter=a=1,a=2,b=3&filter=c=4&sortField=metadata.name,asc&sortField=metadata.uid,desc', + '/entities/by-query?filter=a=1,a=2,b=3&filter=c=4&orderField=metadata.name,asc&orderField=metadata.uid,desc', ); expect(response.status).toEqual(200); @@ -187,6 +187,10 @@ describe('createRouter readonly disabled', () => { { field: 'metadata.name', order: 'asc' }, { field: 'metadata.uid', order: 'desc' }, ], + fullTextFilter: { + fields: undefined, + term: '', + }, }); }); diff --git a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.test.ts b/plugins/catalog-backend/src/service/request/parseEntityOrderFieldParams.test.ts similarity index 53% rename from plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.test.ts rename to plugins/catalog-backend/src/service/request/parseEntityOrderFieldParams.test.ts index 35f7c2cac0..b732163394 100644 --- a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityOrderFieldParams.test.ts @@ -14,31 +14,31 @@ * limitations under the License. */ -import { parseEntitySortFieldParams } from './parseEntitySortFieldParams'; +import { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams'; -describe('parseEntitySortFieldParams', () => { - it('supports no sort fields', () => { - const result = parseEntitySortFieldParams({}); +describe('parseEntityOrderFieldParams', () => { + it('supports no order fields', () => { + const result = parseEntityOrderFieldParams({}); expect(result).toEqual(undefined); }); - it('supports single sortField', () => { - const result = parseEntitySortFieldParams({ - sortField: ['metadata.name,desc'], + it('supports single orderField', () => { + const result = parseEntityOrderFieldParams({ + orderField: ['metadata.name,desc'], })!; expect(result).toEqual([{ field: 'metadata.name', order: 'desc' }]); }); - it('supports single sortField without order', () => { - const result = parseEntitySortFieldParams({ - sortField: ['metadata.name'], + it('supports single orderField without order', () => { + const result = parseEntityOrderFieldParams({ + orderField: ['metadata.name'], })!; expect(result).toEqual([{ field: 'metadata.name' }]); }); - it('supports multiple sort fields', () => { - const result = parseEntitySortFieldParams({ - sortField: ['metadata.name,desc', 'metadata.uid,asc'], + it('supports multiple order fields', () => { + const result = parseEntityOrderFieldParams({ + orderField: ['metadata.name,desc', 'metadata.uid,asc'], }); expect(result).toEqual([ @@ -47,11 +47,11 @@ describe('parseEntitySortFieldParams', () => { ]); }); - it('throws if sortField order is not valid', () => { + it('throws if orderField order is not valid', () => { expect(() => - parseEntitySortFieldParams({ - sortField: ['metadata.name,desc', 'metadata.uid,invalid'], + parseEntityOrderFieldParams({ + orderField: ['metadata.name,desc', 'metadata.uid,invalid'], }), - ).toThrow(/Invalid sort field order/); + ).toThrow(/Invalid order field order/); }); }); diff --git a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts b/plugins/catalog-backend/src/service/request/parseEntityOrderFieldParams.ts similarity index 75% rename from plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts rename to plugins/catalog-backend/src/service/request/parseEntityOrderFieldParams.ts index 5efa2de05e..5ab8cbfcf9 100644 --- a/plugins/catalog-backend/src/service/request/parseEntitySortFieldParams.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityOrderFieldParams.ts @@ -18,19 +18,19 @@ import { InputError } from '@backstage/errors'; import { EntityOrder } from '../../catalog/types'; import { parseStringsParam } from './common'; -export function parseEntitySortFieldParams( +export function parseEntityOrderFieldParams( params: Record, ): EntityOrder[] | undefined { - const sortFieldStrings = parseStringsParam(params.sortField, 'sortField'); - if (!sortFieldStrings) { + const orderFieldStrings = parseStringsParam(params.orderField, 'orderField'); + if (!orderFieldStrings) { return undefined; } - return sortFieldStrings.map(sortFieldString => { - const [field, order] = sortFieldString.split(','); + return orderFieldStrings.map(orderFieldString => { + const [field, order] = orderFieldString.split(','); if (order !== undefined && !isOrder(order)) { - throw new InputError('Invalid sort field order, must be asc or desc'); + throw new InputError('Invalid order field order, must be asc or desc'); } return { field, order }; }); diff --git a/plugins/catalog-backend/src/service/request/parseFullTextFilterFields.ts b/plugins/catalog-backend/src/service/request/parseFullTextFilterFields.ts new file mode 100644 index 0000000000..02ba5864fc --- /dev/null +++ b/plugins/catalog-backend/src/service/request/parseFullTextFilterFields.ts @@ -0,0 +1,28 @@ +import { parseStringParam } from './common'; + +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export function parseFullTextFilterFields(params: Record) { + const fullTextFilterFields = parseStringParam( + params.fullTextFilterFields, + 'fullTextFilterFields', + ); + if (!fullTextFilterFields) { + return undefined; + } + + return fullTextFilterFields.split(','); +} diff --git a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts index 3a8bf1b225..da2d7e474c 100644 --- a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts @@ -28,8 +28,9 @@ describe('parseQueryEntitiesParams', () => { fields: ['kind'], limit: '3', filter: ['a=1', 'b=2'], - sortField: ['metadata.name,desc'], - query: 'query', + orderField: ['metadata.name,desc'], + fullTextFilterTerm: 'query', + fullTextFilterFields: 'metadata.name,metadata.namespace', }; const parsedObj = parseQueryEntitiesParams( validRequest, @@ -40,7 +41,10 @@ describe('parseQueryEntitiesParams', () => { { field: 'metadata.name', order: 'desc' }, ]); expect(parsedObj.filter).toBeDefined(); - expect(parsedObj.query).toBe('query'); + expect(parsedObj.fullTextFilter).toEqual({ + term: 'query', + fields: ['metadata.name', 'metadata.namespace'], + }); expect(parsedObj).not.toHaveProperty('authorizationToken'); expect(parsedObj).not.toHaveProperty('cursor'); }); @@ -52,7 +56,7 @@ describe('parseQueryEntitiesParams', () => { expect(parsedObj.fields).toBeUndefined(); expect(parsedObj.orderFields).toBeUndefined(); expect(parsedObj.filter).toBeUndefined(); - expect(parsedObj.query).toBeUndefined(); + expect(parsedObj.fullTextFilter).toEqual({ term: '', fields: undefined }); expect(parsedObj).not.toHaveProperty('authorizationToken'); expect(parsedObj).not.toHaveProperty('cursor'); }); @@ -62,9 +66,10 @@ describe('parseQueryEntitiesParams', () => { limit: 'asd', }, { filter: 3 }, - { sortField: ['metadata.uid,diagonal'] }, + { orderField: ['metadata.uid,diagonal'] }, { fields: [4] }, - { query: [] }, + { fullTextFilterTerm: [] }, + { fullTextFilterFields: 3 }, ])('should throw if some parameter is not valid %p', params => { expect(() => parseQueryEntitiesParams(params)).toThrow(); }); diff --git a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts index 0a3da2bd48..67a4629c1c 100644 --- a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts @@ -21,8 +21,9 @@ import { } from '../../catalog/types'; import { parseIntegerParam, parseStringParam } from './common'; import { parseEntityFilterParams } from './parseEntityFilterParams'; -import { parseEntitySortFieldParams } from './parseEntitySortFieldParams'; +import { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams'; import { parseEntityTransformParams } from './parseEntityTransformParams'; +import { parseFullTextFilterFields } from './parseFullTextFilterFields'; export function parseQueryEntitiesParams( params: Record, @@ -40,15 +41,23 @@ export function parseQueryEntitiesParams( } const filter = parseEntityFilterParams(params); - const query = parseStringParam(params.query, 'query'); - const sortFields = parseEntitySortFieldParams(params); + const fullTextFilterTerm = parseStringParam( + params.fullTextFilterTerm, + 'fullTextFilterTerm', + ); + const fullTextFilterFields = parseFullTextFilterFields(params); + + const orderFields = parseEntityOrderFieldParams(params); const response: Omit = { fields, filter, limit, - orderFields: sortFields, - query, + orderFields, + fullTextFilter: { + term: fullTextFilterTerm || '', + fields: fullTextFilterFields, + }, }; return response; From 8c030b1826c9f6629612c0f87f900f04d285519d Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 14:04:27 +0100 Subject: [PATCH 060/417] catalog: split changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/breezy-bees-care.md | 5 +++++ .changeset/silly-suits-run.md | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 .changeset/breezy-bees-care.md diff --git a/.changeset/breezy-bees-care.md b/.changeset/breezy-bees-care.md new file mode 100644 index 0000000000..9a5b59fe03 --- /dev/null +++ b/.changeset/breezy-bees-care.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': minor +--- + +Add `queryEntities` method to `CatalogApi`. diff --git a/.changeset/silly-suits-run.md b/.changeset/silly-suits-run.md index 2fc731f2a4..ec371e4077 100644 --- a/.changeset/silly-suits-run.md +++ b/.changeset/silly-suits-run.md @@ -1,8 +1,7 @@ --- -'@backstage/catalog-client': minor '@backstage/plugin-catalog-backend': minor --- Add /entities/by-query endpoint returning paginated entities. -The endpoint supports cursor base pagination and server side sorting of the entities by name or uid. +The endpoint supports cursor base pagination and server side sorting of the entities From 88740bed619452c57853fe13ee5d2c041a187f10 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 14:05:49 +0100 Subject: [PATCH 061/417] catalog-client: improve queryEntities example Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/src/types/api.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 963e0521a0..ee6579efca 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -477,14 +477,16 @@ export interface CatalogApi { * * @remarks * - * Example: + * @example * * ``` * const response = await catalogClient.queryEntities({ * filter: [{ kind: 'group' }], * limit: 20, - * query: 'A', - * sortFields: { field: 'metadata.name' order: 'asc' }, + * fullTextFilter: { + * term: 'A', + * } + * orderFields: { field: 'metadata.name' order: 'asc' }, * }); * ``` * From 095e755d9b5d2a61dd42848154868a5ccc69c20b Mon Sep 17 00:00:00 2001 From: Jasper Herzberg Date: Thu, 12 Jan 2023 14:11:33 +0100 Subject: [PATCH 062/417] feat: add api definition dialog Signed-off-by: Jasper Herzberg --- .changeset/old-foxes-shave.md | 5 + plugins/api-docs/api-report.md | 7 + .../ApiDefinitionDialog.tsx | 176 ++++++++++++++++++ .../components/ApiDefinitionDialog/index.ts | 17 ++ .../src/components/ApisCards/presets.tsx | 36 +++- plugins/api-docs/src/components/index.ts | 1 + 6 files changed, 236 insertions(+), 6 deletions(-) create mode 100644 .changeset/old-foxes-shave.md create mode 100644 plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx create mode 100644 plugins/api-docs/src/components/ApiDefinitionDialog/index.ts diff --git a/.changeset/old-foxes-shave.md b/.changeset/old-foxes-shave.md new file mode 100644 index 0000000000..4cd0808103 --- /dev/null +++ b/.changeset/old-foxes-shave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Add ApiDefinitionDialog component for fast access to the API definition in ProvidedApiCards and ConsumedApiCards. diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index 0872d97355..98a4f2cd96 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -20,6 +20,13 @@ import { UserListFilterKind } from '@backstage/plugin-catalog-react'; // @public (undocumented) export const ApiDefinitionCard: () => JSX.Element; +// @public +export function ApiDefinitionDialog(props: { + open: boolean; + entity: ApiEntity; + onClose: () => void; +}): JSX.Element; + // @public (undocumented) export type ApiDefinitionWidget = { type: string; diff --git a/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx b/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx new file mode 100644 index 0000000000..2f82a0cc5a --- /dev/null +++ b/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx @@ -0,0 +1,176 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ApiEntity } from '@backstage/catalog-model'; +import { useApi } from '@backstage/core-plugin-api'; +import { BackstageTheme } from '@backstage/theme'; +import { + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + makeStyles, + Tab, + Tabs, + Typography, +} from '@material-ui/core'; +import React, { useEffect } from 'react'; +import { apiDocsConfigRef } from '../../config'; +import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget'; + +const useStyles = makeStyles(theme => ({ + fullHeightDialog: { + height: 'calc(100% - 64px)', + }, + root: { + display: 'flex', + flexGrow: 1, + width: '100%', + height: '100%', + }, + tabs: { + borderRight: `1px solid ${theme.palette.divider}`, + flexShrink: 0, + }, + tabContents: { + flexGrow: 1, + overflowX: 'auto', + }, + title: { + color: theme.palette.text.primary, + wordBreak: 'break-word', + fontSize: theme.typography.h3.fontSize, + marginBottom: 0, + }, + type: { + textTransform: 'uppercase', + fontSize: 11, + opacity: 0.8, + marginBottom: theme.spacing(1), + color: theme.palette.text.primary, + }, +})); + +function TabPanel(props: { + children?: React.ReactNode; + index: number; + value: number; +}) { + const { children, value, index, ...other } = props; + const classes = useStyles(); + return ( + + ); +} + +function a11yProps(index: number) { + return { + id: `vertical-tab-${index}`, + 'aria-controls': `vertical-tabpanel-${index}`, + }; +} + +/** + * A dialog that lets users inspect the API definition. + * + * @public + */ +export function ApiDefinitionDialog(props: { + open: boolean; + entity: ApiEntity; + onClose: () => void; +}) { + const { open, entity, onClose } = props; + const [activeTab, setActiveTab] = React.useState(0); + const classes = useStyles(); + + useEffect(() => { + setActiveTab(0); + }, [open]); + + const config = useApi(apiDocsConfigRef); + const definitionWidget = config.getApiDefinitionWidget(entity); + + let tabIndex = 0; + let tabPanelIndex = 0; + + return ( + + + + API - {definitionWidget?.title ?? 'Raw'} + + + {entity.metadata.title ?? entity.metadata.name} + + + + setActiveTab(newValue)} + aria-label="API definition options" + className={classes.tabs} + > + {definitionWidget ? ( + + ) : null} + + + + {definitionWidget ? ( + + {definitionWidget.component(entity.spec.definition)} + + ) : null} + + + + + + + + + ); +} diff --git a/plugins/api-docs/src/components/ApiDefinitionDialog/index.ts b/plugins/api-docs/src/components/ApiDefinitionDialog/index.ts new file mode 100644 index 0000000000..28e3388bcc --- /dev/null +++ b/plugins/api-docs/src/components/ApiDefinitionDialog/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ApiDefinitionDialog } from './ApiDefinitionDialog'; diff --git a/plugins/api-docs/src/components/ApisCards/presets.tsx b/plugins/api-docs/src/components/ApisCards/presets.tsx index 4a0a0f429e..b1ef39c113 100644 --- a/plugins/api-docs/src/components/ApisCards/presets.tsx +++ b/plugins/api-docs/src/components/ApisCards/presets.tsx @@ -15,10 +15,13 @@ */ import { ApiEntity } from '@backstage/catalog-model'; -import { EntityTable } from '@backstage/plugin-catalog-react'; -import React from 'react'; -import { ApiTypeTitle } from '../ApiDefinitionCard'; import { TableColumn } from '@backstage/core-components'; +import { EntityTable } from '@backstage/plugin-catalog-react'; +import ExtensionIcon from '@material-ui/icons/Extension'; +import { ToggleButton } from '@material-ui/lab'; +import React, { useState } from 'react'; +import { ApiTypeTitle } from '../ApiDefinitionCard'; +import { ApiDefinitionDialog } from '../ApiDefinitionDialog'; export function createSpecApiTypeColumn(): TableColumn { return { @@ -28,9 +31,29 @@ export function createSpecApiTypeColumn(): TableColumn { }; } -// TODO: This could be moved to plugin-catalog-react if we wouldn't have a -// special createSpecApiTypeColumn. But this is required to use ApiTypeTitle to -// resolve the display name of an entity. Is the display name really worth it? +const ApiDefinitionButton = ({ apiEntity }: { apiEntity: ApiEntity }) => { + const [dialogOpen, setDialogOpen] = useState(false); + + return ( + <> + setDialogOpen(!dialogOpen)}> + + + setDialogOpen(false)} + /> + + ); +}; + +function createApiDefinitionColumn(): TableColumn { + return { + title: 'API Definition', + render: entity => , + }; +} export const apiEntityColumns: TableColumn[] = [ EntityTable.columns.createEntityRefColumn({ defaultKind: 'API' }), @@ -39,4 +62,5 @@ export const apiEntityColumns: TableColumn[] = [ createSpecApiTypeColumn(), EntityTable.columns.createSpecLifecycleColumn(), EntityTable.columns.createMetadataDescriptionColumn(), + createApiDefinitionColumn(), ]; diff --git a/plugins/api-docs/src/components/index.ts b/plugins/api-docs/src/components/index.ts index ea40076af4..ba3747d42f 100644 --- a/plugins/api-docs/src/components/index.ts +++ b/plugins/api-docs/src/components/index.ts @@ -16,6 +16,7 @@ export * from './ApiExplorerPage'; export * from './ApiDefinitionCard'; +export * from './ApiDefinitionDialog'; export * from './ApisCards'; export * from './AsyncApiDefinitionWidget'; export * from './ComponentsCards'; From 718811bafb19bf94a071bd933e8ba0b550c44ceb Mon Sep 17 00:00:00 2001 From: pamelin Date: Fri, 3 Feb 2023 14:54:54 +0000 Subject: [PATCH 063/417] fix: Use app-config.yaml from master Signed-off-by: pamelin --- app-config.yaml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index 743ca31c4b..dd72051189 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -118,11 +118,6 @@ proxy: headers: Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' - '/stackstorm': - target: https://your.stackstorm.instance.com/api - headers: - St2-Api-Key: ${ST2_API_KEY} - organization: name: My Company @@ -448,6 +443,3 @@ gocd: permission: enabled: true - -stackstorm: - webUrl: https://your.stackstorm.webui.com From 221ad6e88777e927beebeea4dae58aae3c4e8405 Mon Sep 17 00:00:00 2001 From: pamelin Date: Fri, 3 Feb 2023 15:22:05 +0000 Subject: [PATCH 064/417] fix: add api-report.md for stackstorm api Signed-off-by: pamelin --- plugins/stackstorm/api-report.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 plugins/stackstorm/api-report.md diff --git a/plugins/stackstorm/api-report.md b/plugins/stackstorm/api-report.md new file mode 100644 index 0000000000..2a28388766 --- /dev/null +++ b/plugins/stackstorm/api-report.md @@ -0,0 +1,26 @@ +## API Report File for "@backstage/plugin-stackstorm" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { RouteRef } from '@backstage/core-plugin-api'; + +// Warning: (ae-missing-release-tag) "StackstormPage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const StackstormPage: () => JSX.Element; + +// Warning: (ae-missing-release-tag) "stackstormPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const stackstormPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// (No @packageDocumentation comment for this package) +``` From 7f4ce79b077c5e4905faf83b6cf0416a901c7e18 Mon Sep 17 00:00:00 2001 From: pamelin Date: Fri, 3 Feb 2023 15:39:25 +0000 Subject: [PATCH 065/417] fix: add api-report.md for stackstorm api Signed-off-by: pamelin --- plugins/stackstorm/api-report.md | 12 ++++-------- plugins/stackstorm/src/index.ts | 7 +++++++ plugins/stackstorm/src/plugin.ts | 11 +++++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/plugins/stackstorm/api-report.md b/plugins/stackstorm/api-report.md index 2a28388766..3e3d79fe27 100644 --- a/plugins/stackstorm/api-report.md +++ b/plugins/stackstorm/api-report.md @@ -3,17 +3,15 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +/// + import { BackstagePlugin } from '@backstage/core-plugin-api'; import { RouteRef } from '@backstage/core-plugin-api'; -// Warning: (ae-missing-release-tag) "StackstormPage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const StackstormPage: () => JSX.Element; -// Warning: (ae-missing-release-tag) "stackstormPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const stackstormPlugin: BackstagePlugin< { root: RouteRef; @@ -21,6 +19,4 @@ export const stackstormPlugin: BackstagePlugin< {}, {} >; - -// (No @packageDocumentation comment for this package) ``` diff --git a/plugins/stackstorm/src/index.ts b/plugins/stackstorm/src/index.ts index aff9e2d78a..b64ae207e4 100644 --- a/plugins/stackstorm/src/index.ts +++ b/plugins/stackstorm/src/index.ts @@ -13,4 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** + * A Backstage plugin that integrates towards StackStorm + * + * @packageDocumentation + */ + export { stackstormPlugin, StackstormPage } from './plugin'; diff --git a/plugins/stackstorm/src/plugin.ts b/plugins/stackstorm/src/plugin.ts index 012c78372b..74df4a0b66 100644 --- a/plugins/stackstorm/src/plugin.ts +++ b/plugins/stackstorm/src/plugin.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { createApiFactory, createPlugin, @@ -24,6 +25,11 @@ import { stackStormApiRef, StackStormClient } from './api'; import { rootRouteRef } from './routes'; +/** + * The Backstage plugin that holds stackstorm specific components + * + * @public + */ export const stackstormPlugin = createPlugin({ id: 'stackstorm', apis: [ @@ -45,6 +51,11 @@ export const stackstormPlugin = createPlugin({ }, }); +/** + * A component to display a stackstorm home page + * + * @public + */ export const StackstormPage = stackstormPlugin.provide( createRoutableExtension({ name: 'StackstormPage', From a7469138be3601324e38c94782d3fccda9040fcd Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 17:44:42 +0100 Subject: [PATCH 066/417] catalog-client: new cursors in api report Signed-off-by: Vincenzo Scamporlino --- packages/catalog-client/api-report.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index b8a6a17a09..22feceabec 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -261,8 +261,11 @@ export type QueryEntitiesInitialRequest = { fields?: string[]; limit?: number; filter?: EntityFilterQuery; - sortFields?: EntityOrderQuery; - query?: string; + orderFields?: EntityOrderQuery; + fullTextFilter?: { + term: string; + fields?: string[]; + }; }; // @public @@ -272,10 +275,12 @@ export type QueryEntitiesRequest = // @public export type QueryEntitiesResponse = { - entities: Entity[]; + items: Entity[]; totalItems: number; - nextCursor?: string; - prevCursor?: string; + pageInfo: { + nextCursor?: string; + prevCursor?: string; + }; }; // @public From 9e3915e40c70042255df507391647f9363aa0698 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 17:45:56 +0100 Subject: [PATCH 067/417] catalog-client: permission queryEntities cursor requests Signed-off-by: Vincenzo Scamporlino --- plugins/catalog-backend/src/catalog/types.ts | 8 +- .../service/AuthorizedEntitiesCatalog.test.ts | 149 ++++++++++++++++++ .../src/service/AuthorizedEntitiesCatalog.ts | 57 +++++-- .../service/DefaultEntitiesCatalog.test.ts | 20 --- .../src/service/DefaultEntitiesCatalog.ts | 34 ++-- .../src/service/createRouter.test.ts | 51 +++++- .../src/service/createRouter.ts | 23 ++- .../request/parseQueryEntitiesParams.test.ts | 28 +++- .../request/parseQueryEntitiesParams.ts | 4 +- plugins/catalog-backend/src/service/util.ts | 44 ++++++ 10 files changed, 340 insertions(+), 78 deletions(-) diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index d182ffdc47..62c8fad605 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -179,7 +179,7 @@ export interface EntitiesCatalog { * * @param request */ - queryEntities(request?: QueryEntitiesRequest): Promise; + queryEntities(request: QueryEntitiesRequest): Promise; /** * Removes a single entity. @@ -242,7 +242,7 @@ export interface QueryEntitiesCursorRequest { authorizationToken?: string; fields?: (entity: Entity) => Entity; limit?: number; - cursor: string; + cursor: Cursor; } /** @@ -258,11 +258,11 @@ export interface QueryEntitiesResponse { /** * The cursor of the next pagination request. */ - nextCursor?: string; + nextCursor?: Cursor; /** * The cursor of the previous pagination request. */ - prevCursor?: string; + prevCursor?: Cursor; }; /** * the total number of entities matching the current filters. diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts index e559f5fd49..2ee47dae19 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts @@ -20,6 +20,8 @@ import { createConditionTransformer } from '@backstage/plugin-permission-node'; import { isEntityKind } from '../permissions/rules/isEntityKind'; import { CatalogPermissionRule } from '../permissions/rules'; import { AuthorizedEntitiesCatalog } from './AuthorizedEntitiesCatalog'; +import { Cursor, EntityFilter, QueryEntitiesResponse } from '../catalog/types'; +import { Entity } from '@backstage/catalog-model'; describe('AuthorizedEntitiesCatalog', () => { const fakeCatalog = { @@ -157,6 +159,153 @@ describe('AuthorizedEntitiesCatalog', () => { }); }); + describe('queryEntities', () => { + it('returns empty response on DENY', async () => { + fakePermissionApi.authorizeConditional.mockResolvedValue([ + { result: AuthorizeResult.DENY }, + ]); + const catalog = createCatalog(); + + await expect( + catalog.queryEntities({ + authorizationToken: 'abcd', + filter: { key: 'kind', values: ['b'] }, + }), + ).resolves.toEqual({ + items: [], + pageInfo: {}, + totalItems: 0, + }); + + expect(fakeCatalog.queryEntities).not.toHaveBeenCalled(); + }); + + it('calls underlying catalog method on ALLOW', async () => { + fakePermissionApi.authorizeConditional.mockResolvedValue([ + { result: AuthorizeResult.ALLOW }, + ]); + const catalog = createCatalog(); + + await catalog.queryEntities({ + authorizationToken: 'abcd', + filter: { key: 'kind', values: ['b'] }, + }); + + expect(fakeCatalog.queryEntities).toHaveBeenCalledWith({ + authorizationToken: 'abcd', + filter: { key: 'kind', values: ['b'] }, + }); + }); + + it('calls underlying catalog method with correct filter on CONDITIONAL', async () => { + fakePermissionApi.authorizeConditional.mockResolvedValue([ + { + result: AuthorizeResult.CONDITIONAL, + conditions: { + rule: 'IS_ENTITY_KIND', + params: { kinds: ['b'] }, + }, + }, + ]); + + const requestFilter: EntityFilter = { key: 'name', values: ['name'] }; + + const entities = [ + { + kind: 'component', + namespace: 'default', + name: 'a', + } as unknown as Entity, + { + kind: 'component', + namespace: 'default', + name: 'b1', + } as unknown as Entity, + ]; + + fakeCatalog.queryEntities.mockResolvedValue({ + items: entities, + pageInfo: { + nextCursor: { + isPrevious: false, + orderFieldValues: ['xxx', null], + filter: { allOf: [{ key: 'kind', values: ['b'] }, requestFilter] }, + }, + prevCursor: { + isPrevious: true, + orderFieldValues: ['a', null], + filter: { allOf: [{ key: 'kind', values: ['b'] }, requestFilter] }, + }, + }, + totalItems: 4, + } as QueryEntitiesResponse); + const catalog = createCatalog(isEntityKind); + + let response = await catalog.queryEntities({ + authorizationToken: 'abcd', + filter: { key: 'name', values: ['name'] }, + }); + + expect(fakeCatalog.queryEntities).toHaveBeenCalledWith({ + authorizationToken: 'abcd', + filter: { allOf: [{ key: 'kind', values: ['b'] }, requestFilter] }, + }); + + expect(response).toEqual({ + items: entities, + totalItems: 4, + pageInfo: { + nextCursor: { + isPrevious: false, + filter: requestFilter, + orderFieldValues: ['xxx', null], + }, + prevCursor: { + isPrevious: true, + filter: requestFilter, + orderFieldValues: ['a', null], + }, + }, + }); + + const cursor: Cursor = { + filter: requestFilter, + orderFields: [{ field: 'name', order: 'asc' }], + isPrevious: false, + orderFieldValues: ['a', null], + }; + response = await catalog.queryEntities({ + authorizationToken: 'abcd', + cursor, + }); + + expect(fakeCatalog.queryEntities).toHaveBeenNthCalledWith(2, { + authorizationToken: 'abcd', + cursor: { + ...cursor, + filter: { allOf: [{ key: 'kind', values: ['b'] }, requestFilter] }, + }, + }); + + expect(response).toEqual({ + items: entities, + totalItems: 4, + pageInfo: { + nextCursor: { + isPrevious: false, + filter: requestFilter, + orderFieldValues: ['xxx', null], + }, + prevCursor: { + isPrevious: true, + filter: requestFilter, + orderFieldValues: ['a', null], + }, + }, + }); + }); + }); + describe('removeEntityByUid', () => { it('throws error on DENY', async () => { fakeCatalog.entities.mockResolvedValue({ diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index f9ec058879..2649b45260 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -26,6 +26,7 @@ import { } from '@backstage/plugin-permission-common'; import { ConditionTransformer } from '@backstage/plugin-permission-node'; import { + Cursor, EntitiesBatchRequest, EntitiesBatchResponse, EntitiesCatalog, @@ -39,7 +40,7 @@ import { QueryEntitiesResponse, } from '../catalog/types'; import { basicEntityFilter } from './request/basicEntityFilter'; -import { isQueryEntitiesInitialRequest } from './util'; +import { isQueryEntitiesCursorRequest } from './util'; export class AuthorizedEntitiesCatalog implements EntitiesCatalog { constructor( @@ -110,12 +111,12 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { } async queryEntities( - request?: QueryEntitiesRequest, + request: QueryEntitiesRequest, ): Promise { const authorizeDecision = ( await this.permissionApi.authorizeConditional( [{ permission: catalogEntityReadPermission }], - { token: request?.authorizationToken }, + { token: request.authorizationToken }, ) )[0]; @@ -132,14 +133,52 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { authorizeDecision.conditions, ); - return this.entitiesCatalog.queryEntities({ - ...request, - ...(isQueryEntitiesInitialRequest(request) && { - filter: request?.filter + let permissionedRequest: QueryEntitiesRequest; + let requestFilter: EntityFilter | undefined; + + if (isQueryEntitiesCursorRequest(request)) { + requestFilter = request.cursor.filter; + + permissionedRequest = { + ...request, + cursor: { + ...request.cursor, + filter: request.cursor.filter + ? { allOf: [permissionFilter, request.cursor.filter] } + : permissionFilter, + }, + }; + } else { + permissionedRequest = { + ...request, + filter: request.filter ? { allOf: [permissionFilter, request.filter] } : permissionFilter, - }), - }); + }; + requestFilter = request.filter; + } + + const response = await this.entitiesCatalog.queryEntities( + permissionedRequest, + ); + + const prevCursor: Cursor | undefined = response.pageInfo.prevCursor && { + ...response.pageInfo.prevCursor, + filter: requestFilter, + }; + + const nextCursor: Cursor | undefined = response.pageInfo.nextCursor && { + ...response.pageInfo.nextCursor, + filter: requestFilter, + }; + + return { + ...response, + pageInfo: { + prevCursor, + nextCursor, + }, + }; } return this.entitiesCatalog.queryEntities(request); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index 5bfb0e0077..740f5b2558 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -1291,26 +1291,6 @@ describe('DefaultEntitiesCatalog', () => { expect(response5.totalItems).toBe(6); }, ); - - it('should throw in case of malformed cursor', async () => { - const catalog = new DefaultEntitiesCatalog({ - database: knex, - logger: getVoidLogger(), - stitcher, - }); - - const cursor = Buffer.from( - JSON.stringify({ filter: 'notavalidfilter' }), - 'utf8', - ).toString('base64'); - const request: QueryEntitiesCursorRequest = { - cursor, - }; - - await expect(catalog.queryEntities(request)).rejects.toThrow( - Error('Malformed cursor, could not be parsed'), - ); - }); }); describe('removeEntityByUid', () => { diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index ba59bc55c0..a635a9a7d2 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -333,10 +333,10 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { } async queryEntities( - request?: QueryEntitiesRequest, + request: QueryEntitiesRequest, ): Promise { const db = this.database; - const limit = request?.limit ?? 20; + const limit = request.limit ?? 20; const cursor: Omit & { orderFieldValues?: (string | null)[]; @@ -449,32 +449,32 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { firstRow?.entity_id, ]; - const nextCursor = hasMoreResults - ? encodeCursor({ + const nextCursor: Cursor | undefined = hasMoreResults + ? { ...cursor, orderFieldValues: sortFieldsFromRow(lastRow), firstSortFieldValues, isPrevious: false, totalItems, - }) + } : undefined; - const prevCursor = + const prevCursor: Cursor | undefined = !isInitialRequest && rows.length > 0 && !isEqual(sortFieldsFromRow(firstRow), cursor.firstSortFieldValues) - ? encodeCursor({ + ? { ...cursor, orderFieldValues: sortFieldsFromRow(firstRow), firstSortFieldValues: cursor.firstSortFieldValues, isPrevious: true, totalItems, - }) + } : undefined; const items = rows .map(e => JSON.parse(e.final_entity!)) - .map(e => (request?.fields ? request.fields(e) : e)); + .map(e => (request.fields ? request.fields(e) : e)); return { items, @@ -690,16 +690,6 @@ export const cursorParser: z.ZodSchema = z.object({ totalItems: z.number().optional(), }); -function encodeCursor(cursor: Cursor) { - const json = JSON.stringify(cursor); - return Buffer.from(json, 'utf8').toString('base64'); -} - -function decodeCursor(encodedCursor: string) { - const json = Buffer.from(encodedCursor, 'base64').toString('utf8'); - return cursorParser.parse(JSON.parse(json)); -} - function parseCursorFromRequest( request?: QueryEntitiesRequest, ): Partial { @@ -712,11 +702,7 @@ function parseCursorFromRequest( return { filter, orderFields: sortFields, fullTextFilter }; } if (isQueryEntitiesCursorRequest(request)) { - try { - return decodeCursor(request.cursor); - } catch { - throw new InputError('Malformed cursor, could not be parsed'); - } + return request.cursor; } return {}; } diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 5121e800da..f2f87fa800 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -25,7 +25,7 @@ import { } from '@backstage/catalog-model'; import express from 'express'; import request from 'supertest'; -import { EntitiesCatalog } from '../catalog/types'; +import { Cursor, EntitiesCatalog } from '../catalog/types'; import { LocationInput, LocationService, RefreshService } from './types'; import { basicEntityFilter } from './request'; import { createRouter } from './createRouter'; @@ -37,6 +37,7 @@ import { import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; import { CatalogProcessingOrchestrator } from '../processing/types'; import { z } from 'zod'; +import { encodeCursor } from './util'; describe('createRouter readonly disabled', () => { let entitiesCatalog: jest.Mocked; @@ -145,7 +146,7 @@ describe('createRouter readonly disabled', () => { entitiesCatalog.queryEntities.mockResolvedValueOnce({ items, totalItems: 100, - pageInfo: { nextCursor: 'something' }, + pageInfo: { nextCursor: mockCursor() }, }); const response = await request(app).get('/entities/by-query'); @@ -154,7 +155,7 @@ describe('createRouter readonly disabled', () => { items, totalItems: 100, pageInfo: { - nextCursor: 'something', + nextCursor: expect.any(String), }, }); }); @@ -202,23 +203,50 @@ describe('createRouter readonly disabled', () => { entitiesCatalog.queryEntities.mockResolvedValueOnce({ items, totalItems: 100, - pageInfo: { nextCursor: 'next' }, + pageInfo: { nextCursor: mockCursor() }, }); + const cursor = mockCursor({ totalItems: 100, isPrevious: false }); + const response = await request(app).get( - '/entities/by-query?cursor=something', + `/entities/by-query?cursor=${encodeCursor(cursor)}`, ); expect(entitiesCatalog.queryEntities).toHaveBeenCalledTimes(1); expect(entitiesCatalog.queryEntities).toHaveBeenCalledWith({ - cursor: 'something', + cursor, }); expect(response.status).toEqual(200); expect(response.body).toEqual({ items, totalItems: 100, - pageInfo: { nextCursor: 'next' }, + pageInfo: { nextCursor: expect.any(String) }, }); }); + + it('should throw in case of malformed cursor', async () => { + const items: Entity[] = [ + { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, + ]; + + entitiesCatalog.queryEntities.mockResolvedValueOnce({ + items, + totalItems: 100, + pageInfo: { nextCursor: mockCursor() }, + }); + + let response = await request(app).get( + `/entities/by-query?cursor=${Buffer.from( + JSON.stringify({ bad: 'cursor' }), + 'utf8', + ).toString('base64')}`, + ); + expect(response.status).toEqual(400); + expect(response.body.error.message).toMatch(/Malformed cursor/); + + response = await request(app).get(`/entities/by-query?cursor=badcursor`); + expect(response.status).toEqual(400); + expect(response.body.error.message).toMatch(/Malformed cursor/); + }); }); describe('GET /entities/by-uid/:uid', () => { @@ -908,3 +936,12 @@ describe('NextRouter permissioning', () => { }); }); }); + +function mockCursor(partialCursor?: Partial): Cursor { + return { + orderFields: [], + orderFieldValues: [], + isPrevious: false, + ...partialCursor, + }; +} diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index 7603f6955d..849096c601 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -46,6 +46,7 @@ import { parseEntityOrderParams } from './request/parseEntityOrderParams'; import { LocationService, RefreshOptions, RefreshService } from './types'; import { disallowReadonlyMode, + encodeCursor, locationInput, validateRequestBody, } from './util'; @@ -132,12 +133,24 @@ export async function createRouter( res.json(entities); }) .get('/entities/by-query', async (req, res) => { - const response = await entitiesCatalog.queryEntities({ - ...parseQueryEntitiesParams(req.query), - authorizationToken: getBearerToken(req.header('authorization')), - }); + const { items, pageInfo, totalItems } = + await entitiesCatalog.queryEntities({ + ...parseQueryEntitiesParams(req.query), + authorizationToken: getBearerToken(req.header('authorization')), + }); - res.json(response); + res.json({ + items, + totalItems, + pageInfo: { + ...(pageInfo.nextCursor && { + nextCursor: encodeCursor(pageInfo.nextCursor), + }), + ...(pageInfo.prevCursor && { + prevCursor: encodeCursor(pageInfo.prevCursor), + }), + }, + }); }) .get('/entities/by-uid/:uid', async (req, res) => { const { uid } = req.params; diff --git a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts index da2d7e474c..43ba218eac 100644 --- a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.test.ts @@ -15,9 +15,11 @@ */ import { + Cursor, QueryEntitiesCursorRequest, QueryEntitiesInitialRequest, } from '../../catalog/types'; +import { encodeCursor } from '../util'; import { parseQueryEntitiesParams } from './parseQueryEntitiesParams'; describe('parseQueryEntitiesParams', () => { @@ -77,29 +79,40 @@ describe('parseQueryEntitiesParams', () => { describe('cursor request', () => { it('should parse all the defined params', () => { + const cursor: Cursor = { + totalItems: 100, + orderFields: [], + orderFieldValues: [], + isPrevious: false, + }; const validRequest = { authorizationToken: 'to_not_be_returned', fields: ['kind'], limit: '3', - cursor: 'cursor', + cursor: encodeCursor(cursor), }; const parsedObj = parseQueryEntitiesParams( validRequest, ) as QueryEntitiesCursorRequest; expect(parsedObj.limit).toBe(3); expect(parsedObj.fields).toBeDefined(); - expect(parsedObj.cursor).toBe('cursor'); + expect(parsedObj.cursor).toEqual(cursor); }); it('should ignore unknown params', () => { + const cursor: Cursor = { + totalItems: 100, + orderFields: [], + orderFieldValues: [], + isPrevious: false, + }; const validRequest = { authorizationToken: 'to_not_be_returned', fields: ['kind'], limit: '3', - cursor: 'cursor', + cursor: encodeCursor(cursor), filter: ['a=1', 'b=2'], - sortField: 'sortField', - sortFieldOrder: 'desc', + orderField: 'orderField,desc', query: 'query', }; const parsedObj = parseQueryEntitiesParams( @@ -107,10 +120,9 @@ describe('parseQueryEntitiesParams', () => { ) as QueryEntitiesCursorRequest; expect(parsedObj.limit).toBe(3); expect(parsedObj.fields).toBeDefined(); - expect(parsedObj.cursor).toBe('cursor'); + expect(parsedObj.cursor).toEqual(cursor); expect(parsedObj).not.toHaveProperty('filter'); - expect(parsedObj).not.toHaveProperty('sortField'); - expect(parsedObj).not.toHaveProperty('sortFieldOrder'); + expect(parsedObj).not.toHaveProperty('orderField'); expect(parsedObj).not.toHaveProperty('query'); }); diff --git a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts index 67a4629c1c..ae8b649d13 100644 --- a/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts +++ b/plugins/catalog-backend/src/service/request/parseQueryEntitiesParams.ts @@ -19,6 +19,7 @@ import { QueryEntitiesInitialRequest, QueryEntitiesRequest, } from '../../catalog/types'; +import { decodeCursor } from '../util'; import { parseIntegerParam, parseStringParam } from './common'; import { parseEntityFilterParams } from './parseEntityFilterParams'; import { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams'; @@ -32,8 +33,9 @@ export function parseQueryEntitiesParams( const limit = parseIntegerParam(params.limit, 'limit'); const cursor = parseStringParam(params.cursor, 'cursor'); if (cursor) { + const decodedCursor = decodeCursor(cursor); const response: Omit = { - cursor, + cursor: decodedCursor, fields, limit, }; diff --git a/plugins/catalog-backend/src/service/util.ts b/plugins/catalog-backend/src/service/util.ts index 1ab154a86d..699bca2fc9 100644 --- a/plugins/catalog-backend/src/service/util.ts +++ b/plugins/catalog-backend/src/service/util.ts @@ -19,6 +19,8 @@ import { Request } from 'express'; import lodash from 'lodash'; import { z } from 'zod'; import { + Cursor, + EntityFilter, QueryEntitiesCursorRequest, QueryEntitiesInitialRequest, QueryEntitiesRequest, @@ -88,3 +90,45 @@ export function isQueryEntitiesCursorRequest( } return !!(input as QueryEntitiesCursorRequest).cursor; } + +const entityFilterParser: z.ZodSchema = z.lazy(() => + z + .object({ + key: z.string(), + values: z.array(z.string()).optional(), + }) + .or(z.object({ not: entityFilterParser })) + .or(z.object({ anyOf: z.array(entityFilterParser) })) + .or(z.object({ allOf: z.array(entityFilterParser) })), +); + +export const cursorParser: z.ZodSchema = z.object({ + orderFields: z.array( + z.object({ field: z.string(), order: z.enum(['asc', 'desc']) }), + ), + orderFieldValues: z.array(z.string().or(z.null())), + filter: entityFilterParser.optional(), + isPrevious: z.boolean(), + query: z.string().optional(), + firstSortFieldValues: z.array(z.string().or(z.null())).optional(), + totalItems: z.number().optional(), +}); + +export function encodeCursor(cursor: Cursor) { + const json = JSON.stringify(cursor); + return Buffer.from(json, 'utf8').toString('base64'); +} + +export function decodeCursor(encodedCursor: string) { + try { + const data = Buffer.from(encodedCursor, 'base64').toString('utf8'); + const result = cursorParser.safeParse(JSON.parse(data)); + + if (!result.success) { + throw new InputError(`Malformed cursor: ${result.error}`); + } + return result.data; + } catch (e) { + throw new InputError(`Malformed cursor: ${e}`); + } +} From bd82c2242cd97477f829909810cf36698123b723 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Feb 2023 17:48:44 +0100 Subject: [PATCH 068/417] catalog-backend define default limit Signed-off-by: Vincenzo Scamporlino --- .../catalog-backend/src/service/DefaultEntitiesCatalog.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index a635a9a7d2..f983d7496b 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -62,6 +62,8 @@ const defaultSortField: EntityOrder = { order: 'asc', }; +const DEFAULT_LIMIT = 20; + function parsePagination(input?: EntityPagination): { limit?: number; offset?: number; @@ -336,7 +338,8 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { request: QueryEntitiesRequest, ): Promise { const db = this.database; - const limit = request.limit ?? 20; + + const limit = request.limit ?? DEFAULT_LIMIT; const cursor: Omit & { orderFieldValues?: (string | null)[]; From db10b6ef6583677fa492bb4a8b79aa5d06c16eb9 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 6 Feb 2023 08:54:01 +0100 Subject: [PATCH 069/417] feat(auth): add auth provider for Bitbucket Server Signed-off-by: Katharina Sick --- .changeset/pretty-jars-peel.md | 9 + docs/auth/bitbucket/provider.md | 2 +- docs/auth/bitbucketServer/provider.md | 52 +++ docs/auth/index.md | 1 + packages/app-defaults/src/defaults/apis.ts | 15 + packages/app/src/identityProviders.ts | 7 + packages/backend/src/plugins/auth.ts | 7 + .../BitbucketServerAuth.test.ts | 51 +++ .../bitbucketServer/BitbucketServerAuth.ts | 66 +++ .../auth/bitbucketServer/index.ts | 18 + .../auth/bitbucketServer/types.ts | 35 ++ .../src/apis/implementations/auth/index.ts | 1 + .../src/apis/definitions/auth.ts | 15 + .../src/providers/bitbucketServer/index.ts | 18 + .../bitbucketServer/provider.test.ts | 377 ++++++++++++++++++ .../src/providers/bitbucketServer/provider.ts | 297 ++++++++++++++ plugins/auth-backend/src/providers/index.ts | 1 + .../auth-backend/src/providers/providers.ts | 3 + .../AuthProviders/DefaultProviderSettings.tsx | 9 + 19 files changed, 983 insertions(+), 1 deletion(-) create mode 100644 .changeset/pretty-jars-peel.md create mode 100644 docs/auth/bitbucketServer/provider.md create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts create mode 100644 packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts create mode 100644 plugins/auth-backend/src/providers/bitbucketServer/index.ts create mode 100644 plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts create mode 100644 plugins/auth-backend/src/providers/bitbucketServer/provider.ts diff --git a/.changeset/pretty-jars-peel.md b/.changeset/pretty-jars-peel.md new file mode 100644 index 0000000000..639d4565ed --- /dev/null +++ b/.changeset/pretty-jars-peel.md @@ -0,0 +1,9 @@ +--- +'@backstage/core-plugin-api': minor +'@backstage/app-defaults': minor +'@backstage/core-app-api': minor +'@backstage/plugin-user-settings': minor +'@backstage/plugin-auth-backend': minor +--- + +Added a Bitbucket Server Auth Provider and added its API to the app defaults diff --git a/docs/auth/bitbucket/provider.md b/docs/auth/bitbucket/provider.md index 36859dab45..b03201893c 100644 --- a/docs/auth/bitbucket/provider.md +++ b/docs/auth/bitbucket/provider.md @@ -61,7 +61,7 @@ how this is done. Note that for the Bitbucket provider, you'll want to use factory. The `@backstage/plugin-auth-backend` plugin also comes with two built-in -resolves that can be used if desired. The first one is the +resolvers that can be used if desired. The first one is the `bitbucketUsernameSignInResolver`, which identifies users by matching their Bitbucket username to `bitbucket.org/username` annotations of `User` entities in the catalog. Note that you must populate your catalog with matching entities or diff --git a/docs/auth/bitbucketServer/provider.md b/docs/auth/bitbucketServer/provider.md new file mode 100644 index 0000000000..96c7db263e --- /dev/null +++ b/docs/auth/bitbucketServer/provider.md @@ -0,0 +1,52 @@ +--- +id: provider +title: Bitbucket Server Authentication Provider +sidebar_label: Bitbucket Server +description: Adding Bitbucket Server OAuth as an authentication provider in Backstage +--- + +The Backstage `core-plugin-api` package comes with a Bitbucket Server authentication provider that can authenticate +users using Bitbucket Server. This does **NOT** work with Bitbucket Cloud. + +## Create an Application Link in Bitbucket Server + +To add Bitbucket Server authentication, you must create an outgoing application link. Follow the steps described in +the [Bitbucket Server documentation](https://confluence.atlassian.com/bitbucketserver/configure-an-outgoing-link-1108483656.html) +to create one. + +## Configuration + +The provider configuration can then be added to your `app-config.yaml` under the root `auth` configuration: + +```yaml +auth: + environment: development + providers: + bitbucketServer: + development: + host: bitbucket.org + clientId: ${AUTH_BITBUCKET_SERVER_CLIENT_ID} + clientSecret: ${AUTH_BITBUCKET_SERVER_CLIENT_SECRET} +``` + +The Bitbucket Server provider is a structure with two configuration keys: + +- `clientId`: The client ID that was generated by Bitbucket, e.g. `b0f868455c15dcdff5c5fb5d173ae684`. +- `clientSecret`: The client secret tied to the generated client ID. + +## Adding the provider to the Backstage frontend + +To add the provider to the frontend, add the `bitbucketServerAuthApi` reference and `SignInPage` component as shown +in [Adding the provider to the sign-in page](../index.md#adding-the-provider-to-the-sign-in-page). + +## Using Bitbucket Server for sign-in + +In order to use the Bitbucket Server provider for sign-in, you must configure it with a `signIn.resolver`. See +the [Sign-In Resolver documentation](../identity-resolver.md) for more details on how this is done. Note that for the +Bitbucket Server provider, you'll want to use `bitbucketServer` as the provider ID, +and `providers.bitbucketServer.create` for the provider factory. + +The `@backstage/plugin-auth-backend` plugin also comes with a built-in resolver that can be used if desired. +The `emailMatchingUserEntityProfileEmail` identifies users by matching their Bitbucket Server email address to the email +address of `User` entities in the catalog. Note that you must populate your catalog with matching entities or users will +not be able to sign in with this resolver. diff --git a/docs/auth/index.md b/docs/auth/index.md index fa185c0c23..8e15830aa8 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -18,6 +18,7 @@ Backstage comes with many common authentication providers in the core library: - [Auth0](auth0/provider.md) - [Azure](microsoft/provider.md) - [Bitbucket](bitbucket/provider.md) +- [Bitbucket Server](bitbucketServer/provider.md) - [Cloudflare Access](cloudflare/access.md) - [GitHub](github/provider.md) - [GitLab](gitlab/provider.md) diff --git a/packages/app-defaults/src/defaults/apis.ts b/packages/app-defaults/src/defaults/apis.ts index 3f5cfc1c58..d3ebddfb84 100644 --- a/packages/app-defaults/src/defaults/apis.ts +++ b/packages/app-defaults/src/defaults/apis.ts @@ -25,6 +25,7 @@ import { GitlabAuth, MicrosoftAuth, BitbucketAuth, + BitbucketServerAuth, OAuthRequestManager, WebStorage, UrlPatternDiscovery, @@ -53,6 +54,7 @@ import { configApiRef, oneloginAuthApiRef, bitbucketAuthApiRef, + bitbucketServerAuthApiRef, atlassianAuthApiRef, } from '@backstage/core-plugin-api'; import { @@ -219,6 +221,19 @@ export const apis = [ environment: configApi.getOptionalString('auth.environment'), }), }), + createApiFactory({ + api: bitbucketServerAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi }) => + BitbucketServerAuth.create({ + discoveryApi, + oauthRequestApi, + defaultScopes: ['REPO_READ'], + }), + }), createApiFactory({ api: atlassianAuthApiRef, deps: { diff --git a/packages/app/src/identityProviders.ts b/packages/app/src/identityProviders.ts index 5f8c0faf47..66f1460210 100644 --- a/packages/app/src/identityProviders.ts +++ b/packages/app/src/identityProviders.ts @@ -22,6 +22,7 @@ import { microsoftAuthApiRef, oneloginAuthApiRef, bitbucketAuthApiRef, + bitbucketServerAuthApiRef, } from '@backstage/core-plugin-api'; export const providers = [ @@ -67,4 +68,10 @@ export const providers = [ message: 'Sign In using Bitbucket', apiRef: bitbucketAuthApiRef, }, + { + id: 'bitbucket-server-auth-provider', + title: 'Bitbucket Server', + message: 'Sign In using Bitbucket Server', + apiRef: bitbucketServerAuthApiRef, + }, ]; diff --git a/packages/backend/src/plugins/auth.ts b/packages/backend/src/plugins/auth.ts index 8beda6f3fb..0d92315f92 100644 --- a/packages/backend/src/plugins/auth.ts +++ b/packages/backend/src/plugins/auth.ts @@ -114,6 +114,13 @@ export default async function createPlugin( }, }), + bitbucketServer: providers.bitbucketServer.create({ + signIn: { + resolver: + providers.bitbucketServer.resolvers.emailMatchingUserEntityProfileEmail(), + }, + }), + // This is an example of how to configure the OAuth2Proxy provider as well // as how to sign a user in without a matching user entity in the catalog. // You can try it out using `` diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts new file mode 100644 index 0000000000..32e7755a00 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.test.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import MockOAuthApi from '../../OAuthRequestApi/MockOAuthApi'; +import { UrlPatternDiscovery } from '../../DiscoveryApi'; +import BitbucketServerAuth from './BitbucketServerAuth'; + +const getSession = jest.fn(); + +jest.mock('../../../../lib/AuthSessionManager', () => ({ + ...(jest.requireActual('../../../../lib/AuthSessionManager') as any), + RefreshingAuthSessionManager: class { + getSession = getSession; + }, +})); + +describe('BitbucketServerAuth', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + it.each([ + ['PUBLIC_REPOS', ['PUBLIC_REPOS']], + ['PROJECT_ADMIN REPO_READ', ['PROJECT_ADMIN', 'REPO_READ']], + [ + 'PROJECT_ADMIN REPO_READ ACCOUNT_WRITE', + ['PROJECT_ADMIN', 'REPO_READ', 'ACCOUNT_WRITE'], + ], + ])(`should normalize scopes correctly - %p`, (scope, scopes) => { + const bitbucketServerAuth = BitbucketServerAuth.create({ + oauthRequestApi: new MockOAuthApi(), + discoveryApi: UrlPatternDiscovery.compile('http://example.com'), + }); + + bitbucketServerAuth.getAccessToken(scope); + expect(getSession).toHaveBeenCalledWith({ scopes: new Set(scopes) }); + }); +}); diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts new file mode 100644 index 0000000000..dc50eff6ab --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/BitbucketServerAuth.ts @@ -0,0 +1,66 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BackstageIdentityResponse, + bitbucketServerAuthApiRef, + ProfileInfo, +} from '@backstage/core-plugin-api'; + +import { OAuthApiCreateOptions } from '../types'; +import { OAuth2 } from '../oauth2'; + +export type BitbucketServerAuthResponse = { + providerInfo: { + accessToken: string; + scope: string; + expiresInSeconds: number; + }; + profile: ProfileInfo; + backstageIdentity: BackstageIdentityResponse; +}; + +const DEFAULT_PROVIDER = { + id: 'bitbucketServer', + title: 'Bitbucket Server', + icon: () => null, +}; + +/** + * Implements the OAuth flow to Bitbucket Server. + * @public + */ +export default class BitbucketServerAuth { + static create( + options: OAuthApiCreateOptions, + ): typeof bitbucketServerAuthApiRef.T { + const { + discoveryApi, + environment = 'development', + provider = DEFAULT_PROVIDER, + oauthRequestApi, + defaultScopes = ['PROJECT_ADMIN'], + } = options; + + return OAuth2.create({ + discoveryApi, + oauthRequestApi, + provider, + environment, + defaultScopes, + }); + } +} diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts new file mode 100644 index 0000000000..5fcb8f72f2 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './types'; +export { default as BitbucketServerAuth } from './BitbucketServerAuth'; diff --git a/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts new file mode 100644 index 0000000000..1041aa8110 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/bitbucketServer/types.ts @@ -0,0 +1,35 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ProfileInfo, + BackstageIdentityResponse, +} from '@backstage/core-plugin-api'; + +/** + * Session information for Bitbucket Server auth. + * + * @public + */ +export type BitbucketServerSession = { + providerInfo: { + accessToken: string; + scopes: Set; + expiresAt?: Date; + }; + profile: ProfileInfo; + backstageIdentity: BackstageIdentityResponse; +}; diff --git a/packages/core-app-api/src/apis/implementations/auth/index.ts b/packages/core-app-api/src/apis/implementations/auth/index.ts index c4cf520db5..b54e0424da 100644 --- a/packages/core-app-api/src/apis/implementations/auth/index.ts +++ b/packages/core-app-api/src/apis/implementations/auth/index.ts @@ -23,5 +23,6 @@ export * from './saml'; export * from './microsoft'; export * from './onelogin'; export * from './bitbucket'; +export * from './bitbucketServer'; export * from './atlassian'; export type { OAuthApiCreateOptions, AuthApiCreateOptions } from './types'; diff --git a/packages/core-plugin-api/src/apis/definitions/auth.ts b/packages/core-plugin-api/src/apis/definitions/auth.ts index 163ae74806..43597639b6 100644 --- a/packages/core-plugin-api/src/apis/definitions/auth.ts +++ b/packages/core-plugin-api/src/apis/definitions/auth.ts @@ -412,6 +412,21 @@ export const bitbucketAuthApiRef: ApiRef< id: 'core.auth.bitbucket', }); +/** + * Provides authentication towards Bitbucket Server APIs. + * + * @public + * @remarks + * + * See {@link https://confluence.atlassian.com/bitbucketserver/bitbucket-oauth-2-0-provider-api-1108483661.html#BitbucketOAuth2.0providerAPI-scopes} + * for a full list of supported scopes. + */ +export const bitbucketServerAuthApiRef: ApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +> = createApiRef({ + id: 'core.auth.bitbucket-server', +}); + /** * Provides authentication towards Atlassian APIs. * diff --git a/plugins/auth-backend/src/providers/bitbucketServer/index.ts b/plugins/auth-backend/src/providers/bitbucketServer/index.ts new file mode 100644 index 0000000000..cef12cd50d --- /dev/null +++ b/plugins/auth-backend/src/providers/bitbucketServer/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { bitbucketServer } from './provider'; +export type { BitbucketServerOAuthResult } from './provider'; diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts new file mode 100644 index 0000000000..127ca71a17 --- /dev/null +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -0,0 +1,377 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as helpers from '../../lib/passport/PassportStrategyHelper'; +import { makeProfileInfo } from '../../lib/passport/PassportStrategyHelper'; +import { AuthResolverContext } from '../types'; +import { + BitbucketServerAuthProvider, + BitbucketServerOAuthResult, +} from './provider'; +import { commonByEmailResolver } from '../resolvers'; + +jest.mock('../../lib/passport/PassportStrategyHelper', () => { + return { + ...jest.requireActual('../../lib/passport/PassportStrategyHelper'), + executeFrameHandlerStrategy: jest.fn(), + executeRefreshTokenStrategy: jest.fn(), + executeFetchUserProfileStrategy: jest.fn(), + }; +}); + +const mockFrameHandler = jest.spyOn( + helpers, + 'executeFrameHandlerStrategy', +) as unknown as jest.MockedFunction< + () => Promise<{ + result: BitbucketServerOAuthResult; + privateInfo: { refreshToken?: string }; + }> +>; + +const passportProfile = { + id: '123', + username: 'john.doe', + provider: 'bitubcketServer', + displayName: 'John Doe', + emails: [{ value: 'john@doe.com' }], + photos: [{ value: 'https://bitbucket.org/user/123/avatar' }], +}; + +const mockFetchUserRequests = ( + failOnWhoAmI: boolean = false, + whoAmIValue: string = passportProfile.username, + failOnGetUser: boolean = false, + getUserOk: boolean = true, + avatarUrl: string = '/user/123/avatar', + setDisplayName: boolean = true, + setUserName: boolean = true, +) => { + const fetchMock = global.fetch as jest.Mock; + if (failOnWhoAmI) { + fetchMock.mockRejectedValueOnce(() => {}); + } else { + fetchMock.mockResolvedValueOnce({ + headers: { get: jest.fn(() => whoAmIValue) }, + }); + } + if (failOnGetUser) { + fetchMock.mockRejectedValueOnce(() => {}); + } else { + fetchMock.mockResolvedValueOnce({ + ok: getUserOk, + json: () => ({ + name: setUserName ? 'john.doe' : undefined, + emailAddress: 'john@doe.com', + id: 123, + displayName: setDisplayName ? 'John Doe' : undefined, + active: true, + slug: 'john.doe', + type: 'NORMAL', + links: { + self: [ + { + href: 'https://bitbucket.org/users/john.doe', + }, + ], + }, + avatarUrl: avatarUrl, + }), + }); + } +}; + +describe('BitbucketServerAuthProvider', () => { + const originalFetch = global.fetch; + + beforeEach(() => { + global.fetch = jest.fn(); + }); + + afterEach(() => { + global.fetch = originalFetch; + }); + + const provider = new BitbucketServerAuthProvider({ + resolverContext: { + signInWithCatalogUser: jest.fn(info => { + return { + token: `token-for-user:${info.filter['spec.profile.email']}`, + }; + }), + } as unknown as AuthResolverContext, + signInResolver: commonByEmailResolver, + authHandler: async ({ fullProfile }) => ({ + profile: makeProfileInfo(fullProfile), + }), + callbackUrl: 'mock', + clientId: 'mock', + clientSecret: 'mock', + host: 'bitbucket.org', + authorizationUrl: 'mock', + tokenUrl: 'mock', + }); + + describe('when transforming to type OAuthResponse', () => { + it('should map to a valid response', async () => { + mockFetchUserRequests(); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + it('should throw if whoami fails', async () => { + mockFetchUserRequests(true); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the username of the logged in user`, + ); + }); + it('should throw if whoami returns an invalid response', async () => { + mockFetchUserRequests(false, ''); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the username of the logged in user`, + ); + }); + it('should throw if get user fails', async () => { + mockFetchUserRequests(false, passportProfile.username, true); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the user '${passportProfile.username}'`, + ); + }); + it('should throw if get user is not ok', async () => { + mockFetchUserRequests(false, passportProfile.username, false, false); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + + await expect(provider.handler({} as any)).rejects.toThrow( + `Failed to retrieve the user '${passportProfile.username}'`, + ); + }); + it('should not set an avatar url if not given', async () => { + mockFetchUserRequests(false, passportProfile.username, false, true, ''); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + it('should fallback to the username if no displayName is given', async () => { + mockFetchUserRequests( + false, + passportProfile.username, + false, + true, + '/user/123/avatar', + false, + ); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'john.doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + it('should fallback to the user id if no name is given', async () => { + mockFetchUserRequests( + false, + passportProfile.username, + false, + true, + '/user/123/avatar', + false, + false, + ); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + + const expected = { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: '123', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }; + + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: {}, + }); + const { response } = await provider.handler({} as any); + expect(response).toEqual(expected); + }); + }); + + describe('when authenticating', () => { + it('should forward the refresh token', async () => { + mockFetchUserRequests(); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: { refreshToken: 'refresh-token' }, + }); + + const response = await provider.handler({} as any); + + const expected = { + response: { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }, + refreshToken: 'refresh-token', + }; + + expect(response).toEqual(expected); + }); + it('should forward a new refresh token on refresh', async () => { + mockFetchUserRequests(); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; + const params = { scope: 'REPO_READ' }; + const mockRefreshToken = jest.spyOn( + helpers, + 'executeRefreshTokenStrategy', + ) as unknown as jest.MockedFunction<() => Promise<{}>>; + mockRefreshToken.mockResolvedValueOnce({ + accessToken, + refreshToken: 'dont-forget-to-send-refresh', + params, + }); + mockFrameHandler.mockResolvedValueOnce({ + result: { fullProfile: passportProfile, accessToken, params }, + privateInfo: { refreshToken: 'refresh-token' }, + }); + + const expected = { + response: { + backstageIdentity: { + token: 'token-for-user:john@doe.com', + }, + providerInfo: { + accessToken: '19xasczxcm9n7gacn9jdgm19me', + scope: 'REPO_READ', + }, + profile: { + email: 'john@doe.com', + displayName: 'John Doe', + picture: 'https://bitbucket.org/user/123/avatar', + }, + }, + refreshToken: 'dont-forget-to-send-refresh', + }; + const response = await provider.refresh({ scope: 'REPO_WRITE' } as any); + + expect(response).toEqual(expected); + }); + }); +}); diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts new file mode 100644 index 0000000000..397f63733f --- /dev/null +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -0,0 +1,297 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + encodeState, + OAuthAdapter, + OAuthEnvironmentHandler, + OAuthHandlers, + OAuthProviderOptions, + OAuthRefreshRequest, + OAuthResponse, + OAuthStartRequest, +} from '../../lib/oauth'; +import { Strategy as OAuth2Strategy, VerifyCallback } from 'passport-oauth2'; +import { + executeFetchUserProfileStrategy, + executeFrameHandlerStrategy, + executeRedirectStrategy, + executeRefreshTokenStrategy, + makeProfileInfo, +} from '../../lib/passport'; +import { + AuthHandler, + AuthResolverContext, + OAuthStartResponse, + SignInResolver, +} from '../types'; +import express from 'express'; +import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; +import { PassportProfile } from '../../lib/passport/types'; +import { commonByEmailResolver } from '../resolvers'; + +type PrivateInfo = { + refreshToken: string; +}; + +export type BitbucketServerOAuthResult = { + fullProfile: PassportProfile; + params: { + scope: string; + access_token?: string; + token_type?: string; + expires_in?: number; + }; + accessToken: string; + refreshToken?: string; +}; + +export type BitbucketServerAuthProviderOptions = OAuthProviderOptions & { + host: string; + authorizationUrl: string; + tokenUrl: string; + authHandler: AuthHandler; + signInResolver?: SignInResolver; + resolverContext: AuthResolverContext; +}; + +export class BitbucketServerAuthProvider implements OAuthHandlers { + private readonly signInResolver?: SignInResolver; + private readonly authHandler: AuthHandler; + private readonly resolverContext: AuthResolverContext; + private readonly strategy: OAuth2Strategy; + private readonly host: string; + + constructor(options: BitbucketServerAuthProviderOptions) { + this.signInResolver = options.signInResolver; + this.authHandler = options.authHandler; + this.resolverContext = options.resolverContext; + this.strategy = new OAuth2Strategy( + { + authorizationURL: options.authorizationUrl, + tokenURL: options.tokenUrl, + clientID: options.clientId, + clientSecret: options.clientSecret, + callbackURL: options.callbackUrl, + }, + ( + accessToken: string, + refreshToken: string, + params: any, + fullProfile: PassportProfile, + done: VerifyCallback, + ) => { + done(undefined, { fullProfile, params, accessToken }, { refreshToken }); + }, + ); + this.host = options.host; + } + + async start(req: OAuthStartRequest): Promise { + return await executeRedirectStrategy(req, this.strategy, { + accessType: 'offline', + prompt: 'consent', + scope: req.scope, + state: encodeState(req.state), + }); + } + + async handler( + req: express.Request, + ): Promise<{ response: OAuthResponse; refreshToken?: string }> { + const { result, privateInfo } = await executeFrameHandlerStrategy< + BitbucketServerOAuthResult, + PrivateInfo + >(req, this.strategy); + + return { + response: await this.handleResult(result), + refreshToken: privateInfo.refreshToken, + }; + } + + async refresh( + req: OAuthRefreshRequest, + ): Promise<{ response: OAuthResponse; refreshToken?: string }> { + const { accessToken, refreshToken, params } = + await executeRefreshTokenStrategy( + this.strategy, + req.refreshToken, + req.scope, + ); + const fullProfile = await executeFetchUserProfileStrategy( + this.strategy, + accessToken, + ); + return { + response: await this.handleResult({ + fullProfile, + params, + accessToken, + }), + refreshToken, + }; + } + + private async handleResult( + result: BitbucketServerOAuthResult, + ): Promise { + // The OAuth2 strategy does not return a user profile -> let's fetch it before calling the auth handler + result.fullProfile = await this.fetchProfile(result); + const { profile } = await this.authHandler(result, this.resolverContext); + + let backstageIdentity = undefined; + if (this.signInResolver) { + backstageIdentity = await this.signInResolver( + { result, profile }, + this.resolverContext, + ); + } + + return { + providerInfo: { + accessToken: result.accessToken, + scope: result.params.scope, + expiresInSeconds: result.params.expires_in, + }, + profile, + backstageIdentity, + }; + } + + private async fetchProfile( + result: BitbucketServerOAuthResult, + ): Promise { + // Get current user name + let whoAmIResponse; + try { + whoAmIResponse = await fetch( + `https://${this.host}/plugins/servlet/applinks/whoami`, + { + headers: { + Authorization: `Bearer ${result.accessToken}`, + }, + }, + ); + } catch (e) { + throw new Error(`Failed to retrieve the username of the logged in user`); + } + + // A response.ok check here would be worthless as the Bitbucket API always returns 200 OK for this call + const username = whoAmIResponse.headers.get('X-Ausername'); + if (!username) { + throw new Error(`Failed to retrieve the username of the logged in user`); + } + + let userResponse; + try { + userResponse = await fetch( + `https://${this.host}/rest/api/latest/users/${username}?avatarSize=256`, + { + headers: { + Authorization: `Bearer ${result.accessToken}`, + }, + }, + ); + } catch (e) { + throw new Error(`Failed to retrieve the user '${username}'`); + } + + if (!userResponse.ok) { + throw new Error(`Failed to retrieve the user '${username}'`); + } + + const user = await userResponse.json(); + + return { + provider: 'bitbucketServer', + id: user.id.toString(), + displayName: user.displayName, + username: user.name, + emails: [ + { + value: user.emailAddress, + }, + ], + avatarUrl: user.avatarUrl + ? `https://${this.host}${user.avatarUrl}` + : undefined, + }; + } +} + +export const bitbucketServer = createAuthProviderIntegration({ + create(options?: { + /** + * The profile transformation function used to verify and convert the auth response + * into the profile that will be presented to the user. + */ + authHandler?: AuthHandler; + + /** + * Configure sign-in for this provider, without it the provider can not be used to sign users in. + */ + signIn?: { + /** + * Maps an auth result to a Backstage identity for the user. + */ + resolver: SignInResolver; + }; + }) { + return ({ providerId, globalConfig, config, resolverContext }) => + OAuthEnvironmentHandler.mapConfig(config, envConfig => { + const clientId = envConfig.getString('clientId'); + const clientSecret = envConfig.getString('clientSecret'); + const host = envConfig.getString('host'); + const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); + const callbackUrl = + customCallbackUrl || + `${globalConfig.baseUrl}/${providerId}/handler/frame`; + const authorizationUrl = `https://${host}/rest/oauth2/latest/authorize`; + const tokenUrl = `https://${host}/rest/oauth2/latest/token`; + + const authHandler: AuthHandler = + options?.authHandler + ? options.authHandler + : async ({ fullProfile }) => ({ + profile: makeProfileInfo(fullProfile), + }); + + const provider = new BitbucketServerAuthProvider({ + callbackUrl, + clientId, + clientSecret, + host, + authorizationUrl, + tokenUrl, + authHandler, + signInResolver: options?.signIn?.resolver, + resolverContext, + }); + + return OAuthAdapter.fromConfig(globalConfig, provider, { + providerId, + callbackUrl, + }); + }); + }, + resolvers: { + /** + * Looks up the user by matching their email to the entity email. + */ + emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, + }, +}); diff --git a/plugins/auth-backend/src/providers/index.ts b/plugins/auth-backend/src/providers/index.ts index 67d3a62990..a922065fd8 100644 --- a/plugins/auth-backend/src/providers/index.ts +++ b/plugins/auth-backend/src/providers/index.ts @@ -19,6 +19,7 @@ export type { BitbucketOAuthResult, BitbucketPassportProfile, } from './bitbucket'; +export type { BitbucketServerOAuthResult } from './bitbucketServer'; export type { CloudflareAccessClaims, CloudflareAccessGroup, diff --git a/plugins/auth-backend/src/providers/providers.ts b/plugins/auth-backend/src/providers/providers.ts index b2795c25f0..aa630b7481 100644 --- a/plugins/auth-backend/src/providers/providers.ts +++ b/plugins/auth-backend/src/providers/providers.ts @@ -31,6 +31,7 @@ import { okta } from './okta'; import { onelogin } from './onelogin'; import { saml } from './saml'; import { AuthProviderFactory } from './types'; +import { bitbucketServer } from './bitbucketServer'; /** * All built-in auth provider integrations. @@ -42,6 +43,7 @@ export const providers = Object.freeze({ auth0, awsAlb, bitbucket, + bitbucketServer, cfAccess, gcpIap, github, @@ -76,5 +78,6 @@ export const defaultAuthProviderFactories: { onelogin: onelogin.create(), awsalb: awsAlb.create(), bitbucket: bitbucket.create(), + bitbucketServer: bitbucketServer.create(), atlassian: atlassian.create(), }; diff --git a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx index f8e1fb190c..772ec80982 100644 --- a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx +++ b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx @@ -24,6 +24,7 @@ import { oktaAuthApiRef, microsoftAuthApiRef, bitbucketAuthApiRef, + bitbucketServerAuthApiRef, atlassianAuthApiRef, oneloginAuthApiRef, } from '@backstage/core-plugin-api'; @@ -99,6 +100,14 @@ export const DefaultProviderSettings = (props: { icon={Star} /> )} + {configuredProviders.includes('bitbucketServer') && ( + + )} ); }; From 8940c2727986cf51f818571075f9ecf66c4329c1 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 6 Feb 2023 12:04:37 +0100 Subject: [PATCH 070/417] Add API report Signed-off-by: Katharina Sick --- plugins/auth-backend/api-report.md | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 88cb33863e..e25ed18dfe 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -16,6 +16,7 @@ import { GetEntitiesRequest } from '@backstage/catalog-client'; import { IncomingHttpHeaders } from 'http'; import { JsonValue } from '@backstage/types'; import { Logger } from 'winston'; +import passport from 'passport'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; @@ -132,6 +133,21 @@ export type BitbucketPassportProfile = Profile & { }; }; +// Warning: (ae-missing-release-tag) "BitbucketServerOAuthResult" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type BitbucketServerOAuthResult = { + fullProfile: PassportProfile; + params: { + scope: string; + access_token?: string; + token_type?: string; + expires_in?: number; + }; + accessToken: string; + refreshToken?: string; +}; + // @public export class CatalogIdentityClient { constructor(options: { catalogApi: CatalogApi; tokenManager: TokenManager }); @@ -480,6 +496,23 @@ export const providers: Readonly<{ userIdMatchingUserEntityAnnotation(): SignInResolver; }>; }>; + bitbucketServer: Readonly<{ + create: ( + options?: + | { + authHandler?: AuthHandler | undefined; + signIn?: + | { + resolver: SignInResolver; + } + | undefined; + } + | undefined, + ) => AuthProviderFactory; + resolvers: Readonly<{ + emailMatchingUserEntityProfileEmail: () => SignInResolver; + }>; + }>; cfAccess: Readonly<{ create: (options: { authHandler?: AuthHandler | undefined; @@ -730,4 +763,8 @@ export type WebMessageResponse = type: 'authorization_response'; error: Error; }; + +// Warnings were encountered during analysis: +// +// src/providers/bitbucketServer/provider.d.ts:6:5 - (ae-forgotten-export) The symbol "PassportProfile" needs to be exported by the entry point index.d.ts ``` From 3d743aeb3491bc287772ab8e1c90b5ff65828d62 Mon Sep 17 00:00:00 2001 From: pamelin Date: Mon, 6 Feb 2023 11:48:20 +0000 Subject: [PATCH 071/417] fix: add stackstorm client tests Signed-off-by: pamelin --- app-config.yaml | 8 + plugins/stackstorm/config.d.ts | 13 -- .../src/api/StackStormClient.test.ts | 214 ++++++++++++++++++ plugins/stackstorm/src/api/types.ts | 6 +- 4 files changed, 225 insertions(+), 16 deletions(-) create mode 100644 plugins/stackstorm/src/api/StackStormClient.test.ts diff --git a/app-config.yaml b/app-config.yaml index dd72051189..c97adec5ef 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -118,6 +118,11 @@ proxy: headers: Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' + '/stackstorm': + target: https://your.stackstorm.instance.com/api + headers: + St2-Api-Key: ${ST2_API_KEY} + organization: name: My Company @@ -441,5 +446,8 @@ apacheAirflow: gocd: baseUrl: https://your.gocd.instance.com +stackstorm: + webUrl: https://your.stackstorm.webui.instance.com + permission: enabled: true diff --git a/plugins/stackstorm/config.d.ts b/plugins/stackstorm/config.d.ts index cf7a2e2253..64276503fc 100644 --- a/plugins/stackstorm/config.d.ts +++ b/plugins/stackstorm/config.d.ts @@ -15,19 +15,6 @@ */ export interface Config { stackstorm?: { - /** - * StackStorm API base url - * Used for local testing to bypass CORS - * @visibility frontend - */ - baseUrl?: string; - /** - * StackStorm API key - * Used for local testing to bypass CORS - * Do not set this in production deployment - * @visibility frontend - */ - key?: string; /** * StackStorm Web UI url * Used in links to StackStorm web UI diff --git a/plugins/stackstorm/src/api/StackStormClient.test.ts b/plugins/stackstorm/src/api/StackStormClient.test.ts new file mode 100644 index 0000000000..24400e3174 --- /dev/null +++ b/plugins/stackstorm/src/api/StackStormClient.test.ts @@ -0,0 +1,214 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { UrlPatternDiscovery } from '@backstage/core-app-api'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { StackStormClient } from './StackStormClient'; +import { Action, Execution, Pack } from './types'; + +const server = setupServer(); + +const executions: Execution[] = [ + { + id: '63dcac3e18ba00e09e7bb3b6', + action: { + name: 'post_message', + ref: 'chatops.post_message', + description: 'Post a message to stream for chatops', + pack: 'chatops', + runner_type: 'announcement', + id: '62fe101b11935b6aaff4ff92', + }, + status: 'succeeded', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: {}, + parameters: {}, + elapsed_seconds: 2.2, + log: [], + }, + { + id: '63dcac3e18ba00e09e7bb3b6', + action: { + name: 'post_result', + ref: 'chatops.post_result', + description: 'Post an execution result to stream for chatops', + pack: 'chatops', + runner_type: 'orquesta', + id: '62fe101b11935b6aaff4ff93', + }, + status: 'succeeded', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: {}, + parameters: {}, + elapsed_seconds: 18.5, + log: [], + }, + { + id: '63dcac3c9e0b4fe98f46becc', + action: { + name: 'run', + ref: 'shell.run', + description: 'Run shell script', + pack: 'shell', + runner_type: 'shell', + id: '63736caac3d8557c4d61883a', + }, + status: 'failed', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: {}, + parameters: {}, + elapsed_seconds: 5.0, + log: [], + }, +]; + +const executionWithDetails: Execution = { + id: '63dcac3e18ba00e09e7bb3b6', + action: { + name: 'post_message', + ref: 'chatops.post_message', + description: 'Post a message to stream for chatops', + pack: 'chatops', + runner_type: 'announcement', + id: '62fe101b11935b6aaff4ff92', + }, + status: 'succeeded', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: { + output: { + result: 'hello', + }, + }, + parameters: { + var: 'val', + }, + elapsed_seconds: 2.2, + log: [ + { status: 'requested', timestamp: new Date().toISOString() }, + { status: 'succeeded', timestamp: new Date().toISOString() }, + ], +}; + +const packs: Pack[] = [ + { + ref: 'chatops', + description: 'ChatOps integration pack', + version: '3.7.0', + }, + { + ref: 'core', + description: 'Basic core actions.', + version: '3.7.0', + }, +]; + +const actions: Action[] = [ + { + id: '62fe101b11935b6aaff4ff96', + name: 'announcement', + ref: 'core.announcement', + pack: 'core', + description: + 'Action that broadcasts the announcement to all stream consumers.', + runner_type: 'announcement', + }, + { + id: '62fe101b11935b6aaff4ff97', + name: 'echo', + ref: 'core.echo', + pack: 'core', + description: + 'Action that executes the Linux echo command on the localhost.', + runner_type: 'local-shell-cmd', + }, +]; + +const identityApiMock = () => ({ + signOut: jest.fn(), + getProfileInfo: jest.fn(), + getBackstageIdentity: jest.fn(), + getCredentials: jest.fn().mockResolvedValue({ token: undefined }), +}); + +describe('StackStormClient', () => { + setupRequestMockHandlers(server); + + const mockBaseUrl = 'http://backstage:9191/api/proxy'; + const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); + let client: StackStormClient; + + const setupHandlers = () => { + server.use( + rest.get(`${mockBaseUrl}/stackstorm/executions`, (req, res, ctx) => { + const limit = req.url.searchParams.get('limit') + ? Number(req.url.searchParams.get('limit')) + : executions.length; + const offset = req.url.searchParams.get('offset') + ? Number(req.url.searchParams.get('offset')) + : 0; + return res(ctx.json(executions.slice(offset, offset + limit))); + }), + rest.get( + `${mockBaseUrl}/stackstorm/executions/63dcac3e18ba00e09e7bb3b6`, + (_req, res, ctx) => { + return res(ctx.json(executionWithDetails)); + }, + ), + rest.get(`${mockBaseUrl}/stackstorm/packs`, (_req, res, ctx) => { + return res(ctx.json(packs)); + }), + rest.get(`${mockBaseUrl}/stackstorm/actions`, (req, res, ctx) => { + const name = req.url.searchParams.get('pack'); + return res(ctx.json(name === 'core' ? actions : [])); + }), + ); + }; + + beforeEach(() => { + setupHandlers(); + client = new StackStormClient({ + discoveryApi: discoveryApi, + identityApi: identityApiMock(), + }); + }); + + it('get executions should return executions with emulated pagination', async () => { + const got = await client.getExecutions(2, 1); + expect(got.length).toEqual(2); + expect(got).toMatchObject(executions.slice(1, 3)); + }); + + it('get execution should return one execution', async () => { + const got = await client.getExecution('63dcac3e18ba00e09e7bb3b6'); + expect(got).toMatchObject(executionWithDetails); + }); + + it('get packs should return list of all packs', async () => { + const got = await client.getPacks(); + expect(got.length).toEqual(packs.length); + expect(got).toMatchObject(packs); + }); + + it('get actions should return list of actions', async () => { + const got = await client.getActions('core'); + expect(got).toMatchObject(actions); + }); +}); diff --git a/plugins/stackstorm/src/api/types.ts b/plugins/stackstorm/src/api/types.ts index 8a3036d3ca..13c92fb055 100644 --- a/plugins/stackstorm/src/api/types.ts +++ b/plugins/stackstorm/src/api/types.ts @@ -23,8 +23,8 @@ export type Execution = { id: string; action: Action; status: string; - start_timestamp: Date; - end_timestamp: Date; + start_timestamp: string; + end_timestamp: string; result: object; parameters: object; elapsed_seconds: number; @@ -33,7 +33,7 @@ export type Execution = { export type ExecutionLog = { status: string; - timestamp: Date; + timestamp: string; }; export type Action = { From 7ad74fba7309282468b366610fcea56a69e6e6fc Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 6 Feb 2023 13:41:18 +0100 Subject: [PATCH 072/417] Added a missing validator check for items in an array Signed-off-by: bnechyporenko --- .../TemplatePage/createValidator.test.ts | 59 ++++++++++++++++++- .../TemplatePage/createValidator.ts | 26 +++++++- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index 177697eda0..da7a79b1b9 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -17,14 +17,32 @@ import { createValidator } from './createValidator'; import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; import { ApiHolder } from '@backstage/core-plugin-api'; -import { FormValidation } from '@rjsf/core'; +import { FieldValidation, FormValidation } from '@rjsf/core'; describe('createValidator', () => { const validators: Record> = { - CustomPicker: (value, validation, _context) => { + CustomPicker: ( + value: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { if (!value || !(value as { value?: unknown }).value) { - validation.addError('Error !'); + fieldValidation.addError('Error !'); + } + }, + TagPicker: ( + value: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + if (!value) { + fieldValidation.addError('A tag name can not be empty'); + } + if (!/^[a-z0-9-]+$/.test(value as string)) { + fieldValidation.addError( + 'A tag name can only contain lowercase letters, numeric characters or dashes', + ); } }, }; @@ -70,4 +88,39 @@ describe('createValidator', () => { expect(result).not.toBeNull(); expect(result.p1.addError).toHaveBeenCalledTimes(1); }); + + it('Should call validator for array property from a custom field extension', () => { + /* GIVEN */ + const rootSchema = { + title: 'My form', + properties: { + tags: { + title: 'Tags', + type: 'array', + items: { + type: 'string', + 'ui:field': 'TagPicker', + }, + }, + }, + }; + const validator = createValidator(rootSchema, validators, context); + + const formData = { + tags: ['invalid-tag$$'], + }; + const errors = { + addError: jest.fn(), + tags: { + addError: jest.fn(), + } as unknown as FormValidation, + } as unknown as FormValidation; + + /* WHEN */ + const result = validator(formData, errors); + + /* THEN */ + expect(result).not.toBeNull(); + expect(result.tags.addError).toHaveBeenCalledTimes(1); + }); }); diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index 4a64481fc3..98273da43a 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -23,6 +23,10 @@ function isObject(obj: unknown): obj is JsonObject { return typeof obj === 'object' && obj !== null && !Array.isArray(obj); } +function isArray(obj: unknown): obj is JsonObject { + return typeof obj === 'object' && obj !== null && Array.isArray(obj); +} + export const createValidator = ( rootSchema: JsonObject, validators: Record>, @@ -46,8 +50,8 @@ export const createValidator = ( for (const [key, propData] of Object.entries(formData)) { const propValidation = errors[key]; + const propSchemaProps = schemaProps[key]; if (isObject(propData)) { - const propSchemaProps = schemaProps[key]; if (isObject(propSchemaProps)) { validate( propSchemaProps, @@ -55,10 +59,26 @@ export const createValidator = ( propValidation as FormValidation, ); } + } else if (isArray(propData)) { + if (isObject(propSchemaProps)) { + const { items } = propSchemaProps; + if (isObject(items)) { + for (const propItem of propData as JsonObject[]) { + const fieldName = items['ui:field'] as string; + if (fieldName && typeof validators[fieldName] === 'function') { + validators[fieldName]!( + propItem as JsonValue, + propValidation, + context, + ); + } + } + } + } } else { - const propSchema = schemaProps[key]; const fieldName = - isObject(propSchema) && (propSchema['ui:field'] as string); + isObject(propSchemaProps) && + (propSchemaProps['ui:field'] as string); if (fieldName && typeof validators[fieldName] === 'function') { validators[fieldName]!( propData as JsonValue, From 074f7e81b5033ed68f75eec17a9ebc6c7f4a02fd Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 6 Feb 2023 13:49:44 +0100 Subject: [PATCH 073/417] Added a changeset Signed-off-by: bnechyporenko --- .changeset/lucky-papayas-allow.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/lucky-papayas-allow.md diff --git a/.changeset/lucky-papayas-allow.md b/.changeset/lucky-papayas-allow.md new file mode 100644 index 0000000000..5a896efd0b --- /dev/null +++ b/.changeset/lucky-papayas-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': minor +--- + +Added a missing validator check for items in an array From 8c63cebe70106a17efa3c7a3f3f2859591b6be6a Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 6 Feb 2023 14:05:02 +0100 Subject: [PATCH 074/417] Incorporated a feedback Signed-off-by: bnechyporenko --- .changeset/slow-moles-sin.md | 2 +- .../TemplatePage/createValidator.test.ts | 15 +++++++++------ .../components/TemplatePage/createValidator.ts | 16 +++++++--------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md index 140d9e7435..02e1952312 100644 --- a/.changeset/slow-moles-sin.md +++ b/.changeset/slow-moles-sin.md @@ -2,4 +2,4 @@ '@backstage/plugin-circleci': patch --- -Making workflow a link +Making workflow a link diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index da7a79b1b9..d9b9d1c0c3 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -32,17 +32,20 @@ describe('createValidator', () => { } }, TagPicker: ( - value: unknown, + values: unknown, fieldValidation: FieldValidation, _context: { apiHolder: ApiHolder }, ) => { - if (!value) { + const input = values as string[]; + if (input.length === 0) { fieldValidation.addError('A tag name can not be empty'); } - if (!/^[a-z0-9-]+$/.test(value as string)) { - fieldValidation.addError( - 'A tag name can only contain lowercase letters, numeric characters or dashes', - ); + for (const item of input) { + if (!/^[a-z0-9-]+$/.test(item)) { + fieldValidation.addError( + 'A tag name can only contain lowercase letters, numeric characters or dashes', + ); + } } }, }; diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index 98273da43a..123a7e800e 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -63,15 +63,13 @@ export const createValidator = ( if (isObject(propSchemaProps)) { const { items } = propSchemaProps; if (isObject(items)) { - for (const propItem of propData as JsonObject[]) { - const fieldName = items['ui:field'] as string; - if (fieldName && typeof validators[fieldName] === 'function') { - validators[fieldName]!( - propItem as JsonValue, - propValidation, - context, - ); - } + const fieldName = items['ui:field'] as string; + if (fieldName && typeof validators[fieldName] === 'function') { + validators[fieldName]!( + propData as JsonObject[], + propValidation, + context, + ); } } } From 4584a4ba2f1503dea680a8b446dbb449b243db0c Mon Sep 17 00:00:00 2001 From: pamelin Date: Mon, 6 Feb 2023 16:01:21 +0000 Subject: [PATCH 075/417] fix: add PacksTable tests Signed-off-by: pamelin --- .../components/PacksTable/PacksTable.test.tsx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx diff --git a/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx b/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx new file mode 100644 index 0000000000..e0f922d211 --- /dev/null +++ b/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx @@ -0,0 +1,55 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import React from 'react'; +import { Pack, StackStormApi, stackStormApiRef } from '../../api'; +import { PacksTable } from './PacksTable'; + +const packs: Pack[] = [ + { + ref: 'chatops', + description: 'ChatOps integration pack', + version: '3.7.0', + }, + { + ref: 'core', + description: 'Basic core actions.', + version: '3.7.1', + }, +]; + +describe('PacksTable', () => { + const mockApi: jest.Mocked = { + getExecutions: jest.fn().mockResolvedValue([]), + getExecution: jest.fn().mockResolvedValue({}), + getPacks: jest.fn().mockResolvedValue(packs), + getActions: jest.fn().mockResolvedValue([]), + } as any; + + it('should render all packs', async () => { + const { getByText } = await renderInTestApp( + + + , + ); + + packs.forEach(p => { + expect(getByText(p.ref)).toBeInTheDocument(); + expect(getByText(p.description)).toBeInTheDocument(); + expect(getByText(p.version)).toBeInTheDocument(); + }); + }); +}); From 7ce480edcfd9996f4653888d9d202e0a684f78eb Mon Sep 17 00:00:00 2001 From: pamelin Date: Mon, 6 Feb 2023 16:54:32 +0000 Subject: [PATCH 076/417] fix: add ActionsList tests Signed-off-by: pamelin --- .../ActionsList/ActionsList.test.tsx | 88 +++++++++++++++++++ .../components/ActionsList/ActionsList.tsx | 2 + 2 files changed, 90 insertions(+) create mode 100644 plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx new file mode 100644 index 0000000000..9f57d76ef3 --- /dev/null +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx @@ -0,0 +1,88 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import React from 'react'; +import { Action, Pack, StackStormApi, stackStormApiRef } from '../../api'; +import { ActionsList, PackListItem } from './ActionsList'; + +const packs: Pack[] = [ + { + ref: 'chatops', + description: 'ChatOps integration pack', + version: '3.7.0', + }, + { + ref: 'core', + description: 'Basic core actions.', + version: '3.7.1', + }, +]; + +const actions: Action[] = [ + { + id: '62fe101b11935b6aaff4ff96', + name: 'announcement', + ref: 'core.announcement', + pack: 'core', + description: + 'Action that broadcasts the announcement to all stream consumers.', + runner_type: 'broadcast', + }, + { + id: '62fe101b11935b6aaff4ff97', + name: 'echo', + ref: 'core.echo', + pack: 'core', + description: + 'Action that executes the Linux echo command on the localhost.', + runner_type: 'local-shell-cmd', + }, +]; + +describe('ActionsList', () => { + const mockApi: jest.Mocked = { + getExecutions: jest.fn().mockResolvedValue([]), + getExecution: jest.fn().mockResolvedValue({}), + getPacks: jest.fn().mockResolvedValue(packs), + getActions: jest.fn().mockResolvedValue(actions), + } as any; + + it('should render all packs', async () => { + const { getByText } = await renderInTestApp( + + + , + ); + + packs.forEach(p => { + expect(getByText(p.ref)).toBeInTheDocument(); + expect(getByText(p.description)).toBeInTheDocument(); + }); + }); + + it('should render all pack actions', async () => { + const { getByText } = await renderInTestApp( + + {}} /> + , + ); + + actions.forEach(a => { + expect(getByText(a.name)).toBeInTheDocument(); + expect(getByText(a.runner_type)).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx index 014e8c31a3..47e328716f 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx @@ -73,6 +73,7 @@ export const ActionItems = ({ pack }: ActionItemsProps) => { {(value || []).map(a => { return ( @@ -150,6 +151,7 @@ export const ActionsList = () => { {(value || []).map(p => { return ( Date: Mon, 6 Feb 2023 12:36:57 -0600 Subject: [PATCH 077/417] adding dot option to minimatch Signed-off-by: Justin De Burgo --- .../src/ingestion/CatalogRules.test.ts | 20 +++++++++++++++++++ .../src/ingestion/CatalogRules.ts | 5 ++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts index 34e89fad29..592b1dda21 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts @@ -35,6 +35,10 @@ const entity = { }; const location: Record = { + v: { + type: 'url', + target: 'https://github.com/b/c/blob/master/.folder/v.yaml', + }, w: { type: 'url', target: 'https://github.com/b/c/blob/master/w.yaml', @@ -263,4 +267,20 @@ describe('DefaultCatalogRulesEnforcer', () => { expect(enforcer.isAllowed(entity.component, location.z)).toBe(false); }); }); + + it('should allow locations with a hidden folder', () => { + const enforcer = DefaultCatalogRulesEnforcer.fromConfig( + new ConfigReader({ + catalog: { + rules: [ + { + allow: ['Component'], + locations: [{ type: 'url', pattern: 'https://github.com/b/**' }], + }, + ], + }, + }), + ); + expect(enforcer.isAllowed(entity.component, location.v)).toBe(true); + }); }); diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.ts index 677649d4b2..21b2d05a46 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.ts @@ -186,7 +186,10 @@ export class DefaultCatalogRulesEnforcer implements CatalogRulesEnforcer { } if ( matcher.pattern && - !minimatch(location?.target, matcher.pattern, { nocase: true }) + !minimatch(location?.target, matcher.pattern, { + nocase: true, + dot: true, + }) ) { continue; } From 0a32911d8a1ac9e6cd5f84da81aa5d5d4291ae13 Mon Sep 17 00:00:00 2001 From: David Weber Date: Sun, 29 Jan 2023 01:30:46 +0100 Subject: [PATCH 078/417] feat: improve navigation of adr plugin Signed-off-by: David Weber --- .changeset/light-crabs-drum.md | 6 ++ .../src/search/createMadrParser.ts | 42 ++----------- plugins/adr-backend/src/search/madrParser.ts | 59 ++++++++++++++++++ .../adr-backend/src/service/router.test.ts | 8 +-- plugins/adr-backend/src/service/router.ts | 22 ++++--- plugins/adr/README.md | 2 + plugins/adr/api-report.md | 3 + plugins/adr/docs/adr-tab.png | Bin 0 -> 773895 bytes plugins/adr/src/api/types.ts | 9 +++ .../EntityAdrContent/EntityAdrContent.tsx | 41 +++++++++--- 10 files changed, 136 insertions(+), 56 deletions(-) create mode 100644 .changeset/light-crabs-drum.md create mode 100644 plugins/adr-backend/src/search/madrParser.ts create mode 100644 plugins/adr/docs/adr-tab.png diff --git a/.changeset/light-crabs-drum.md b/.changeset/light-crabs-drum.md new file mode 100644 index 0000000000..ebc0b3fa5a --- /dev/null +++ b/.changeset/light-crabs-drum.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-adr-backend': minor +'@backstage/plugin-adr': minor +--- + +Display title, status and date in ADR navigation, sourced from ADR content and reverse order. diff --git a/plugins/adr-backend/src/search/createMadrParser.ts b/plugins/adr-backend/src/search/createMadrParser.ts index 6b77ec2fa7..1bc3c852e9 100644 --- a/plugins/adr-backend/src/search/createMadrParser.ts +++ b/plugins/adr-backend/src/search/createMadrParser.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import { DateTime } from 'luxon'; -import { marked } from 'marked'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { MADR_DATE_FORMAT } from '@backstage/plugin-adr-common'; import { AdrParser } from './types'; +import { madrParser } from './madrParser'; const applyArgsToFormat = ( format: string, @@ -65,43 +64,12 @@ export const createMadrParser = ( const dateFormat = options.dateFormat ?? MADR_DATE_FORMAT; return async ({ entity, content, path }) => { - const tokens = marked.lexer(content); - if (!tokens.length) { - throw new Error('ADR has no content'); - } - - // First h1 header should contain ADR title - const adrTitle = ( - tokens.find( - t => t.type === 'heading' && t.depth === 1, - ) as marked.Tokens.Heading - )?.text; - - // First list should contain status & date metadata (if defined) - const listTokens = ( - tokens.find(t => t.type === 'list') as marked.Tokens.List - )?.items; - const adrStatus = listTokens - .find(t => /^status:/i.test(t.text)) - ?.text.replace(/^status:/i, '') - .trim() - .toLocaleLowerCase('en-US'); - const adrDateTime = DateTime.fromFormat( - listTokens - .find(t => /^date:/i.test(t.text)) - ?.text.replace(/^date:/i, '') - .trim() ?? '', - dateFormat, - ); - const adrDate = adrDateTime.isValid - ? adrDateTime.toFormat(MADR_DATE_FORMAT) - : undefined; - + const madr = madrParser(content, dateFormat); return { - title: adrTitle ?? path.replace(/\.md$/, ''), + title: madr.title ?? path.replace(/\.md$/, ''), text: content, - status: adrStatus, - date: adrDate, + status: madr.status, + date: madr.date, entityRef: stringifyEntityRef(entity), entityTitle: entity.metadata.title, location: applyArgsToFormat(locationTemplate, { diff --git a/plugins/adr-backend/src/search/madrParser.ts b/plugins/adr-backend/src/search/madrParser.ts new file mode 100644 index 0000000000..30672028fe --- /dev/null +++ b/plugins/adr-backend/src/search/madrParser.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DateTime } from 'luxon'; +import { marked } from 'marked'; +import { MADR_DATE_FORMAT } from '@backstage/plugin-adr-common'; + +export const madrParser = (content: string, dateFormat = MADR_DATE_FORMAT) => { + const tokens = marked.lexer(content); + if (!tokens.length) { + throw new Error('ADR has no content'); + } + + // First h1 header should contain ADR title + const adrTitle = ( + tokens.find( + t => t.type === 'heading' && t.depth === 1, + ) as marked.Tokens.Heading + )?.text; + + // First list should contain status & date metadata (if defined) + const listTokens = (tokens.find(t => t.type === 'list') as marked.Tokens.List) + ?.items; + const adrStatus = listTokens + ?.find(t => /^status:/i.test(t.text)) + ?.text.replace(/^status:/i, '') + .trim() + .toLocaleLowerCase('en-US'); + + const adrDateTime = DateTime.fromFormat( + listTokens + ?.find(t => /^date:/i.test(t.text)) + ?.text.replace(/^date:/i, '') + .trim() ?? '', + dateFormat, + ); + const adrDate = adrDateTime?.isValid + ? adrDateTime.toFormat(MADR_DATE_FORMAT) + : undefined; + + return { + title: adrTitle, + status: adrStatus, + date: adrDate, + }; +}; diff --git a/plugins/adr-backend/src/service/router.test.ts b/plugins/adr-backend/src/service/router.test.ts index fbbd6e8532..1ae9076bb5 100644 --- a/plugins/adr-backend/src/service/router.test.ts +++ b/plugins/adr-backend/src/service/router.test.ts @@ -156,8 +156,8 @@ describe('createRouter', () => { data: [ { type: 'file', - name: 'testFile001.txt', - path: 'folder/testFile001.txt', + name: 'testFile002.txt', + path: 'testFile002.txt', }, { type: 'file', @@ -166,8 +166,8 @@ describe('createRouter', () => { }, { type: 'file', - name: 'testFile002.txt', - path: 'testFile002.txt', + name: 'testFile001.txt', + path: 'folder/testFile001.txt', }, ], }; diff --git a/plugins/adr-backend/src/service/router.ts b/plugins/adr-backend/src/service/router.ts index e6603ab346..ed02a76e13 100644 --- a/plugins/adr-backend/src/service/router.ts +++ b/plugins/adr-backend/src/service/router.ts @@ -19,6 +19,7 @@ import { NotModifiedError, stringifyError } from '@backstage/errors'; import { Logger } from 'winston'; import express from 'express'; import Router from 'express-promise-router'; +import { madrParser } from '../search/madrParser'; /** @public */ export type AdrRouterOptions = { @@ -59,13 +60,20 @@ export async function createRouter( etag: cachedTree?.etag, }); const files = await treeGetResponse.files(); - const data = files.map(file => { - return { - type: 'file', - name: file.path.substring(file.path.lastIndexOf('/') + 1), - path: file.path, - }; - }); + const data = await Promise.all( + files + .map(async file => { + const fileContent = await file.content(); + const adrInfo = madrParser(fileContent.toString()); + return { + type: 'file', + name: file.path.substring(file.path.lastIndexOf('/') + 1), + path: file.path, + ...adrInfo, + }; + }) + .reverse(), + ); await cacheClient.set(urlToProcess, { data, diff --git a/plugins/adr/README.md b/plugins/adr/README.md index b9cc5d84ba..a669762dad 100644 --- a/plugins/adr/README.md +++ b/plugins/adr/README.md @@ -4,6 +4,8 @@ Welcome to the ADR plugin! This plugin allows you to browse ADRs associated with your entities as well as a way to discover ADRs across others entities via Backstage Search. Use this to learn from the past experience of other projects to guide your own architecture decisions. +![ADR tab](./docs/adr-tab.png) + ## Setup 1. Install this plugin: diff --git a/plugins/adr/api-report.md b/plugins/adr/api-report.md index d6480cd090..4005e1625e 100644 --- a/plugins/adr/api-report.md +++ b/plugins/adr/api-report.md @@ -51,6 +51,9 @@ export type AdrFileInfo = { type: string; path: string; name: string; + title?: string; + status?: string; + date?: string; }; // @public diff --git a/plugins/adr/docs/adr-tab.png b/plugins/adr/docs/adr-tab.png new file mode 100644 index 0000000000000000000000000000000000000000..d9dd728221c502861fe144843adde3390292f50a GIT binary patch literal 773895 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

g`hbf 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℘PtM_kX%m~DZD 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

t>}bvjw0L$N#rP9mAW`dSC`6oW@5Cs1WTHF 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
%Jd^>-9R%^EjTz^Z7iE)6Cdv_Ws#& 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
X*Q>nMzD?8KA#f{uXZ2-xGBJrxEmvD+J_QnZ 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
+
+ + + Choose Custom Field Extension + + + + + + + +
+
+ + + +
handleFieldConfigChange(e.formData)} + validator={validator} + schema={selectedField.schema?.uiOptions || {}} + > + + +
+
+
+
+ + + + + + + null} + /> +
+
+ ); +}; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx new file mode 100644 index 0000000000..0edf390bfe --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx @@ -0,0 +1,243 @@ +/* + * Copyright 2022 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 { ErrorPanel, Progress } from '@backstage/core-components'; +import { useAsync, useRerender } from '@react-hookz/web'; +import React, { createContext, ReactNode, useContext, useEffect } from 'react'; +import { + TemplateDirectoryAccess, + TemplateFileAccess, +} from '../../lib/filesystem'; + +const MAX_SIZE = 1024 * 1024; +const MAX_SIZE_MESSAGE = 'This file is too large to be displayed'; + +interface DirectoryEditorFile { + /** The path of the file relative to the root directory */ + path: string; + /** The staged content of the file */ + content: string; + /** Whether the staged content matches what is on disk */ + dirty: boolean; + + /** Update the staged content of the file without saving */ + updateContent(content: string): void; + /** Save the staged content of the file to disk */ + save(): Promise; + /** Reload the staged content of the file from disk */ + reload(): Promise; +} + +interface DirectoryEditor { + /** A list of all files in the edited directory */ + files: Array; + + /** The currently selected file */ + selectedFile: DirectoryEditorFile | undefined; + /** Switch the selected file */ + setSelectedFile(path: string | undefined): void; + + /** Save all files to disk */ + save(): Promise; + /** Reload all files from disk */ + reload(): Promise; + + subscribe(listener: () => void): () => void; +} + +class DirectoryEditorFileManager implements DirectoryEditorFile { + readonly #access: TemplateFileAccess; + readonly #signalUpdate: () => void; + + #content?: string; + #savedContent?: string; + + constructor(access: TemplateFileAccess, signalUpdate: () => void) { + this.#access = access; + this.#signalUpdate = signalUpdate; + } + + get path() { + return this.#access.path; + } + + get content() { + return this.#content ?? MAX_SIZE_MESSAGE; + } + + updateContent(content: string): void { + if (this.#content === undefined) { + return; + } + this.#content = content; + this.#signalUpdate(); + } + + get dirty() { + return this.#content !== this.#savedContent; + } + + async save(): Promise { + if (this.#content !== undefined) { + await this.#access.save(this.#content); + this.#savedContent = this.#content; + this.#signalUpdate(); + } + } + + async reload(): Promise { + const file = await this.#access.file(); + if (file.size > MAX_SIZE) { + if (this.#content !== undefined) { + this.#content = undefined; + this.#savedContent = undefined; + this.#signalUpdate(); + } + return; + } + + const content = await file.text(); + if (this.#content !== content) { + this.#content = content; + this.#savedContent = content; + this.#signalUpdate(); + } + } +} + +class DirectoryEditorManager implements DirectoryEditor { + readonly #access: TemplateDirectoryAccess; + readonly #listeners = new Set<() => void>(); + + #files: DirectoryEditorFile[] = []; + #selectedFile: DirectoryEditorFile | undefined; + + constructor(access: TemplateDirectoryAccess) { + this.#access = access; + } + + get files() { + return this.#files; + } + + get selectedFile() { + return this.#selectedFile; + } + + setSelectedFile = (path: string | undefined): void => { + const prev = this.#selectedFile; + const next = this.#files.find(file => file.path === path); + if (prev !== next) { + this.#selectedFile = next; + this.#signalUpdate(); + } + }; + + get dirty() { + return this.#files.some(file => file.dirty); + } + + async save(): Promise { + await Promise.all(this.#files.map(file => file.save())); + } + + async reload(): Promise { + const selectedPath = this.#selectedFile?.path; + + const files = await this.#access.listFiles(); + const fileManagers = await Promise.all( + files.map(async file => { + const manager = new DirectoryEditorFileManager( + file, + this.#signalUpdate, + ); + await manager.reload(); + return manager; + }), + ); + this.#files.length = 0; + this.#files.push(...fileManagers); + + this.setSelectedFile(selectedPath); + this.#signalUpdate(); + } + + subscribe(listener: () => void): () => void { + this.#listeners.add(listener); + return () => { + this.#listeners.delete(listener); + }; + } + + #signalUpdate = () => { + this.#listeners.forEach(listener => listener()); + }; +} + +const DirectoryEditorContext = createContext( + undefined, +); + +export function useDirectoryEditor(): DirectoryEditor { + const value = useContext(DirectoryEditorContext); + const rerender = useRerender(); + + useEffect(() => value?.subscribe(rerender), [value, rerender]); + + if (!value) { + throw new Error('must be used within a DirectoryEditorProvider'); + } + return value; +} + +interface DirectoryEditorProviderProps { + directory: TemplateDirectoryAccess; + children?: ReactNode; +} + +export function DirectoryEditorProvider(props: DirectoryEditorProviderProps) { + const { directory } = props; + + const [{ result, error }, { execute }] = useAsync( + async (dir: TemplateDirectoryAccess) => { + const manager = new DirectoryEditorManager(dir); + await manager.reload(); + + const firstYaml = manager.files.find(file => file.path.match(/\.ya?ml$/)); + if (firstYaml) { + manager.setSelectedFile(firstYaml.path); + } + + return manager; + }, + ); + + useEffect(() => { + execute(directory); + }, [execute, directory]); + + if (error) { + return ; + } else if (!result) { + return ; + } + + return ( + + {props.children} + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx new file mode 100644 index 0000000000..36a62f1b8a --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx @@ -0,0 +1,44 @@ +/* + * Copyright 2022 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 { base64EncodeContent } from './DryRunContext'; + +// eslint-disable-next-line no-restricted-imports +import { TextEncoder } from 'util'; + +window.TextEncoder = TextEncoder; + +describe('base64EncodeContent', () => { + it('encodes text files', () => { + expect(base64EncodeContent('abc')).toBe('YWJj'); + expect(base64EncodeContent('abc'.repeat(1000000))).toBe( + window.btoa(''), + ); + }); + + it('encodes binary files', () => { + expect(base64EncodeContent('\x00\x01\x02')).toBe('AAEC'); + expect(base64EncodeContent('😅')).toBe('8J+YhQ=='); + // Triggers chunking + expect(base64EncodeContent('😅'.repeat(18000))).toBe( + '8J+YhfCfmIXwn5iF8J+YhfCfmIXwn5iF'.repeat(3000), + ); + // Triggers size check + expect(base64EncodeContent('😅'.repeat(1000000))).toBe( + window.btoa(''), + ); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx new file mode 100644 index 0000000000..a617eebe1e --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx @@ -0,0 +1,179 @@ +/* + * Copyright 2022 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 yaml from 'yaml'; +import { useApi } from '@backstage/core-plugin-api'; +import { JsonObject } from '@backstage/types'; +import React, { + createContext, + ReactNode, + useCallback, + useContext, + useMemo, + useRef, + useState, +} from 'react'; +import { + scaffolderApiRef, + ScaffolderDryRunResponse, +} from '@backstage/plugin-scaffolder-react'; + +const MAX_CONTENT_SIZE = 64 * 1024; +const CHUNK_SIZE = 32 * 1024; + +interface DryRunOptions { + templateContent: string; + values: JsonObject; + files: Array<{ path: string; content: string }>; +} + +interface DryRunResult extends ScaffolderDryRunResponse { + id: number; +} + +interface DryRun { + results: DryRunResult[]; + selectedResult: DryRunResult | undefined; + + selectResult(id: number): void; + deleteResult(id: number): void; + execute(options: DryRunOptions): Promise; +} + +const DryRunContext = createContext(undefined); + +interface DryRunProviderProps { + children: ReactNode; +} + +export function base64EncodeContent(content: string): string { + if (content.length > MAX_CONTENT_SIZE) { + return window.btoa(''); + } + + try { + return window.btoa(content); + } catch { + const decoder = new TextEncoder(); + const buffer = decoder.encode(content); + + const chunks = new Array(); + for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) { + chunks.push( + String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE)), + ); + } + return window.btoa(chunks.join('')); + } +} + +export function DryRunProvider(props: DryRunProviderProps) { + const scaffolderApi = useApi(scaffolderApiRef); + + const [state, setState] = useState< + Pick + >({ + results: [], + selectedResult: undefined, + }); + const idRef = useRef(1); + + const selectResult = useCallback((id: number) => { + setState(prevState => { + const result = prevState.results.find(r => r.id === id); + if (result === prevState.selectedResult) { + return prevState; + } + return { + results: prevState.results, + selectedResult: result, + }; + }); + }, []); + + const deleteResult = useCallback((id: number) => { + setState(prevState => { + const index = prevState.results.findIndex(r => r.id === id); + if (index === -1) { + return prevState; + } + const newResults = prevState.results.slice(); + const [deleted] = newResults.splice(index, 1); + return { + results: newResults, + selectedResult: + prevState.selectedResult?.id === deleted.id + ? newResults[0] + : prevState.selectedResult, + }; + }); + }, []); + + const execute = useCallback( + async (options: DryRunOptions) => { + if (!scaffolderApi.dryRun) { + throw new Error('Scaffolder API does not support dry-run'); + } + + const parsed = yaml.parse(options.templateContent); + + const response = await scaffolderApi.dryRun({ + template: parsed, + values: options.values, + secrets: {}, + directoryContents: options.files.map(file => ({ + path: file.path, + base64Content: base64EncodeContent(file.content), + })), + }); + + const result = { + ...response, + id: idRef.current++, + }; + + setState(prevState => ({ + results: [...prevState.results, result], + selectedResult: prevState.selectedResult ?? result, + })); + }, + [scaffolderApi], + ); + + const dryRun = useMemo( + () => ({ + ...state, + selectResult, + deleteResult, + execute, + }), + [state, selectResult, deleteResult, execute], + ); + + return ( + + {props.children} + + ); +} + +export function useDryRun(): DryRun { + const value = useContext(DryRunContext); + if (!value) { + throw new Error('must be used within a DryRunProvider'); + } + return value; +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx new file mode 100644 index 0000000000..0267093ee6 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx @@ -0,0 +1,118 @@ +/* + * Copyright 2022 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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { act, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React, { useEffect } from 'react'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import { DryRunProvider, useDryRun } from '../DryRunContext'; +import { DryRunResults } from './DryRunResults'; + +function DryRunRemote({ + execute, + remove, +}: { + execute?: boolean; + remove?: boolean; +}) { + const dryRun = useDryRun(); + + useEffect(() => { + if (execute) { + dryRun.execute({ + templateContent: '', + values: {}, + files: [], + }); + } + if (remove) { + if (dryRun.selectedResult) { + dryRun.deleteResult(dryRun.selectedResult.id); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [execute, remove]); + + return null; +} + +const mockScaffolderApi = { + dryRun: async () => ({ + directoryContents: [], + log: [], + output: {}, + steps: [], + }), +}; + +describe('DryRunResults', () => { + it('renders without exploding', async () => { + await renderInTestApp( + + + + + , + ); + expect(screen.getByText('Dry-run results')).toBeInTheDocument(); + }); + + it('expands when dry-run result is added and toggles on click, and disappears when results are gone', async () => { + const { rerender } = await renderInTestApp( + + + + + + , + ); + + expect(screen.getByText('Files')).not.toBeVisible(); + + await act(async () => { + rerender( + + + + + + , + ); + }); + + expect(screen.getByText('Files')).toBeVisible(); + + await userEvent.click(screen.getByText('Dry-run results')); + await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); + + await userEvent.click(screen.getByText('Dry-run results')); + expect(screen.getByText('Files')).toBeVisible(); + + await act(async () => { + rerender( + + + + + + , + ); + }); + + await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx new file mode 100644 index 0000000000..ae9374438f --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx @@ -0,0 +1,91 @@ +/* + * Copyright 2022 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 { BackstageTheme } from '@backstage/theme'; +import Accordion from '@material-ui/core/Accordion'; +import AccordionDetails from '@material-ui/core/AccordionDetails'; +import AccordionSummary from '@material-ui/core/AccordionSummary'; +import Divider from '@material-ui/core/Divider'; +import { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import ExpandMoreIcon from '@material-ui/icons/ExpandLess'; +import { usePrevious } from '@react-hookz/web'; +import React, { useEffect, useState } from 'react'; +import { useDryRun } from '../DryRunContext'; +import { DryRunResultsList } from './DryRunResultsList'; +import { DryRunResultsView } from './DryRunResultsView'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + header: { + height: 48, + minHeight: 0, + '&.Mui-expanded': { + height: 48, + minHeight: 0, + }, + }, + content: { + display: 'grid', + background: theme.palette.background.default, + gridTemplateColumns: '180px auto 1fr', + gridTemplateRows: '1fr', + padding: 0, + height: 400, + }, +})); + +export function DryRunResults() { + const classes = useStyles(); + const dryRun = useDryRun(); + const [expanded, setExpanded] = useState(false); + const [hidden, setHidden] = useState(true); + + const resultsLength = dryRun.results.length; + const prevResultsLength = usePrevious(resultsLength); + useEffect(() => { + if (prevResultsLength === 0 && resultsLength === 1) { + setHidden(false); + setExpanded(true); + } else if (prevResultsLength === 1 && resultsLength === 0) { + setExpanded(false); + } + }, [prevResultsLength, resultsLength]); + + return ( + <> + + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx new file mode 100644 index 0000000000..706f284db1 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx @@ -0,0 +1,95 @@ +/* + * Copyright 2022 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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { act, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React, { useEffect } from 'react'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import { DryRunProvider, useDryRun } from '../DryRunContext'; +import { DryRunResultsList } from './DryRunResultsList'; + +function DryRunRemote({ execute }: { execute?: number }) { + const dryRun = useDryRun(); + + useEffect(() => { + if (execute) { + dryRun.execute({ + templateContent: '', + values: {}, + files: [], + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [execute]); + + return null; +} + +const mockScaffolderApi = { + dryRun: async () => ({ + directoryContents: [], + log: [], + output: {}, + steps: [], + }), +}; + +describe('DryRunResultsList', () => { + it('renders without exploding', async () => { + const rendered = await renderInTestApp( + + + + + , + ); + expect(rendered.baseElement.querySelector('ul')).toBeEmptyDOMElement(); + }); + + it('adds new result items and deletes them', async () => { + const { rerender } = await renderInTestApp( + + + + + + , + ); + + expect(screen.getByText('Result 1')).toBeInTheDocument(); + expect(screen.queryByText('Result 2')).not.toBeInTheDocument(); + + await act(async () => { + rerender( + + + + + + , + ); + }); + + expect(screen.getByText('Result 1')).toBeInTheDocument(); + expect(screen.getByText('Result 2')).toBeInTheDocument(); + + await userEvent.click(screen.getAllByLabelText('delete')[0]); + + expect(screen.queryByText('Result 1')).not.toBeInTheDocument(); + expect(screen.getByText('Result 2')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx new file mode 100644 index 0000000000..462c3b58fd --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx @@ -0,0 +1,83 @@ +/* + * Copyright 2022 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 { BackstageTheme } from '@backstage/theme'; +import IconButton from '@material-ui/core/IconButton'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; +import ListItemText from '@material-ui/core/ListItemText'; +import { makeStyles } from '@material-ui/core/styles'; +import CancelIcon from '@material-ui/icons/Cancel'; +import CheckIcon from '@material-ui/icons/Check'; +import DeleteIcon from '@material-ui/icons/Delete'; +import React from 'react'; +import { useDryRun } from '../DryRunContext'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + root: { + overflowY: 'auto', + background: theme.palette.background.default, + }, + iconSuccess: { + minWidth: 0, + marginRight: theme.spacing(1), + color: theme.palette.status.ok, + }, + iconFailure: { + minWidth: 0, + marginRight: theme.spacing(1), + color: theme.palette.status.error, + }, +})); + +export function DryRunResultsList() { + const classes = useStyles(); + const dryRun = useDryRun(); + + return ( + + {dryRun.results.map(result => { + const failed = result.log.some(l => l.body.status === 'failed'); + return ( + dryRun.selectResult(result.id)} + > + + {failed ? : } + + + + dryRun.deleteResult(result.id)} + > + + + + + ); + })} + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx new file mode 100644 index 0000000000..b554a1c0c0 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx @@ -0,0 +1,55 @@ +/* + * Copyright 2022 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 { makeStyles } from '@material-ui/core/styles'; +import Divider from '@material-ui/core/Divider'; +import React, { Children, ReactNode } from 'react'; +import classNames from 'classnames'; + +const useStyles = makeStyles(theme => ({ + root: { + display: 'grid', + gridTemplateColumns: '280px auto 3fr', + gridTemplateRows: '1fr', + }, + child: { + overflowY: 'auto', + height: '100%', + minHeight: 0, + }, + firstChild: { + background: theme.palette.background.paper, + }, +})); + +export function DryRunResultsSplitView(props: { children: ReactNode }) { + const classes = useStyles(); + const childArray = Children.toArray(props.children); + + if (childArray.length !== 2) { + throw new Error('must have exactly 2 children'); + } + + return ( +
+
+ {childArray[0]} +
+ +
{childArray[1]}
+
+ ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx new file mode 100644 index 0000000000..c2d8d3a2a4 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx @@ -0,0 +1,99 @@ +/* + * Copyright 2022 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 { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React, { ReactNode, useEffect } from 'react'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import { DryRunProvider, useDryRun } from '../DryRunContext'; +import { DryRunResultsView } from './DryRunResultsView'; + +// The inside needs mocking to render in jsdom +jest.mock('react-virtualized-auto-sizer', () => ({ + __esModule: true, + default: (props: { + children: (size: { width: number; height: number }) => ReactNode; + }) => <>{props.children({ width: 400, height: 200 })}, +})); + +function DryRunRemote() { + const dryRun = useDryRun(); + + useEffect(() => { + dryRun.execute({ + templateContent: '', + values: {}, + files: [], + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return null; +} + +describe('DryRunResultsView', () => { + it('renders a result', async () => { + await renderInTestApp( + ({ + directoryContents: [ + { + path: 'foo.txt', + base64Content: window.btoa('Foo Content'), + executable: false, + }, + ], + log: [{ body: { message: 'Foo Message', stepId: 'foo' } }], + output: { + links: [{ title: 'Foo Link', url: 'http://example.com' }], + }, + steps: [{ id: 'foo', action: 'foo', name: 'Foo' }], + }), + }, + ], + ]} + > + + + + + , + { + mountedRoutes: { + '/catalog/:kind/:namespace/:name': entityRouteRef, + }, + }, + ); + + expect(screen.getByText('foo.txt')).toBeInTheDocument(); + expect(screen.getByText('Foo Content')).toBeInTheDocument(); + + expect(screen.queryByText('Foo Message')).not.toBeInTheDocument(); + expect(screen.queryByText('Foo Link')).not.toBeInTheDocument(); + + await userEvent.click(screen.getByText('Log')); + expect(screen.getByText('Foo Message')).toBeInTheDocument(); + + await userEvent.click(screen.getByText('Output')); + expect(screen.getByText('Foo Link')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx new file mode 100644 index 0000000000..852ec05a82 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx @@ -0,0 +1,195 @@ +/* + * Copyright 2022 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 { LogViewer } from '@backstage/core-components'; +import { StreamLanguage } from '@codemirror/language'; +import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; +import Box from '@material-ui/core/Box'; +import Divider from '@material-ui/core/Divider'; +import { makeStyles } from '@material-ui/core/styles'; +import Tab from '@material-ui/core/Tab'; +import Tabs from '@material-ui/core/Tabs'; +import CodeMirror from '@uiw/react-codemirror'; +import React, { useEffect, useMemo, useState } from 'react'; +import { FileBrowser } from '../../../components/FileBrowser'; +import { TaskStatusStepper } from '../../../components/TaskPage/TaskPage'; +import { TaskPageLinks } from '../../../components/TaskPage/TaskPageLinks'; +import { useDryRun } from '../DryRunContext'; +import { DryRunResultsSplitView } from './DryRunResultsSplitView'; + +const useStyles = makeStyles({ + root: { + display: 'flex', + flexFlow: 'column nowrap', + }, + contentWrapper: { + flex: 1, + position: 'relative', + }, + content: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + + display: 'flex', + '& > *': { + flex: 1, + }, + }, + codeMirror: { + height: '100%', + overflowY: 'auto', + }, +}); + +function FilesContent() { + const classes = useStyles(); + const { selectedResult } = useDryRun(); + const [selectedPath, setSelectedPath] = useState(''); + const selectedFile = selectedResult?.directoryContents.find( + f => f.path === selectedPath, + ); + + useEffect(() => { + if (selectedResult) { + const [firstFile] = selectedResult.directoryContents; + if (firstFile) { + setSelectedPath(firstFile.path); + } else { + setSelectedPath(''); + } + } + return undefined; + }, [selectedResult]); + + if (!selectedResult) { + return null; + } + return ( + + file.path)} + /> + + + ); +} +function LogContent() { + const { selectedResult } = useDryRun(); + const [currentStepId, setUserSelectedStepId] = useState(); + + const steps = useMemo(() => { + if (!selectedResult) { + return []; + } + return ( + selectedResult.steps.map(step => { + const stepLog = selectedResult.log.filter( + l => l.body.stepId === step.id, + ); + return { + id: step.id, + name: step.name, + logString: stepLog.map(l => l.body.message).join('\n'), + status: stepLog[stepLog.length - 1]?.body.status ?? 'completed', + }; + }) ?? [] + ); + }, [selectedResult]); + + if (!selectedResult) { + return null; + } + + const selectedStep = steps.find(s => s.id === currentStepId) ?? steps[0]; + + return ( + + + + + ); +} + +function OutputContent() { + const classes = useStyles(); + const { selectedResult } = useDryRun(); + + if (!selectedResult) { + return null; + } + + return ( + + + {selectedResult.output?.links?.length && ( + + )} + + + + ); +} + +export function DryRunResultsView() { + const classes = useStyles(); + const [selectedTab, setSelectedTab] = useState<'files' | 'log' | 'output'>( + 'files', + ); + + return ( +
+ setSelectedTab(v)}> + + + + + + +
+
+ {selectedTab === 'files' && } + {selectedTab === 'log' && } + {selectedTab === 'output' && } +
+
+
+ ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts new file mode 100644 index 0000000000..af8ef5214f --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 { DryRunResults } from './DryRunResults'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx new file mode 100644 index 0000000000..c5556c3b06 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2022 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 { makeStyles } from '@material-ui/core'; +import React, { useState } from 'react'; +import type { + LayoutOptions, + NextFieldExtensionOptions, +} from '@backstage/plugin-scaffolder-react'; +import { TemplateDirectoryAccess } from '../../lib/filesystem'; +import { DirectoryEditorProvider } from './DirectoryEditorContext'; +import { DryRunProvider } from './DryRunContext'; +import { DryRunResults } from './DryRunResults'; +import { TemplateEditorBrowser } from './TemplateEditorBrowser'; +import { TemplateEditorForm } from './TemplateEditorForm'; +import { TemplateEditorTextArea } from './TemplateEditorTextArea'; + +const useStyles = makeStyles({ + // Reset and fix sizing to make sure scrolling behaves correctly + root: { + gridArea: 'pageContent', + + display: 'grid', + gridTemplateAreas: ` + "browser editor preview" + "results results results" + `, + gridTemplateColumns: '1fr 3fr 2fr', + gridTemplateRows: '1fr auto', + }, + browser: { + gridArea: 'browser', + overflow: 'auto', + }, + editor: { + gridArea: 'editor', + overflow: 'auto', + }, + preview: { + gridArea: 'preview', + overflow: 'auto', + }, + results: { + gridArea: 'results', + }, +}); + +export const TemplateEditor = (props: { + directory: TemplateDirectoryAccess; + fieldExtensions?: NextFieldExtensionOptions[]; + layouts?: LayoutOptions[]; + onClose?: () => void; +}) => { + const classes = useStyles(); + + const [errorText, setErrorText] = useState(); + + return ( + + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ ); +}; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx new file mode 100644 index 0000000000..cec311a5cd --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx @@ -0,0 +1,55 @@ +/* + * Copyright 2022 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 { renderInTestApp } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { MockFileSystemAccess } from '../../lib/filesystem/MockFileSystemAccess'; +import { DirectoryEditorProvider } from './DirectoryEditorContext'; +import { TemplateEditorBrowser } from './TemplateEditorBrowser'; + +Blob.prototype.text = async function text() { + return new Promise(resolve => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result as string); + reader.readAsText(this); + }); +}; + +describe('TemplateEditorBrowser', () => { + it('should render files and expand dirs without exploding', async () => { + await renderInTestApp( + + + , + ); + + await expect(screen.findByText('foo.txt')).resolves.toBeInTheDocument(); + expect(screen.getByText('dir')).toBeInTheDocument(); + expect(screen.queryByText('bar.txt')).not.toBeInTheDocument(); + expect(screen.queryByText('baz.txt')).not.toBeInTheDocument(); + + await userEvent.click(screen.getByText('dir')); + expect(screen.getByText('bar.txt')).toBeInTheDocument(); + expect(screen.getByText('baz.txt')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx new file mode 100644 index 0000000000..a668aa1868 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx @@ -0,0 +1,100 @@ +/* + * Copyright 2022 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 { Divider, IconButton, makeStyles, Tooltip } from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; +import RefreshIcon from '@material-ui/icons/Refresh'; +import SaveIcon from '@material-ui/icons/Save'; +import React from 'react'; +import { FileBrowser } from '../../components/FileBrowser'; + +import { useDirectoryEditor } from './DirectoryEditorContext'; + +const useStyles = makeStyles(theme => ({ + button: { + padding: theme.spacing(1), + }, + buttons: { + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + justifyContent: 'flex-start', + }, + buttonsGap: { + flex: '1 1 auto', + }, + buttonsDivider: { + marginBottom: theme.spacing(1), + }, +})); + +/** The local file browser for the template editor */ +export function TemplateEditorBrowser(props: { onClose?: () => void }) { + const classes = useStyles(); + const directoryEditor = useDirectoryEditor(); + const changedFiles = directoryEditor.files.filter(file => file.dirty); + + const handleClose = () => { + if (!props.onClose) { + return; + } + if (changedFiles.length > 0) { + // eslint-disable-next-line no-alert + const accepted = window.confirm( + 'Are you sure? Unsaved changes will be lost', + ); + if (!accepted) { + return; + } + } + props.onClose(); + }; + + return ( + <> +
+ + +
+

Learn more about the software catalog

+ + + READ + +
+
+ + +
+

Build your own software templates

+ + + CONTRIBUTE + +
+
+ + +
+

Learn more about TechDocs

+ + + DOCS + +
+
+ + +
+

Learn more about Backstage Search

+ + + READ + +
+
+ + +
+

Learn more about the K8s plugin

+ + + READ + +
+
+ + +
+

Build a plugin

+ + + CONTRIBUTE + +
+
); diff --git a/microsite-next/src/pages/home/home.module.scss b/microsite-next/src/pages/home/home.module.scss index aa442a0c7b..de15e49140 100644 --- a/microsite-next/src/pages/home/home.module.scss +++ b/microsite-next/src/pages/home/home.module.scss @@ -1,3 +1,5 @@ +$desktopUpBreakpoint: 997px; + .homePage { font-size: 1.25rem; @@ -46,21 +48,28 @@ display: grid; align-items: center; - grid-template-columns: repeat(4, 1fr); - picture { display: block; - - grid-row: 1/3; - grid-column: 3/-1; + text-align: center; } :global(.catalogTitle) { - grid-column: 1/3; - img { max-width: 190px; max-height: 190px; } } + + @media (min-width: $desktopUpBreakpoint) { + grid-template-columns: repeat(4, 1fr); + + picture { + grid-row: 1/3; + grid-column: 3/-1; + } + + :global(.catalogTitle) { + grid-column: 1/3; + } + } } From b4168778c0a5e6fdebead7d3da1a11d61bdda966 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Tue, 7 Feb 2023 22:18:37 -0500 Subject: [PATCH 170/417] feat: Add Software Templates section & _home page SCSS improvements Signed-off-by: Carlos Esteban Lopez --- microsite-next/src/pages/home/_home.tsx | 48 +++++++++++++++++++ .../src/pages/home/home.module.scss | 30 ++++++++++-- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx index a715ee93a9..afc8381ec1 100644 --- a/microsite-next/src/pages/home/_home.tsx +++ b/microsite-next/src/pages/home/_home.tsx @@ -169,6 +169,54 @@ export function Home() { + +
+
+ Software Templates Rocket GIF + +

Backstage Software Templates

+ +

Standards can set you free

+
+ + + + + + + + Using templates, engineers can spin up a new microservice with + your organization's best practices built-in, right from the start + + + + Click a button to create a Spring Boot project with your repo + automatically configured on GitHub and your CI already running the + first build + + + + Go instead of Java? CircleCI instead of Jenkins? Serverless + instead of Kubernetes? GCP instead of AWS? Customize your recipes + with your best practices baked-in + + + + When the right way is also the easiest way, engineers get up and + running faster — and more safely + +
+
+

Build your own software templates

diff --git a/microsite-next/src/pages/home/home.module.scss b/microsite-next/src/pages/home/home.module.scss index de15e49140..1cc4ba8238 100644 --- a/microsite-next/src/pages/home/home.module.scss +++ b/microsite-next/src/pages/home/home.module.scss @@ -43,7 +43,9 @@ $desktopUpBreakpoint: 997px; } } -.catalogContainer { +// Shared container styles +.catalogContainer, +.softwareTemplatesContainer { gap: 2rem; display: grid; align-items: center; @@ -53,23 +55,41 @@ $desktopUpBreakpoint: 997px; text-align: center; } - :global(.catalogTitle) { + :global([class*='Title']), + :global([class*='title']) { img { max-width: 190px; max-height: 190px; } } +} +.catalogContainer { @media (min-width: $desktopUpBreakpoint) { grid-template-columns: repeat(4, 1fr); picture { - grid-row: 1/3; - grid-column: 3/-1; + grid-row: span 2; + grid-column: span 2; } :global(.catalogTitle) { - grid-column: 1/3; + grid-column: span 2; + } + } +} + +.softwareTemplatesContainer { + @media (min-width: $desktopUpBreakpoint) { + grid: repeat(2, auto) / repeat(4, 1fr); + + picture { + grid-row-start: 3; + grid-column: span 4; + } + + :global(.softwareTemplatesTitle) { + grid-column: span 4; } } } From cc4f67d95256f91e914f3d25c7811bbc9b234370 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Wed, 8 Feb 2023 19:14:37 -0500 Subject: [PATCH 171/417] feat: Home page sections complete Signed-off-by: Carlos Esteban Lopez --- microsite-next/src/pages/home/_home.tsx | 231 +++++++++++++++++++++++- 1 file changed, 225 insertions(+), 6 deletions(-) diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx index afc8381ec1..59951646ce 100644 --- a/microsite-next/src/pages/home/_home.tsx +++ b/microsite-next/src/pages/home/_home.tsx @@ -1,13 +1,13 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import { BannerSection } from '@site/src/components/banner-section/banner-section'; +import { BannerSectionColumns } from '@site/src/components/banner-section/banner-section-columns'; +import { ContentBlock } from '@site/src/components/content-block/content-block'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; import React from 'react'; -import { BannerSection } from '../../components/banner-section/banner-section'; import homeStyles from './home.module.scss'; -import { BannerSectionColumns } from '../../components/banner-section/banner-section-columns'; -import { ContentBlock } from '@site/src/components/content-block/content-block'; export function Home() { const { siteConfig } = useDocusaurusContext(); @@ -118,7 +118,7 @@ export function Home() { /> @@ -169,7 +169,7 @@ export function Home() {
- +
- + Software Templates Cards + +
+
+ Backstage TechDocs File Copy GIF + +

Backstage TechDocs

+ +

Docs like code

+
+ + + + Backstage TechDocs Markdown to HTML + + + + Whenever you use a Backstage Software Template, your project + automatically gets a TechDocs site, for free + + + + With our docs-like-code approach, engineers write their + documentation in Markdown files right alongside their code + + + + Updating code? Update your documentation while you're there — with + docs and code in the same place, it becomes a natural part of your + workstream + + + + Since all your documentation is in Backstage, finding any TechDoc + is just a search query away + +
+
+

Learn more about TechDocs

@@ -243,6 +293,54 @@ export function Home() {
+ +
+
+ Search Platform Telescope GIF + +

Backstage Search Platform

+ +

A search platform made just for you

+
+ + + + Search Platform Search Bar + + + + Backstage Search more than just a box you type questions into — + it's an entire platform all by itself, which you can customize to + fit your organization's needs + + + + Bring your own search engine, create a customized search page + experience, or edit the look and feel of each search result + + + + With an extensible backend, you can search beyond the Software + Catalog and index any source you'd like — whether it's TechDocs or + Confluence and Stack Overflow + + + + New hires and seasoned employees alike can easily search your + infrastructure instead of getting lost in it + +
+
+

Learn more about Backstage Search

@@ -256,6 +354,50 @@ export function Home() {
+ + +
+ Backstage Kubernetes Flag GIF + +

Backstage Kubernetes

+ +

Manage your services, not clusters

+
+
+ } + > + + Backstage features the first Kubernetes monitoring tool designed + around the needs of service owners, not cluster admins + + + + Get all your service's deployments in one, aggregated view — no + more digging through cluster logs in a CLI, no more combing + through lists of services you don't own + + + + Since Backstage uses the Kubernetes API, it's cloud agnostic — so + it works no matter which cloud provider or managed Kubernetes + service you use, and even works in multi-cloud orgs + + + + Now you don't have to switch dashboards when you move from local + testing to production, or from one cloud provider to another + + + +

Learn more about the K8s plugin

@@ -269,6 +411,65 @@ export function Home() {
+ +
+
+ Plugins Building Blocks GIF + +

+ Customize Backstage with plugins +

+ +

An app store for your infrastructure

+
+ + + + Plugins Cards + + + + Want scalable website testing? Add the{' '} + + Lighthouse{' '} + + plugin. Wondering about recommended frameworks? Add the{' '} + + Tech Radar{' '} + + plugin. + + + + If you don't see the plugin you need, it's simple to build your + own + + + + Building internal plugins lets you tailor your version of + Backstage to be a perfect fit for your infrastructure + + + + Building open source plugins{' '} + contributes to the entire Backstage ecosystem, which benefits + everyone + +
+
+

Build a plugin

@@ -281,6 +482,24 @@ export function Home() {
+ + +
+

+ Backstage is a{' '} + + Cloud Native Computing Foundation + {' '} + incubation project +

+ + CNCF Logo +
+
); From 0e22cacc48f2a8a4a4868c92e60a580fafa83f09 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Thu, 9 Feb 2023 18:29:08 -0500 Subject: [PATCH 172/417] feat: Hardcode dar theme, set up top left logo & add adopters form Signed-off-by: Carlos Esteban Lopez --- microsite-next/docusaurus.config.js | 9 ++- microsite-next/src/pages/home/_home.tsx | 71 ++++++++++++++----- .../home/_hub-spot-new-adopters-form.tsx | 52 ++++++++++++++ .../src/pages/home/home.module.scss | 4 ++ .../hub-spot-new-adopters-form.module.scss | 38 ++++++++++ 5 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 microsite-next/src/pages/home/_hub-spot-new-adopters-form.tsx create mode 100644 microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index 28e74f3633..4f7e0472be 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -85,8 +85,15 @@ module.exports = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ { + colorMode: { + defaultMode: 'dark', + // disableSwitch: true, + }, navbar: { - title: 'Backstage Software Catalog and Developer Platform', + logo: { + alt: 'Backstage Software Catalog and Developer Platform', + src: 'img/logo.svg', + }, items: [ { href: 'https://github.com/backstage/backstage', diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx index 59951646ce..292a5a2dc0 100644 --- a/microsite-next/src/pages/home/_home.tsx +++ b/microsite-next/src/pages/home/_home.tsx @@ -5,39 +5,70 @@ import { BannerSectionColumns } from '@site/src/components/banner-section/banner import { ContentBlock } from '@site/src/components/content-block/content-block'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; -import React from 'react'; +import React, { useState } from 'react'; import homeStyles from './home.module.scss'; +import { HubSpotNewAdoptersForm } from './_hub-spot-new-adopters-form'; + +const hiddenNewsletterBannerKey = 'hiddenNewsletterBanner'; export function Home() { const { siteConfig } = useDocusaurusContext(); + const [hiddenNewsletterBanner, setHideNewsletterBanner] = useState(() => { + return JSON.parse(localStorage.getItem(hiddenNewsletterBannerKey)) || false; + }); + + const hideNewsletterBanner = (shouldHide: boolean) => { + localStorage.setItem(hiddenNewsletterBannerKey, JSON.stringify(shouldHide)); + setHideNewsletterBanner(shouldHide); + }; + return (
-
- 🗞️ Want to stay up to date with Backstage? Sign up for our{' '} - + {!hiddenNewsletterBanner && ( +
- Newsletter - - ! -
+
+ 🗞️ Want to stay up to date with Backstage? Sign up for our{' '} + + Newsletter + + ! +
-
X
-
+
hideNewsletterBanner(true)} + > + + + +
+
+ )} + } >
+ + ); diff --git a/microsite-next/src/pages/home/_hub-spot-new-adopters-form.tsx b/microsite-next/src/pages/home/_hub-spot-new-adopters-form.tsx new file mode 100644 index 0000000000..18b720098f --- /dev/null +++ b/microsite-next/src/pages/home/_hub-spot-new-adopters-form.tsx @@ -0,0 +1,52 @@ +import clsx from 'clsx'; +import React, { useEffect, useState } from 'react'; + +import hubSpotStyles from './hub-spot-new-adopters-form.module.scss'; + +export const HubSpotNewAdoptersForm = () => { + const [isClosed, setClosed] = useState(true); + + useEffect(() => { + const script = document.createElement('script'); + script.src = 'https://js.hsforms.net/forms/v2.js'; + document.body.appendChild(script); + + script.addEventListener('load', () => { + // @ts-ignore + if (window.hbspt) { + // @ts-ignore + window.hbspt.forms.create({ + portalId: '21894833', + formId: '9a5aa2af-87f3-4a44-819f-88ee243bb61e', + target: `.${hubSpotStyles.hubSpotNewAdopterFormContent}`, + pageId: '79735607665', + }); + } + }); + }, []); + + return ( +
+ + +
+
+ ); +}; diff --git a/microsite-next/src/pages/home/home.module.scss b/microsite-next/src/pages/home/home.module.scss index 1cc4ba8238..6b33c17681 100644 --- a/microsite-next/src/pages/home/home.module.scss +++ b/microsite-next/src/pages/home/home.module.scss @@ -26,6 +26,10 @@ $desktopUpBreakpoint: 997px; :global(.bannerContent) { flex: 1; } + + :global(.bannerCloseButton) { + color: var(--ifm-color-secondary); + } } .svgContainer { diff --git a/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss b/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss new file mode 100644 index 0000000000..83735db349 --- /dev/null +++ b/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss @@ -0,0 +1,38 @@ +.hubSpotNewAdopterFormContainer { + top: 50%; + right: 0; + display: flex; + position: fixed; + transform: translateY(-50%); + + transition: all 250ms ease-in-out; + + &:global(.adoptersFormHidden) { + transform: translate(500px, -50%); + } + + > button { + top: 50%; + left: -2rem; + position: fixed; + + transform: rotate(-90deg) translateX(-50%); + transform-origin: top left; + } +} + +.hubSpotNewAdopterFormContent { + height: 600px; + max-width: 500px; + overflow-y: hidden; + border-radius: 8px 0 0 8px; + background-color: var(--ifm-color-content); + + form { + width: 100%; + height: 100%; + overflow-y: auto; + + padding-right: 2rem; + } +} From 0a3024c9a6fcd9a8e19d74448867d9ed00065fa9 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Thu, 9 Feb 2023 18:39:45 -0500 Subject: [PATCH 173/417] fix: Fix adopters form background & remove theme switch from config Signed-off-by: Carlos Esteban Lopez --- microsite-next/docusaurus.config.js | 2 +- .../src/pages/home/hub-spot-new-adopters-form.module.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index 4f7e0472be..52867ed121 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -87,7 +87,7 @@ module.exports = { { colorMode: { defaultMode: 'dark', - // disableSwitch: true, + disableSwitch: true, }, navbar: { logo: { diff --git a/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss b/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss index 83735db349..77e1a87a53 100644 --- a/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss +++ b/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss @@ -26,7 +26,7 @@ max-width: 500px; overflow-y: hidden; border-radius: 8px 0 0 8px; - background-color: var(--ifm-color-content); + background-color: var(--ifm-color-white); form { width: 100%; From 537b921b8359e02d510594db73df270fb86909c3 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Tue, 14 Feb 2023 16:44:03 -0500 Subject: [PATCH 174/417] refactor: Improve grid components & replace them in community page Signed-off-by: Carlos Esteban Lopez --- .../banner-section-columns.module.scss | 43 --- .../banner-section/banner-section-columns.tsx | 34 --- .../banner-section-grid.module.scss | 20 ++ .../banner-section/banner-section-grid.tsx | 35 +++ .../banner-section/banner-section.tsx | 8 +- .../content-block/content-block.module.scss | 10 +- .../content-block/content-block.tsx | 50 ++-- .../src/pages/community/_community.tsx | 267 +++++++++--------- .../src/pages/community/community.module.scss | 53 +--- microsite-next/src/pages/demos/_demos.tsx | 73 +++-- .../src/pages/demos/demos.module.scss | 4 - microsite-next/src/pages/home/_home.tsx | 111 ++++---- .../src/pages/home/home.module.scss | 12 +- 13 files changed, 325 insertions(+), 395 deletions(-) delete mode 100644 microsite-next/src/components/banner-section/banner-section-columns.module.scss delete mode 100644 microsite-next/src/components/banner-section/banner-section-columns.tsx create mode 100644 microsite-next/src/components/banner-section/banner-section-grid.module.scss create mode 100644 microsite-next/src/components/banner-section/banner-section-grid.tsx diff --git a/microsite-next/src/components/banner-section/banner-section-columns.module.scss b/microsite-next/src/components/banner-section/banner-section-columns.module.scss deleted file mode 100644 index 32cc53eb5e..0000000000 --- a/microsite-next/src/components/banner-section/banner-section-columns.module.scss +++ /dev/null @@ -1,43 +0,0 @@ -.bannerSection { - display: block; - - &:global(.greyBackground) { - background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%); - } - - &:global(.greenGradientBackground) { - background: linear-gradient( - 178.64deg, - hsla(0, 0%, 100%, 0) 57.61%, - hsla(0, 0%, 100%, 0.17) 127.71% - ), - linear-gradient( - 144.35deg, - rgba(98, 197, 179, 0) 56.68%, - rgba(98, 197, 179, 0.59) 109.25% - ), - linear-gradient( - 192.29deg, - rgba(155, 240, 225, 0) 54.17%, - rgba(155, 240, 225, 0.67) 137.34% - ); - } - - &:global(.greenBottomGradientBackground) { - background: linear-gradient( - 178.64deg, - hsla(0, 0%, 100%, 0) 57.61%, - hsla(0, 0%, 100%, 0.17) 127.71% - ), - linear-gradient( - 144.35deg, - rgba(98, 197, 179, 0) 56.68%, - rgba(98, 197, 179, 0.59) 109.25% - ), - linear-gradient( - 192.29deg, - rgba(155, 240, 225, 0) 54.17%, - rgba(155, 240, 225, 0.67) 137.34% - ); - } -} diff --git a/microsite-next/src/components/banner-section/banner-section-columns.tsx b/microsite-next/src/components/banner-section/banner-section-columns.tsx deleted file mode 100644 index db33b52961..0000000000 --- a/microsite-next/src/components/banner-section/banner-section-columns.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import clsx from 'clsx'; -import React, { PropsWithChildren, ReactNode } from 'react'; - -import bannerColumnStyles from './banner-section-columns.module.scss'; - -export type IBannerSectionColumnsProps = PropsWithChildren<{ - header?: ReactNode; - // children: ReactNode | ReactNode[]; -}>; - -export const BannerSectionColumns = ({ - header, - children, -}: IBannerSectionColumnsProps) => ( - <> - {header && ( -
-
{header}
-
- )} - - {Array.isArray(children) ? ( -
- {children.map((child, index) => ( -
- {child} -
- ))} -
- ) : ( - children - )} - -); diff --git a/microsite-next/src/components/banner-section/banner-section-grid.module.scss b/microsite-next/src/components/banner-section/banner-section-grid.module.scss new file mode 100644 index 0000000000..c57b82ac57 --- /dev/null +++ b/microsite-next/src/components/banner-section/banner-section-grid.module.scss @@ -0,0 +1,20 @@ +$desktopUpBreakpoint: 997px; + +.sectionGridContainer { + gap: 2rem; + display: grid; + + :global(.gridHeader) { + grid-column: 1 / -1; + } +} + +.gridContainer { + gap: 2rem; + display: grid; + align-items: center; + + @media (min-width: $desktopUpBreakpoint) { + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + } +} diff --git a/microsite-next/src/components/banner-section/banner-section-grid.tsx b/microsite-next/src/components/banner-section/banner-section-grid.tsx new file mode 100644 index 0000000000..7846ffe010 --- /dev/null +++ b/microsite-next/src/components/banner-section/banner-section-grid.tsx @@ -0,0 +1,35 @@ +import clsx from 'clsx'; +import React, { PropsWithChildren, ReactNode } from 'react'; + +import bannerGridStyles from './banner-section-grid.module.scss'; + +export type IBannerSectionColumnsProps = PropsWithChildren<{ + header?: ReactNode; + className?: string; + // children: ReactNode | ReactNode[]; +}>; + +export const BannerSectionGrid = ({ + header, + children, + className, +}: IBannerSectionColumnsProps) => { + console.log('Header: ', header); + + return ( +
+ {header &&
{header}
} + +
+ {Array.isArray(children) + ? children.map((child, index) => + React.cloneElement(child, { + key: index, + className: clsx(child.props.className), + }), + ) + : children} +
+
+ ); +}; diff --git a/microsite-next/src/components/banner-section/banner-section.tsx b/microsite-next/src/components/banner-section/banner-section.tsx index dbab99200e..564b1f2043 100644 --- a/microsite-next/src/components/banner-section/banner-section.tsx +++ b/microsite-next/src/components/banner-section/banner-section.tsx @@ -4,6 +4,7 @@ import React, { PropsWithChildren } from 'react'; import bannerStyles from './banner-section.module.scss'; export type IBannerSectionProps = PropsWithChildren<{ + className?: string; greyBackground?: boolean; greenGradientBackground?: boolean; greenBottomGradientBackground?: boolean; @@ -12,19 +13,22 @@ export type IBannerSectionProps = PropsWithChildren<{ export const BannerSection = ({ children, + className, greyBackground = false, greenGradientBackground = false, greenBottomGradientBackground = false, greenCallToActionGradientBackground = false, }: IBannerSectionProps) => (
-
{children}
+
+ {children} +
); diff --git a/microsite-next/src/components/content-block/content-block.module.scss b/microsite-next/src/components/content-block/content-block.module.scss index 77f98400f7..9a34c55390 100644 --- a/microsite-next/src/components/content-block/content-block.module.scss +++ b/microsite-next/src/components/content-block/content-block.module.scss @@ -1,6 +1,9 @@ .contentBlock { + height: 100%; + gap: 1.5rem; display: grid; + align-items: center; > *, h1, @@ -9,6 +12,10 @@ padding: 0; } + :global(.contentBlockTitle) { + align-self: start; + } + :global(.bulletLine) { width: 50px; margin-bottom: 0.5rem; @@ -17,6 +24,7 @@ :global(.actionButtons) { gap: 1rem; display: grid; - grid-template-columns: repeat(2, auto); + align-self: end; + grid-template-columns: repeat(auto-fit, minmax(100px, auto)); } } diff --git a/microsite-next/src/components/content-block/content-block.tsx b/microsite-next/src/components/content-block/content-block.tsx index 4c1cc6272e..ae67070953 100644 --- a/microsite-next/src/components/content-block/content-block.tsx +++ b/microsite-next/src/components/content-block/content-block.tsx @@ -24,32 +24,30 @@ export const ContentBlock = ({ topImgSrc, hasBulletLine, actionButtons, -}: IContentBlockProps) => { - return ( -
- {topImgSrc && {topImgSrc}} +}: IContentBlockProps) => ( +
+ {topImgSrc && {topImgSrc}} -
- {hasBulletLine &&
} +
+ {hasBulletLine &&
} - {title && React.isValidElement(title) ? title :

{title}

} -
- - {children &&

{children}

} - - {actionButtons && ( -
- {actionButtons.map(({ link, label }, index) => ( - - {label} - - ))} -
- )} + {title && React.isValidElement(title) ? title :

{title}

}
- ); -}; + + {children && React.isValidElement(children) ? children :

{children}

} + + {actionButtons && ( +
+ {actionButtons.map(({ link, label }, index) => ( + + {label} + + ))} +
+ )} +
+); diff --git a/microsite-next/src/pages/community/_community.tsx b/microsite-next/src/pages/community/_community.tsx index 3ea0c36da9..082d656454 100644 --- a/microsite-next/src/pages/community/_community.tsx +++ b/microsite-next/src/pages/community/_community.tsx @@ -1,10 +1,13 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import { BannerSection } from '@site/src/components/banner-section/banner-section'; +import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; import React from 'react'; import communityStyles from './community.module.scss'; +import { ContentBlock } from '../../components/content-block/content-block'; interface ICollectionItem { title?: string; @@ -128,155 +131,137 @@ export function Community() { return (
-
-
-
-
-

- Backstage Community -

+ + + Backstage Community} + > + Join the vibrant community around Backstage through social media + and different meetups. To ensure that you have a welcoming + environment, we follow the + + {' '} + CNCF Code of Conduct{' '} + + in everything we do. + -

- Join the vibrant community around Backstage through social - media and different meetups. To ensure that you have a - welcoming environment, we follow the - - {' '} - CNCF Code of Conduct{' '} - - in everything we do. -

-
- -
-

- Get started in our community! -

- -
    - {communityListItems.map( - ({ content: text, link, label }, index) => ( -
  • -

    - {text} {label} -

    -
  • - ), - )} -
-
-
-
-
- -
-
-
-

Offical Backstage initiatives

- -

Stay tuned to the latest developments

-
- -
- {officialInitiatives.map( - ({ title, content, link, label }, index) => ( -
-
- -

{title}

- -

{content}

- - - {label} - -
- ), + -
-
+ title="Get started in our community!" + > +
    + {communityListItems.map( + ({ content: text, link, label }, index) => ( +
  • +

    + {text} {label} +

    +
  • + ), + )} +
+ + + -
-
-
-

Community initiatives

-
+ + +

Offical Backstage initiatives

-
- {communityInitiatives.map( - ({ title, content, link, label }, index) => ( -
-
+

Stay tuned to the latest developments

+ + } + > + {officialInitiatives.map( + ({ title, content, link, label }, index) => ( + + {content} + + ), + )} + + -

{title}

+ + Community initiatives} + > + {communityInitiatives.map( + ({ title, content, link, label }, index) => ( + +

{content}

+
+ ), + )} +
+
-

{content}

- - - {label} - -
- ), - )} -
-
-
- -
-
-
+ + Trainings and Certifications -
+ } + > + {trainingNCertifications.map( + ({ title, content, link, label }, index) => ( + +

{content}

+
+ ), + )} + + -
- {trainingNCertifications.map( - ({ title, content, link, label }, index) => ( -
-
- -

{title}

- -

{content}

- - - {label} - -
- ), - )} -
-
-
- -
-
-
-

Commercial Partners

-
- -
- {partners.map(({ name, url, logo }, index) => ( -
- - {name} - -
- ))} -
-
-
+ + Commercial Partners} + > + {partners.map(({ name, url, logo }, index) => ( +
+ + {name} + +
+ ))} +
+
); diff --git a/microsite-next/src/pages/community/community.module.scss b/microsite-next/src/pages/community/community.module.scss index 5052b7d3b2..3f829b0100 100644 --- a/microsite-next/src/pages/community/community.module.scss +++ b/microsite-next/src/pages/community/community.module.scss @@ -8,60 +8,21 @@ line-height: 56px; word-break: break-word; } -} -.banner, -.officialInitiatives, -.communityInitiatives, -.trainingNCertifications, -.commercialPartners { - :global(.row .col) { - max-width: 50%; - - display: flex; - flex-direction: column; - - :global(.bulletLine) { - width: 50px; - } - - p { - text-align: justify; - flex: 1; - } + p { + text-align: justify; } } -.banner, -.communityInitiatives, -.commercialPartners { - background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%); - // clip-path: polygon(0 0, 100% 0, 100% calc(100% - 2vw - 10px), 0 100%); -} +.listContainer { + height: 100%; + align-items: stretch !important; + grid-template-rows: auto 1fr; -.banner { ul { - flex: 1; + height: 100%; display: flex; flex-direction: column; justify-content: space-between; } } - -.officialInitiatives { - background: linear-gradient( - 178.64deg, - hsla(0, 0%, 100%, 0) 57.61%, - hsla(0, 0%, 100%, 0.17) 127.71% - ), - linear-gradient( - 144.35deg, - rgba(98, 197, 179, 0) 56.68%, - rgba(98, 197, 179, 0.59) 109.25% - ), - linear-gradient( - 192.29deg, - rgba(155, 240, 225, 0) 54.17%, - rgba(155, 240, 225, 0.67) 137.34% - ); -} diff --git a/microsite-next/src/pages/demos/_demos.tsx b/microsite-next/src/pages/demos/_demos.tsx index 4c035dd130..65c04c5282 100644 --- a/microsite-next/src/pages/demos/_demos.tsx +++ b/microsite-next/src/pages/demos/_demos.tsx @@ -1,5 +1,8 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import { BannerSection } from '@site/src/components/banner-section/banner-section'; +import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; +import { ContentBlock } from '@site/src/components/content-block/content-block'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; import React from 'react'; @@ -162,50 +165,38 @@ export function Demos() {
{demoItems.map((demoItem, index) => ( -
-
-
-
-

- {demoItem.title} -

+ + {demoItem.title}} + actionButtons={[ + { + link: demoItem.actionItemLink, + label: 'WATCH NOW', + }, + ]} + > + {demoItem.content} + - {React.isValidElement(demoItem.content) ? ( - demoItem.content - ) : ( -

{demoItem.content}

- )} - - {demoItem.actionItemLink && ( - - WATCH NOW - - )} -
- -
- {demoItem.media.type === 'image' ? ( - {demoItem.title} - ) : ( - - )} -
+
+ {demoItem.media.type === 'image' ? ( + {demoItem.title} + ) : ( + + )}
-
-
+ + ))}
diff --git a/microsite-next/src/pages/demos/demos.module.scss b/microsite-next/src/pages/demos/demos.module.scss index 0a567c45a7..b99874297e 100644 --- a/microsite-next/src/pages/demos/demos.module.scss +++ b/microsite-next/src/pages/demos/demos.module.scss @@ -22,7 +22,3 @@ min-height: 500px; } } - -.bannerGradient { - background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%); -} diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx index 292a5a2dc0..7f7f008bc4 100644 --- a/microsite-next/src/pages/home/_home.tsx +++ b/microsite-next/src/pages/home/_home.tsx @@ -1,7 +1,8 @@ +import BrowserOnly from '@docusaurus/BrowserOnly'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import { BannerSection } from '@site/src/components/banner-section/banner-section'; -import { BannerSectionColumns } from '@site/src/components/banner-section/banner-section-columns'; +import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; import { ContentBlock } from '@site/src/components/content-block/content-block'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; @@ -12,7 +13,7 @@ import { HubSpotNewAdoptersForm } from './_hub-spot-new-adopters-form'; const hiddenNewsletterBannerKey = 'hiddenNewsletterBanner'; -export function Home() { +const HomePage = () => { const { siteConfig } = useDocusaurusContext(); const [hiddenNewsletterBanner, setHideNewsletterBanner] = useState(() => { @@ -28,47 +29,42 @@ export function Home() {
- - {!hiddenNewsletterBanner && ( -
-
- 🗞️ Want to stay up to date with Backstage? Sign up for our{' '} - - Newsletter - - ! -
- -
hideNewsletterBanner(true)} + !hiddenNewsletterBanner && ( +
+
+ 🗞️ Want to stay up to date with Backstage? Sign up for our{' '} + - - - -
+ Newsletter + + !
- )} - + +
hideNewsletterBanner(true)} + > + + + +
+
+ ) } >
-
+
- + - + @@ -386,20 +382,19 @@ export function Home() { - -
- Backstage Kubernetes Flag GIF + <> + Backstage Kubernetes Flag GIF -

Backstage Kubernetes

+

Backstage Kubernetes

-

Manage your services, not clusters

-
-
+

Manage your services, not clusters

+ } > - + @@ -536,4 +531,8 @@ export function Home() {
); -} +}; + +export const Home = () => { + return {() => }; +}; diff --git a/microsite-next/src/pages/home/home.module.scss b/microsite-next/src/pages/home/home.module.scss index 6b33c17681..57f2b9acde 100644 --- a/microsite-next/src/pages/home/home.module.scss +++ b/microsite-next/src/pages/home/home.module.scss @@ -60,7 +60,8 @@ $desktopUpBreakpoint: 997px; } :global([class*='Title']), - :global([class*='title']) { + :global([class*='title']), + :global([class*='gridHeader']) { img { max-width: 190px; max-height: 190px; @@ -97,3 +98,12 @@ $desktopUpBreakpoint: 997px; } } } + +.kubernetesSectionContainer { + :global([class*='gridHeader']) { + img { + max-width: 190px; + max-height: 190px; + } + } +} From acff7b701bbe4e9aa2b4d960cb6032425508a7a2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 00:36:49 +0000 Subject: [PATCH 175/417] chore(deps): update dependency @types/inquirer to v8.2.6 Signed-off-by: Renovate Bot --- yarn.lock | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index ba9593e38a..7e4005f2c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14562,11 +14562,12 @@ __metadata: linkType: hard "@types/inquirer@npm:^8.1.3": - version: 8.2.5 - resolution: "@types/inquirer@npm:8.2.5" + version: 8.2.6 + resolution: "@types/inquirer@npm:8.2.6" dependencies: "@types/through": "*" - checksum: 932c432e634697bcff5d50fdc9e64f90d2e31c5ebcda909f2e9704d0433b5ec608b6ece985c6e57a283f3b62434f1cd3619b64ca61433d7c3bdb41d3c5f27586 + rxjs: ^7.2.0 + checksum: d09c3b6bbfb1aff8bdb8fc938d43536be55dfb51af0c91d0105e3f7c5e3950c12618ac00e2e91f10b5abeba38f4b903289be1df5aa31f213b58c3cc675a19f81 languageName: node linkType: hard @@ -34590,7 +34591,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^7.0.0, rxjs@npm:^7.5.1, rxjs@npm:^7.5.5, rxjs@npm:^7.5.6, rxjs@npm:^7.8.0": +"rxjs@npm:^7.0.0, rxjs@npm:^7.2.0, rxjs@npm:^7.5.1, rxjs@npm:^7.5.5, rxjs@npm:^7.5.6, rxjs@npm:^7.8.0": version: 7.8.0 resolution: "rxjs@npm:7.8.0" dependencies: From f9b1ec31f1b8ce5173ce672d9faa5caa0f80b491 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 10:19:39 +0100 Subject: [PATCH 176/417] Some initial code Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/.eslintrc.js | 1 + plugins/octopus-deploy/README.md | 11 ++ plugins/octopus-deploy/dev/index.tsx | 12 ++ plugins/octopus-deploy/package.json | 52 ++++++++ plugins/octopus-deploy/src/api/index.ts | 88 +++++++++++++ .../EntityPageOctopusDeploy.tsx | 15 +++ .../EntityPageOctopusDeploy/index.ts | 1 + .../components/ReleaseTable/ReleaseTable.tsx | 123 ++++++++++++++++++ .../src/components/ReleaseTable/index.ts | 1 + plugins/octopus-deploy/src/constants.ts | 1 + .../octopus-deploy/src/hooks/useReleases.ts | 26 ++++ plugins/octopus-deploy/src/index.ts | 7 + plugins/octopus-deploy/src/plugin.test.ts | 7 + plugins/octopus-deploy/src/plugin.ts | 49 +++++++ plugins/octopus-deploy/src/routes.ts | 5 + plugins/octopus-deploy/src/setupTests.ts | 2 + .../src/utils/getAnnotationFromEntity.ts | 14 ++ 17 files changed, 415 insertions(+) create mode 100644 plugins/octopus-deploy/.eslintrc.js create mode 100644 plugins/octopus-deploy/README.md create mode 100644 plugins/octopus-deploy/dev/index.tsx create mode 100644 plugins/octopus-deploy/package.json create mode 100644 plugins/octopus-deploy/src/api/index.ts create mode 100644 plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx create mode 100644 plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts create mode 100644 plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx create mode 100644 plugins/octopus-deploy/src/components/ReleaseTable/index.ts create mode 100644 plugins/octopus-deploy/src/constants.ts create mode 100644 plugins/octopus-deploy/src/hooks/useReleases.ts create mode 100644 plugins/octopus-deploy/src/index.ts create mode 100644 plugins/octopus-deploy/src/plugin.test.ts create mode 100644 plugins/octopus-deploy/src/plugin.ts create mode 100644 plugins/octopus-deploy/src/routes.ts create mode 100644 plugins/octopus-deploy/src/setupTests.ts create mode 100644 plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts diff --git a/plugins/octopus-deploy/.eslintrc.js b/plugins/octopus-deploy/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/octopus-deploy/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/octopus-deploy/README.md b/plugins/octopus-deploy/README.md new file mode 100644 index 0000000000..26f8021283 --- /dev/null +++ b/plugins/octopus-deploy/README.md @@ -0,0 +1,11 @@ +# Octopus Deploy Plugin + +Welcome to the octopus-deploy plugin! + +## Features + +- Display the deployment status of the most recent releases for a project in Octopus Deploy straight from the Backstage catalog + +## Getting started + + diff --git a/plugins/octopus-deploy/dev/index.tsx b/plugins/octopus-deploy/dev/index.tsx new file mode 100644 index 0000000000..503cbe6d12 --- /dev/null +++ b/plugins/octopus-deploy/dev/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { createDevApp } from '@backstage/dev-utils'; +import { octopusDeployPlugin, OctopusDeployPage } from '../src/plugin'; + +createDevApp() + .registerPlugin(octopusDeployPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/octopus-deploy' + }) + .render(); diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json new file mode 100644 index 0000000000..8486ed1a32 --- /dev/null +++ b/plugins/octopus-deploy/package.json @@ -0,0 +1,52 @@ +{ + "name": "@backstage/plugin-octopus-deploy", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": true, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/core-components": "^0.12.3", + "@backstage/core-plugin-api": "^1.3.0", + "@backstage/theme": "^0.2.16", + "@material-ui/core": "^4.9.13", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.57", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "^0.22.1", + "@backstage/core-app-api": "^1.4.0", + "@backstage/dev-utils": "^1.0.11", + "@backstage/test-utils": "^1.2.4", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "msw": "^0.49.0", + "cross-fetch": "^3.1.5" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/octopus-deploy/src/api/index.ts b/plugins/octopus-deploy/src/api/index.ts new file mode 100644 index 0000000000..b066f700db --- /dev/null +++ b/plugins/octopus-deploy/src/api/index.ts @@ -0,0 +1,88 @@ +import { createApiRef, DiscoveryApi, IdentityApi } from "@backstage/core-plugin-api"; + +export type OctopusProgression = { + Environments: OctopusEnvironment[]; + Releases: OctopusReleaseProgression[]; +} + +export type OctopusEnvironment = { + Id: string, + Name: string +} + +export type OctopusReleaseProgression = { + Release: OctopusRelease + Deployments: { [key: string]: OctopusDeployment[] } +} + +export type OctopusRelease = { + Id: string + Version: string +} + +export type OctopusDeployment = { + State: string +} + +export const octopusDeployApiRef = createApiRef({ + id: 'plugin.octopusdeploy.service' +}); + +const DEFAULT_PROXY_PATH_BASE = '/octopus-deploy'; + +type Options = { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi + /** + * Path to use for requests via the proxy, defaults to /octopus-deploy + */ + proxyPathBase?: string +} + +export interface OctopusDeployApi { + getReleaseProgression(projectId: string, releaseHistoryCount: number): Promise; +} + +export class OctopusDeployClient implements OctopusDeployApi { + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + private readonly proxyPathBase: string; + + constructor(options: Options) { + this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; + this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE; + } + + async getReleaseProgression(projectId: string, releaseHistoryCount: number): Promise { + const url = await this.getApiUrl(projectId, releaseHistoryCount); + + const { token: idToken } = await this.identityApi.getCredentials(); + const response = await fetch(url, { + headers: idToken ? { Authorization: `Bearer ${idToken}` } : {}, + }); + + let responseJson; + + try { + responseJson = await response.json(); + } catch (e) { + responseJson = { releases: [] }; + } + + if (response.status !== 200) { + throw new Error( + `Error communicating with Octopus Deploy: ${ + responseJson?.error?.title || response.statusText + }`, + ); + } + + return responseJson; + } + + private async getApiUrl(projectId: string, releaseHistoryCount: number) { + const proxyUrl = await this.discoveryApi.getBaseUrl('proxy'); + return `${proxyUrl}${this.proxyPathBase}/projects/${projectId}/progression?releaseHistoryCount=${releaseHistoryCount}`; + } +} \ No newline at end of file diff --git a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx new file mode 100644 index 0000000000..d9b6a001c2 --- /dev/null +++ b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx @@ -0,0 +1,15 @@ +import { useEntity } from '@backstage/plugin-catalog-react'; +import { useReleases } from '../../hooks/useReleases'; +import { getAnnotationFromEntity } from '../../utils/getAnnotationFromEntity'; +import React from 'react'; +import { ReleaseTable } from '../ReleaseTable'; + +export const EntityPageOctopusDeploy = (props: { defaultLimit?: number }) => { + const { entity } = useEntity(); + + const projectId = getAnnotationFromEntity(entity); + + const { environments, releases, loading, error } = useReleases(projectId, props.defaultLimit ?? 3); + + return ; +} \ No newline at end of file diff --git a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts new file mode 100644 index 0000000000..ceed04684b --- /dev/null +++ b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts @@ -0,0 +1 @@ +export { EntityPageOctopusDeploy } from './EntityPageOctopusDeploy'; \ No newline at end of file diff --git a/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx b/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx new file mode 100644 index 0000000000..21322057d3 --- /dev/null +++ b/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx @@ -0,0 +1,123 @@ +import { Box, Typography } from "@material-ui/core"; +import { + OctopusEnvironment, + OctopusReleaseProgression +} from '../../api'; + +import React from 'react'; +import { ResponseErrorPanel, StatusAborted, StatusError, StatusOK, StatusPending, StatusRunning, StatusWarning, Table, TableColumn } from "@backstage/core-components"; + +type ReleaseTableProps = { + environments?: OctopusEnvironment[]; + releases?: OctopusReleaseProgression[]; + loading: boolean; + error?: Error +}; + +export const getDeploymentStatusComponent = (state: string | undefined) => { + switch (state) { + case "Success": + return ( + + Success + + ); + case "Queued": + return ( + + Queued + + ); + case "Executing": + return ( + + Executing + + ); + case "Failed": + return ( + + Failed + + ); + case "Cancelling": + return ( + + Cancelling + + ); + case "Canceled": + return ( + + Canceled + + ); + case "TimedOut": + return ( + + Timed Out + + ); + default: + return ( + + Unknown + + ); + } +} + +export const ReleaseTable = ({environments, releases, loading, error}: ReleaseTableProps) => { + if (error) { + return ( +
+ +
+ ); + } + + const columns: TableColumn[] = [ + { + title: 'Version', + field: 'Release.Version', + highlight: false, + width: 'auto' + }, + ...environments?.map(env => ({ + title: env.Name, + width: 'auto', + render: (row: Partial) => { + const deploymentsForEnvironment = row.Deployments[env.Id]; + if (deploymentsForEnvironment) { + return ( + + + {getDeploymentStatusComponent(deploymentsForEnvironment[0].State)} + + + ) + } + } + //field: `Deployments.${env.Id}[0].State` // TODO: We'll probably need to deal with multi-tenant deployments here + })) ?? [] + ] + + return ( +
+ + !file.dirty)} + onClick={() => directoryEditor.save()} + > + + + + + directoryEditor.reload()} + > + + + +
+ + + + + +
+ + file.path)} + /> + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx new file mode 100644 index 0000000000..0ac604c75d --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx @@ -0,0 +1,234 @@ +/* + * Copyright 2022 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 { useApiHolder } from '@backstage/core-plugin-api'; +import { JsonObject, JsonValue } from '@backstage/types'; +import { makeStyles } from '@material-ui/core/styles'; +import React, { Component, ReactNode, useState } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; +import yaml from 'yaml'; +import { + LayoutOptions, + NextFieldExtensionOptions, + Stepper, + TemplateParameterSchema, +} from '@backstage/plugin-scaffolder-react'; + +import { useDirectoryEditor } from './DirectoryEditorContext'; +import { useDryRun } from './DryRunContext'; + +const useStyles = makeStyles({ + containerWrapper: { + position: 'relative', + width: '100%', + height: '100%', + }, + container: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + overflow: 'auto', + }, +}); + +interface ErrorBoundaryProps { + invalidator: unknown; + setErrorText(errorText: string | undefined): void; + children: ReactNode; +} + +interface ErrorBoundaryState { + shouldRender: boolean; +} + +class ErrorBoundary extends Component { + state = { + shouldRender: true, + }; + + componentDidUpdate(prevProps: { invalidator: unknown }) { + if (prevProps.invalidator !== this.props.invalidator) { + this.setState({ shouldRender: true }); + } + } + + componentDidCatch(error: Error) { + this.props.setErrorText(error.message); + this.setState({ shouldRender: false }); + } + + render() { + return this.state.shouldRender ? this.props.children : null; + } +} + +interface TemplateEditorFormProps { + content?: string; + /** Setting this to true will cause the content to be parsed as if it is the template entity spec */ + contentIsSpec?: boolean; + setErrorText: (errorText?: string) => void; + onDryRun?: (data: JsonObject) => Promise; + fieldExtensions?: NextFieldExtensionOptions[]; + layouts?: LayoutOptions[]; +} + +function isJsonObject(value: JsonValue | undefined): value is JsonObject { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} + +/** Shows the a template form that is parsed from the provided content */ +export function TemplateEditorForm(props: TemplateEditorFormProps) { + const { + content, + contentIsSpec, + onDryRun, + setErrorText, + fieldExtensions = [], + layouts = [], + } = props; + const classes = useStyles(); + const apiHolder = useApiHolder(); + + const [steps, setSteps] = useState(); + + useDebounce( + () => { + try { + if (!content) { + setSteps(undefined); + return; + } + const parsed: JsonValue = yaml.parse(content); + + if (!isJsonObject(parsed)) { + setSteps(undefined); + return; + } + + let rootObj = parsed; + if (!contentIsSpec) { + const isTemplate = + String(parsed.kind).toLocaleLowerCase('en-US') === 'template'; + if (!isTemplate) { + setSteps(undefined); + return; + } + + rootObj = isJsonObject(parsed.spec) ? parsed.spec : {}; + } + + const { parameters } = rootObj; + + if (!Array.isArray(parameters)) { + setErrorText('Template parameters must be an array'); + setSteps(undefined); + return; + } + + setErrorText(); + setSteps( + parameters.flatMap(param => + isJsonObject(param) + ? [ + { + title: String(param.title), + schema: param, + }, + ] + : [], + ), + ); + } catch (e) { + setErrorText(e.message); + } + }, + 250, + [contentIsSpec, content, apiHolder], + ); + + if (!steps) { + return null; + } + + return ( +
+
+ + { + await onDryRun?.(data); + }} + layouts={layouts} + components={{ createButtonText: onDryRun && 'Try It' }} + /> + +
+
+ ); +} + +/** A version of the TemplateEditorForm that is connected to the DirectoryEditor and DryRun contexts */ +export function TemplateEditorFormDirectoryEditorDryRun( + props: Pick< + TemplateEditorFormProps, + 'setErrorText' | 'fieldExtensions' | 'layouts' + >, +) { + const { setErrorText, fieldExtensions = [], layouts } = props; + const dryRun = useDryRun(); + + const directoryEditor = useDirectoryEditor(); + const { selectedFile } = directoryEditor; + + const handleDryRun = async (values: JsonObject) => { + if (!selectedFile) { + return; + } + + try { + await dryRun.execute({ + templateContent: selectedFile.content, + values, + files: directoryEditor.files, + }); + setErrorText(); + } catch (e) { + setErrorText(String(e.cause || e)); + throw e; + } + }; + + const content = + selectedFile && selectedFile.path.match(/\.ya?ml$/) + ? selectedFile.content + : undefined; + + return ( + + ); +} + +TemplateEditorForm.DirectoryEditorDryRun = + TemplateEditorFormDirectoryEditorDryRun; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx new file mode 100644 index 0000000000..61e6c46964 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx @@ -0,0 +1,144 @@ +/* + * Copyright 2022 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 React from 'react'; +import Card from '@material-ui/core/Card'; +import CardActionArea from '@material-ui/core/CardActionArea'; +import CardContent from '@material-ui/core/CardContent'; +import Tooltip from '@material-ui/core/Tooltip'; +import Typography from '@material-ui/core/Typography'; +import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'; +import { makeStyles } from '@material-ui/core/styles'; +import { WebFileSystemAccess } from '../../lib/filesystem'; + +const useStyles = makeStyles(theme => ({ + introText: { + textAlign: 'center', + marginTop: theme.spacing(2), + }, + card: { + position: 'relative', + maxWidth: 340, + marginTop: theme.spacing(4), + margin: theme.spacing(0, 2), + }, + infoIcon: { + position: 'absolute', + top: theme.spacing(1), + right: theme.spacing(1), + }, +})); + +interface EditorIntroProps { + style?: JSX.IntrinsicElements['div']['style']; + onSelect?: (option: 'local' | 'form' | 'field-explorer') => void; +} + +export function TemplateEditorIntro(props: EditorIntroProps) { + const classes = useStyles(); + const supportsLoad = WebFileSystemAccess.isSupported(); + + const cardLoadLocal = ( + + props.onSelect?.('local')} + > + + + Load Template Directory + + + Load a local template directory, allowing you to both edit and try + executing your own template. + + + + {!supportsLoad && ( +
+ + + +
+ )} +
+ ); + + const cardFormEditor = ( + + props.onSelect?.('form')}> + + + Edit Template Form + + + Preview and edit a template form, either using a sample template or + by loading a template from the catalog. + + + + + ); + + const cardFieldExplorer = ( + + props.onSelect?.('field-explorer')}> + + + Custom Field Explorer + + + View and play around with available installed custom field + extensions. + + + + + ); + + return ( +
+ + Get started by choosing one of the options below + +
+ {supportsLoad && cardLoadLocal} + {cardFormEditor} + {!supportsLoad && cardLoadLocal} + {cardFieldExplorer} +
+
+ ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx new file mode 100644 index 0000000000..bf9cd8c464 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx @@ -0,0 +1,58 @@ +/* + * Copyright 2022 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 { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { TemplateEditorPage } from './TemplateEditorPage'; + +describe('TemplateEditorPage', () => { + it('renders without exploding', async () => { + await renderInTestApp(); + + expect(screen.getByText('Load Template Directory')).toBeInTheDocument(); + expect(screen.getByText('Edit Template Form')).toBeInTheDocument(); + }); + + it('template directory loading should not be supported in Jest', async () => { + await renderInTestApp(); + + expect( + screen.getByRole('button', { name: /Load Template Directory/ }), + ).toBeDisabled(); + }); + + it('should be able to continue to form preview', async () => { + await renderInTestApp( + + + , + ); + + await userEvent.click(screen.getByText('Edit Template Form')); + + expect(screen.getByLabelText('Load Existing Template')).toBeInTheDocument(); + }); +}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx new file mode 100644 index 0000000000..03e1619bc8 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -0,0 +1,107 @@ +/* + * Copyright 2022 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 React, { useState } from 'react'; +import { Content, Header, Page } from '@backstage/core-components'; +import { + TemplateDirectoryAccess, + WebFileSystemAccess, +} from '../../lib/filesystem'; +import { CustomFieldExplorer } from './CustomFieldExplorer'; +import { TemplateEditorIntro } from './TemplateEditorIntro'; +import { TemplateEditor } from './TemplateEditor'; +import { TemplateFormPreviewer } from './TemplateFormPreviewer'; +import { + NextFieldExtensionOptions, + type LayoutOptions, +} from '@backstage/plugin-scaffolder-react'; + +type Selection = + | { + type: 'local'; + directory: TemplateDirectoryAccess; + } + | { + type: 'form'; + } + | { + type: 'field-explorer'; + }; + +interface TemplateEditorPageProps { + defaultPreviewTemplate?: string; + customFieldExtensions?: NextFieldExtensionOptions[]; + layouts?: LayoutOptions[]; +} + +export function TemplateEditorPage(props: TemplateEditorPageProps) { + const [selection, setSelection] = useState(); + + let content: JSX.Element | null = null; + if (selection?.type === 'local') { + content = ( + setSelection(undefined)} + layouts={props.layouts} + /> + ); + } else if (selection?.type === 'form') { + content = ( + setSelection(undefined)} + layouts={props.layouts} + /> + ); + } else if (selection?.type === 'field-explorer') { + content = ( + setSelection(undefined)} + /> + ); + } else { + content = ( + + { + if (option === 'local') { + WebFileSystemAccess.requestDirectoryAccess() + .then(directory => setSelection({ type: 'local', directory })) + .catch(() => {}); + } else if (option === 'form') { + setSelection({ type: 'form' }); + } else if (option === 'field-explorer') { + setSelection({ type: 'field-explorer' }); + } + }} + /> + + ); + } + + return ( + +
+ {content} + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx new file mode 100644 index 0000000000..588b0cd4ba --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx @@ -0,0 +1,153 @@ +/* + * Copyright 2022 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 { StreamLanguage } from '@codemirror/language'; +import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; +import { showPanel } from '@codemirror/view'; +import { IconButton, makeStyles, Paper, Tooltip } from '@material-ui/core'; +import RefreshIcon from '@material-ui/icons/Refresh'; +import SaveIcon from '@material-ui/icons/Save'; +import { useKeyboardEvent } from '@react-hookz/web'; +import CodeMirror from '@uiw/react-codemirror'; +import React, { useMemo } from 'react'; +import { useDirectoryEditor } from './DirectoryEditorContext'; + +const useStyles = makeStyles(theme => ({ + container: { + position: 'relative', + width: '100%', + height: '100%', + }, + codeMirror: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + errorPanel: { + color: theme.palette.error.main, + lineHeight: 2, + margin: theme.spacing(0, 1), + }, + floatingButtons: { + position: 'absolute', + top: theme.spacing(1), + right: theme.spacing(3), + }, + floatingButton: { + padding: theme.spacing(1), + }, +})); + +/** A wrapper around CodeMirror with an error panel and extra actions available */ +export function TemplateEditorTextArea(props: { + content?: string; + onUpdate?: (content: string) => void; + errorText?: string; + onSave?: () => void; + onReload?: () => void; +}) { + const { errorText } = props; + const classes = useStyles(); + + const panelExtension = useMemo(() => { + if (!errorText) { + return showPanel.of(null); + } + + const dom = document.createElement('div'); + dom.classList.add(classes.errorPanel); + dom.textContent = errorText; + return showPanel.of(() => ({ dom, bottom: true })); + }, [classes, errorText]); + + useKeyboardEvent( + e => e.key === 's' && (e.ctrlKey || e.metaKey), + e => { + e.preventDefault(); + if (props.onSave) { + props.onSave(); + } + }, + ); + + return ( +
+ + {(props.onSave || props.onReload) && ( +
+ + {props.onSave && ( + + props.onSave?.()} + > + + + + )} + {props.onReload && ( + + props.onReload?.()} + > + + + + )} + +
+ )} +
+ ); +} + +/** A version of the TemplateEditorTextArea that is connected to the DirectoryEditor context */ +export function TemplateEditorDirectoryEditorTextArea(props: { + errorText?: string; +}) { + const directoryEditor = useDirectoryEditor(); + + const actions = directoryEditor.selectedFile?.dirty + ? { + onSave: () => directoryEditor.save(), + onReload: () => directoryEditor.reload(), + } + : { + onReload: () => directoryEditor.reload(), + }; + + return ( + directoryEditor.selectedFile?.updateContent(content)} + {...actions} + /> + ); +} + +TemplateEditorTextArea.DirectoryEditor = TemplateEditorDirectoryEditorTextArea; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx new file mode 100644 index 0000000000..c5f84a4b66 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -0,0 +1,219 @@ +/* + * Copyright 2022 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 { Entity } from '@backstage/catalog-model'; +import { alertApiRef, useApi } from '@backstage/core-plugin-api'; +import { + catalogApiRef, + humanizeEntityRef, +} from '@backstage/plugin-catalog-react'; +import { + FormControl, + IconButton, + InputLabel, + LinearProgress, + makeStyles, + MenuItem, + Select, +} from '@material-ui/core'; +import CloseIcon from '@material-ui/icons/Close'; +import React, { useCallback, useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; +import yaml from 'yaml'; +import { + NextFieldExtensionOptions, + type LayoutOptions, +} from '@backstage/plugin-scaffolder-react'; +import { TemplateEditorForm } from './TemplateEditorForm'; +import { TemplateEditorTextArea } from './TemplateEditorTextArea'; + +const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI +parameters: + - title: Fill in some steps + required: + - name + properties: + name: + title: Name + type: string + description: Unique name of the component + owner: + title: Owner + type: string + description: Owner of the component + ui:field: OwnerPicker + ui:options: + catalogFilter: + kind: Group + - title: Choose a location + required: + - repoUrl + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com +steps: + - id: fetch-base + name: Fetch Base + action: fetch:template + input: + url: ./template + values: + name: \${{parameters.name}} +`; + +type TemplateOption = { + label: string; + value: Entity; +}; + +const useStyles = makeStyles(theme => ({ + root: { + gridArea: 'pageContent', + display: 'grid', + gridTemplateAreas: ` + "controls controls" + "textArea preview" + `, + gridTemplateRows: 'auto 1fr', + gridTemplateColumns: '1fr 1fr', + }, + controls: { + gridArea: 'controls', + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + margin: theme.spacing(1), + }, + textArea: { + gridArea: 'textArea', + }, + preview: { + gridArea: 'preview', + }, +})); + +export const TemplateFormPreviewer = ({ + defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML, + customFieldExtensions = [], + onClose, + layouts = [], +}: { + defaultPreviewTemplate?: string; + customFieldExtensions?: NextFieldExtensionOptions[]; + onClose?: () => void; + layouts?: LayoutOptions[]; +}) => { + const classes = useStyles(); + const alertApi = useApi(alertApiRef); + const catalogApi = useApi(catalogApiRef); + const [selectedTemplate, setSelectedTemplate] = useState(''); + const [errorText, setErrorText] = useState(); + const [templateOptions, setTemplateOptions] = useState([]); + const [templateYaml, setTemplateYaml] = useState(defaultPreviewTemplate); + + const { loading } = useAsync( + () => + catalogApi + .getEntities({ + filter: { kind: 'template' }, + fields: [ + 'kind', + 'metadata.namespace', + 'metadata.name', + 'metadata.title', + 'spec.parameters', + 'spec.steps', + 'spec.output', + ], + }) + .then(({ items }) => + setTemplateOptions( + items.map(template => ({ + label: + template.metadata.title ?? + humanizeEntityRef(template, { defaultKind: 'template' }), + value: template, + })), + ), + ) + .catch(e => + alertApi.post({ + message: `Error loading exisiting templates: ${e.message}`, + severity: 'error', + }), + ), + [catalogApi], + ); + + const handleSelectChange = useCallback( + selected => { + setSelectedTemplate(selected); + setTemplateYaml(yaml.stringify(selected.spec)); + }, + [setTemplateYaml], + ); + + return ( + <> + {loading && } +
+
+ + + Load Existing Template + + + + + + + +
+
+ +
+
+ +
+
+ + ); +}; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/index.ts b/plugins/scaffolder/src/next/TemplateEditorPage/index.ts new file mode 100644 index 0000000000..7ec6bddb64 --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateEditorPage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 { TemplateEditorPage } from './TemplateEditorPage'; diff --git a/yarn.lock b/yarn.lock index 1621cdc5b1..24c2ea1f70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7589,6 +7589,7 @@ __metadata: "@rjsf/core": ^3.2.1 "@rjsf/material-ui": ^3.2.1 "@rjsf/utils": 5.1.0 + "@rjsf/validator-ajv8": 5.1.0 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 From a5213796886dd87616cd9e584021d2efaca3e0e8 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 14:41:26 +0100 Subject: [PATCH 107/417] chore: added changeset Signed-off-by: blam --- .changeset/honest-timers-pull.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/honest-timers-pull.md diff --git a/.changeset/honest-timers-pull.md b/.changeset/honest-timers-pull.md new file mode 100644 index 0000000000..d11d260a22 --- /dev/null +++ b/.changeset/honest-timers-pull.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-react': minor +'@backstage/plugin-scaffolder': minor +--- + +Migrating the `TemplateEditorPage` to work with the new components from `@backstage/plugin-scaffolder-react` From 73981f9407db1985536bac01da29b0e870a93548 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 15:42:47 +0100 Subject: [PATCH 108/417] chore: removed some unneeded code, just use the one that exists Signed-off-by: blam --- .../DirectoryEditorContext.tsx | 243 ------------------ .../TemplateEditorPage/DryRunContext.test.tsx | 44 ---- .../next/TemplateEditorPage/DryRunContext.tsx | 179 ------------- .../DryRunResults/DryRunResults.test.tsx | 118 --------- .../DryRunResults/DryRunResults.tsx | 91 ------- .../DryRunResults/DryRunResultsList.test.tsx | 95 ------- .../DryRunResults/DryRunResultsList.tsx | 83 ------ .../DryRunResults/DryRunResultsSplitView.tsx | 55 ---- .../DryRunResults/DryRunResultsView.test.tsx | 99 ------- .../DryRunResults/DryRunResultsView.tsx | 195 -------------- .../TemplateEditorPage/DryRunResults/index.ts | 17 -- .../TemplateEditorPage/TemplateEditor.tsx | 10 +- .../TemplateEditorBrowser.test.tsx | 55 ---- .../TemplateEditorBrowser.tsx | 100 ------- .../TemplateEditorPage/TemplateEditorForm.tsx | 5 +- .../TemplateEditorPage.test.tsx | 58 ----- .../TemplateEditorTextArea.tsx | 153 ----------- .../TemplateFormPreviewer.tsx | 2 +- 18 files changed, 8 insertions(+), 1594 deletions(-) delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx deleted file mode 100644 index 0edf390bfe..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2022 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 { ErrorPanel, Progress } from '@backstage/core-components'; -import { useAsync, useRerender } from '@react-hookz/web'; -import React, { createContext, ReactNode, useContext, useEffect } from 'react'; -import { - TemplateDirectoryAccess, - TemplateFileAccess, -} from '../../lib/filesystem'; - -const MAX_SIZE = 1024 * 1024; -const MAX_SIZE_MESSAGE = 'This file is too large to be displayed'; - -interface DirectoryEditorFile { - /** The path of the file relative to the root directory */ - path: string; - /** The staged content of the file */ - content: string; - /** Whether the staged content matches what is on disk */ - dirty: boolean; - - /** Update the staged content of the file without saving */ - updateContent(content: string): void; - /** Save the staged content of the file to disk */ - save(): Promise; - /** Reload the staged content of the file from disk */ - reload(): Promise; -} - -interface DirectoryEditor { - /** A list of all files in the edited directory */ - files: Array; - - /** The currently selected file */ - selectedFile: DirectoryEditorFile | undefined; - /** Switch the selected file */ - setSelectedFile(path: string | undefined): void; - - /** Save all files to disk */ - save(): Promise; - /** Reload all files from disk */ - reload(): Promise; - - subscribe(listener: () => void): () => void; -} - -class DirectoryEditorFileManager implements DirectoryEditorFile { - readonly #access: TemplateFileAccess; - readonly #signalUpdate: () => void; - - #content?: string; - #savedContent?: string; - - constructor(access: TemplateFileAccess, signalUpdate: () => void) { - this.#access = access; - this.#signalUpdate = signalUpdate; - } - - get path() { - return this.#access.path; - } - - get content() { - return this.#content ?? MAX_SIZE_MESSAGE; - } - - updateContent(content: string): void { - if (this.#content === undefined) { - return; - } - this.#content = content; - this.#signalUpdate(); - } - - get dirty() { - return this.#content !== this.#savedContent; - } - - async save(): Promise { - if (this.#content !== undefined) { - await this.#access.save(this.#content); - this.#savedContent = this.#content; - this.#signalUpdate(); - } - } - - async reload(): Promise { - const file = await this.#access.file(); - if (file.size > MAX_SIZE) { - if (this.#content !== undefined) { - this.#content = undefined; - this.#savedContent = undefined; - this.#signalUpdate(); - } - return; - } - - const content = await file.text(); - if (this.#content !== content) { - this.#content = content; - this.#savedContent = content; - this.#signalUpdate(); - } - } -} - -class DirectoryEditorManager implements DirectoryEditor { - readonly #access: TemplateDirectoryAccess; - readonly #listeners = new Set<() => void>(); - - #files: DirectoryEditorFile[] = []; - #selectedFile: DirectoryEditorFile | undefined; - - constructor(access: TemplateDirectoryAccess) { - this.#access = access; - } - - get files() { - return this.#files; - } - - get selectedFile() { - return this.#selectedFile; - } - - setSelectedFile = (path: string | undefined): void => { - const prev = this.#selectedFile; - const next = this.#files.find(file => file.path === path); - if (prev !== next) { - this.#selectedFile = next; - this.#signalUpdate(); - } - }; - - get dirty() { - return this.#files.some(file => file.dirty); - } - - async save(): Promise { - await Promise.all(this.#files.map(file => file.save())); - } - - async reload(): Promise { - const selectedPath = this.#selectedFile?.path; - - const files = await this.#access.listFiles(); - const fileManagers = await Promise.all( - files.map(async file => { - const manager = new DirectoryEditorFileManager( - file, - this.#signalUpdate, - ); - await manager.reload(); - return manager; - }), - ); - this.#files.length = 0; - this.#files.push(...fileManagers); - - this.setSelectedFile(selectedPath); - this.#signalUpdate(); - } - - subscribe(listener: () => void): () => void { - this.#listeners.add(listener); - return () => { - this.#listeners.delete(listener); - }; - } - - #signalUpdate = () => { - this.#listeners.forEach(listener => listener()); - }; -} - -const DirectoryEditorContext = createContext( - undefined, -); - -export function useDirectoryEditor(): DirectoryEditor { - const value = useContext(DirectoryEditorContext); - const rerender = useRerender(); - - useEffect(() => value?.subscribe(rerender), [value, rerender]); - - if (!value) { - throw new Error('must be used within a DirectoryEditorProvider'); - } - return value; -} - -interface DirectoryEditorProviderProps { - directory: TemplateDirectoryAccess; - children?: ReactNode; -} - -export function DirectoryEditorProvider(props: DirectoryEditorProviderProps) { - const { directory } = props; - - const [{ result, error }, { execute }] = useAsync( - async (dir: TemplateDirectoryAccess) => { - const manager = new DirectoryEditorManager(dir); - await manager.reload(); - - const firstYaml = manager.files.find(file => file.path.match(/\.ya?ml$/)); - if (firstYaml) { - manager.setSelectedFile(firstYaml.path); - } - - return manager; - }, - ); - - useEffect(() => { - execute(directory); - }, [execute, directory]); - - if (error) { - return ; - } else if (!result) { - return ; - } - - return ( - - {props.children} - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx deleted file mode 100644 index 36a62f1b8a..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2022 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 { base64EncodeContent } from './DryRunContext'; - -// eslint-disable-next-line no-restricted-imports -import { TextEncoder } from 'util'; - -window.TextEncoder = TextEncoder; - -describe('base64EncodeContent', () => { - it('encodes text files', () => { - expect(base64EncodeContent('abc')).toBe('YWJj'); - expect(base64EncodeContent('abc'.repeat(1000000))).toBe( - window.btoa(''), - ); - }); - - it('encodes binary files', () => { - expect(base64EncodeContent('\x00\x01\x02')).toBe('AAEC'); - expect(base64EncodeContent('😅')).toBe('8J+YhQ=='); - // Triggers chunking - expect(base64EncodeContent('😅'.repeat(18000))).toBe( - '8J+YhfCfmIXwn5iF8J+YhfCfmIXwn5iF'.repeat(3000), - ); - // Triggers size check - expect(base64EncodeContent('😅'.repeat(1000000))).toBe( - window.btoa(''), - ); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx deleted file mode 100644 index a617eebe1e..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2022 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 yaml from 'yaml'; -import { useApi } from '@backstage/core-plugin-api'; -import { JsonObject } from '@backstage/types'; -import React, { - createContext, - ReactNode, - useCallback, - useContext, - useMemo, - useRef, - useState, -} from 'react'; -import { - scaffolderApiRef, - ScaffolderDryRunResponse, -} from '@backstage/plugin-scaffolder-react'; - -const MAX_CONTENT_SIZE = 64 * 1024; -const CHUNK_SIZE = 32 * 1024; - -interface DryRunOptions { - templateContent: string; - values: JsonObject; - files: Array<{ path: string; content: string }>; -} - -interface DryRunResult extends ScaffolderDryRunResponse { - id: number; -} - -interface DryRun { - results: DryRunResult[]; - selectedResult: DryRunResult | undefined; - - selectResult(id: number): void; - deleteResult(id: number): void; - execute(options: DryRunOptions): Promise; -} - -const DryRunContext = createContext(undefined); - -interface DryRunProviderProps { - children: ReactNode; -} - -export function base64EncodeContent(content: string): string { - if (content.length > MAX_CONTENT_SIZE) { - return window.btoa(''); - } - - try { - return window.btoa(content); - } catch { - const decoder = new TextEncoder(); - const buffer = decoder.encode(content); - - const chunks = new Array(); - for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) { - chunks.push( - String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE)), - ); - } - return window.btoa(chunks.join('')); - } -} - -export function DryRunProvider(props: DryRunProviderProps) { - const scaffolderApi = useApi(scaffolderApiRef); - - const [state, setState] = useState< - Pick - >({ - results: [], - selectedResult: undefined, - }); - const idRef = useRef(1); - - const selectResult = useCallback((id: number) => { - setState(prevState => { - const result = prevState.results.find(r => r.id === id); - if (result === prevState.selectedResult) { - return prevState; - } - return { - results: prevState.results, - selectedResult: result, - }; - }); - }, []); - - const deleteResult = useCallback((id: number) => { - setState(prevState => { - const index = prevState.results.findIndex(r => r.id === id); - if (index === -1) { - return prevState; - } - const newResults = prevState.results.slice(); - const [deleted] = newResults.splice(index, 1); - return { - results: newResults, - selectedResult: - prevState.selectedResult?.id === deleted.id - ? newResults[0] - : prevState.selectedResult, - }; - }); - }, []); - - const execute = useCallback( - async (options: DryRunOptions) => { - if (!scaffolderApi.dryRun) { - throw new Error('Scaffolder API does not support dry-run'); - } - - const parsed = yaml.parse(options.templateContent); - - const response = await scaffolderApi.dryRun({ - template: parsed, - values: options.values, - secrets: {}, - directoryContents: options.files.map(file => ({ - path: file.path, - base64Content: base64EncodeContent(file.content), - })), - }); - - const result = { - ...response, - id: idRef.current++, - }; - - setState(prevState => ({ - results: [...prevState.results, result], - selectedResult: prevState.selectedResult ?? result, - })); - }, - [scaffolderApi], - ); - - const dryRun = useMemo( - () => ({ - ...state, - selectResult, - deleteResult, - execute, - }), - [state, selectResult, deleteResult, execute], - ); - - return ( - - {props.children} - - ); -} - -export function useDryRun(): DryRun { - const value = useContext(DryRunContext); - if (!value) { - throw new Error('must be used within a DryRunProvider'); - } - return value; -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx deleted file mode 100644 index 0267093ee6..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2022 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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { act, screen, waitFor } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { useEffect } from 'react'; -import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; -import { DryRunProvider, useDryRun } from '../DryRunContext'; -import { DryRunResults } from './DryRunResults'; - -function DryRunRemote({ - execute, - remove, -}: { - execute?: boolean; - remove?: boolean; -}) { - const dryRun = useDryRun(); - - useEffect(() => { - if (execute) { - dryRun.execute({ - templateContent: '', - values: {}, - files: [], - }); - } - if (remove) { - if (dryRun.selectedResult) { - dryRun.deleteResult(dryRun.selectedResult.id); - } - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [execute, remove]); - - return null; -} - -const mockScaffolderApi = { - dryRun: async () => ({ - directoryContents: [], - log: [], - output: {}, - steps: [], - }), -}; - -describe('DryRunResults', () => { - it('renders without exploding', async () => { - await renderInTestApp( - - - - - , - ); - expect(screen.getByText('Dry-run results')).toBeInTheDocument(); - }); - - it('expands when dry-run result is added and toggles on click, and disappears when results are gone', async () => { - const { rerender } = await renderInTestApp( - - - - - - , - ); - - expect(screen.getByText('Files')).not.toBeVisible(); - - await act(async () => { - rerender( - - - - - - , - ); - }); - - expect(screen.getByText('Files')).toBeVisible(); - - await userEvent.click(screen.getByText('Dry-run results')); - await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); - - await userEvent.click(screen.getByText('Dry-run results')); - expect(screen.getByText('Files')).toBeVisible(); - - await act(async () => { - rerender( - - - - - - , - ); - }); - - await waitFor(() => expect(screen.getByText('Files')).not.toBeVisible()); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx deleted file mode 100644 index ae9374438f..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2022 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 { BackstageTheme } from '@backstage/theme'; -import Accordion from '@material-ui/core/Accordion'; -import AccordionDetails from '@material-ui/core/AccordionDetails'; -import AccordionSummary from '@material-ui/core/AccordionSummary'; -import Divider from '@material-ui/core/Divider'; -import { makeStyles } from '@material-ui/core/styles'; -import Typography from '@material-ui/core/Typography'; -import ExpandMoreIcon from '@material-ui/icons/ExpandLess'; -import { usePrevious } from '@react-hookz/web'; -import React, { useEffect, useState } from 'react'; -import { useDryRun } from '../DryRunContext'; -import { DryRunResultsList } from './DryRunResultsList'; -import { DryRunResultsView } from './DryRunResultsView'; - -const useStyles = makeStyles((theme: BackstageTheme) => ({ - header: { - height: 48, - minHeight: 0, - '&.Mui-expanded': { - height: 48, - minHeight: 0, - }, - }, - content: { - display: 'grid', - background: theme.palette.background.default, - gridTemplateColumns: '180px auto 1fr', - gridTemplateRows: '1fr', - padding: 0, - height: 400, - }, -})); - -export function DryRunResults() { - const classes = useStyles(); - const dryRun = useDryRun(); - const [expanded, setExpanded] = useState(false); - const [hidden, setHidden] = useState(true); - - const resultsLength = dryRun.results.length; - const prevResultsLength = usePrevious(resultsLength); - useEffect(() => { - if (prevResultsLength === 0 && resultsLength === 1) { - setHidden(false); - setExpanded(true); - } else if (prevResultsLength === 1 && resultsLength === 0) { - setExpanded(false); - } - }, [prevResultsLength, resultsLength]); - - return ( - <> - - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx deleted file mode 100644 index 706f284db1..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2022 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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { act, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { useEffect } from 'react'; -import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; -import { DryRunProvider, useDryRun } from '../DryRunContext'; -import { DryRunResultsList } from './DryRunResultsList'; - -function DryRunRemote({ execute }: { execute?: number }) { - const dryRun = useDryRun(); - - useEffect(() => { - if (execute) { - dryRun.execute({ - templateContent: '', - values: {}, - files: [], - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [execute]); - - return null; -} - -const mockScaffolderApi = { - dryRun: async () => ({ - directoryContents: [], - log: [], - output: {}, - steps: [], - }), -}; - -describe('DryRunResultsList', () => { - it('renders without exploding', async () => { - const rendered = await renderInTestApp( - - - - - , - ); - expect(rendered.baseElement.querySelector('ul')).toBeEmptyDOMElement(); - }); - - it('adds new result items and deletes them', async () => { - const { rerender } = await renderInTestApp( - - - - - - , - ); - - expect(screen.getByText('Result 1')).toBeInTheDocument(); - expect(screen.queryByText('Result 2')).not.toBeInTheDocument(); - - await act(async () => { - rerender( - - - - - - , - ); - }); - - expect(screen.getByText('Result 1')).toBeInTheDocument(); - expect(screen.getByText('Result 2')).toBeInTheDocument(); - - await userEvent.click(screen.getAllByLabelText('delete')[0]); - - expect(screen.queryByText('Result 1')).not.toBeInTheDocument(); - expect(screen.getByText('Result 2')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx deleted file mode 100644 index 462c3b58fd..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2022 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 { BackstageTheme } from '@backstage/theme'; -import IconButton from '@material-ui/core/IconButton'; -import List from '@material-ui/core/List'; -import ListItem from '@material-ui/core/ListItem'; -import ListItemIcon from '@material-ui/core/ListItemIcon'; -import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; -import ListItemText from '@material-ui/core/ListItemText'; -import { makeStyles } from '@material-ui/core/styles'; -import CancelIcon from '@material-ui/icons/Cancel'; -import CheckIcon from '@material-ui/icons/Check'; -import DeleteIcon from '@material-ui/icons/Delete'; -import React from 'react'; -import { useDryRun } from '../DryRunContext'; - -const useStyles = makeStyles((theme: BackstageTheme) => ({ - root: { - overflowY: 'auto', - background: theme.palette.background.default, - }, - iconSuccess: { - minWidth: 0, - marginRight: theme.spacing(1), - color: theme.palette.status.ok, - }, - iconFailure: { - minWidth: 0, - marginRight: theme.spacing(1), - color: theme.palette.status.error, - }, -})); - -export function DryRunResultsList() { - const classes = useStyles(); - const dryRun = useDryRun(); - - return ( - - {dryRun.results.map(result => { - const failed = result.log.some(l => l.body.status === 'failed'); - return ( - dryRun.selectResult(result.id)} - > - - {failed ? : } - - - - dryRun.deleteResult(result.id)} - > - - - - - ); - })} - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx deleted file mode 100644 index b554a1c0c0..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022 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 { makeStyles } from '@material-ui/core/styles'; -import Divider from '@material-ui/core/Divider'; -import React, { Children, ReactNode } from 'react'; -import classNames from 'classnames'; - -const useStyles = makeStyles(theme => ({ - root: { - display: 'grid', - gridTemplateColumns: '280px auto 3fr', - gridTemplateRows: '1fr', - }, - child: { - overflowY: 'auto', - height: '100%', - minHeight: 0, - }, - firstChild: { - background: theme.palette.background.paper, - }, -})); - -export function DryRunResultsSplitView(props: { children: ReactNode }) { - const classes = useStyles(); - const childArray = Children.toArray(props.children); - - if (childArray.length !== 2) { - throw new Error('must have exactly 2 children'); - } - - return ( -
-
- {childArray[0]} -
- -
{childArray[1]}
-
- ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx deleted file mode 100644 index c2d8d3a2a4..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2022 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 { entityRouteRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React, { ReactNode, useEffect } from 'react'; -import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; -import { DryRunProvider, useDryRun } from '../DryRunContext'; -import { DryRunResultsView } from './DryRunResultsView'; - -// The inside needs mocking to render in jsdom -jest.mock('react-virtualized-auto-sizer', () => ({ - __esModule: true, - default: (props: { - children: (size: { width: number; height: number }) => ReactNode; - }) => <>{props.children({ width: 400, height: 200 })}, -})); - -function DryRunRemote() { - const dryRun = useDryRun(); - - useEffect(() => { - dryRun.execute({ - templateContent: '', - values: {}, - files: [], - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return null; -} - -describe('DryRunResultsView', () => { - it('renders a result', async () => { - await renderInTestApp( - ({ - directoryContents: [ - { - path: 'foo.txt', - base64Content: window.btoa('Foo Content'), - executable: false, - }, - ], - log: [{ body: { message: 'Foo Message', stepId: 'foo' } }], - output: { - links: [{ title: 'Foo Link', url: 'http://example.com' }], - }, - steps: [{ id: 'foo', action: 'foo', name: 'Foo' }], - }), - }, - ], - ]} - > - - - - - , - { - mountedRoutes: { - '/catalog/:kind/:namespace/:name': entityRouteRef, - }, - }, - ); - - expect(screen.getByText('foo.txt')).toBeInTheDocument(); - expect(screen.getByText('Foo Content')).toBeInTheDocument(); - - expect(screen.queryByText('Foo Message')).not.toBeInTheDocument(); - expect(screen.queryByText('Foo Link')).not.toBeInTheDocument(); - - await userEvent.click(screen.getByText('Log')); - expect(screen.getByText('Foo Message')).toBeInTheDocument(); - - await userEvent.click(screen.getByText('Output')); - expect(screen.getByText('Foo Link')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx deleted file mode 100644 index 852ec05a82..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2022 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 { LogViewer } from '@backstage/core-components'; -import { StreamLanguage } from '@codemirror/language'; -import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; -import Box from '@material-ui/core/Box'; -import Divider from '@material-ui/core/Divider'; -import { makeStyles } from '@material-ui/core/styles'; -import Tab from '@material-ui/core/Tab'; -import Tabs from '@material-ui/core/Tabs'; -import CodeMirror from '@uiw/react-codemirror'; -import React, { useEffect, useMemo, useState } from 'react'; -import { FileBrowser } from '../../../components/FileBrowser'; -import { TaskStatusStepper } from '../../../components/TaskPage/TaskPage'; -import { TaskPageLinks } from '../../../components/TaskPage/TaskPageLinks'; -import { useDryRun } from '../DryRunContext'; -import { DryRunResultsSplitView } from './DryRunResultsSplitView'; - -const useStyles = makeStyles({ - root: { - display: 'flex', - flexFlow: 'column nowrap', - }, - contentWrapper: { - flex: 1, - position: 'relative', - }, - content: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - - display: 'flex', - '& > *': { - flex: 1, - }, - }, - codeMirror: { - height: '100%', - overflowY: 'auto', - }, -}); - -function FilesContent() { - const classes = useStyles(); - const { selectedResult } = useDryRun(); - const [selectedPath, setSelectedPath] = useState(''); - const selectedFile = selectedResult?.directoryContents.find( - f => f.path === selectedPath, - ); - - useEffect(() => { - if (selectedResult) { - const [firstFile] = selectedResult.directoryContents; - if (firstFile) { - setSelectedPath(firstFile.path); - } else { - setSelectedPath(''); - } - } - return undefined; - }, [selectedResult]); - - if (!selectedResult) { - return null; - } - return ( - - file.path)} - /> - - - ); -} -function LogContent() { - const { selectedResult } = useDryRun(); - const [currentStepId, setUserSelectedStepId] = useState(); - - const steps = useMemo(() => { - if (!selectedResult) { - return []; - } - return ( - selectedResult.steps.map(step => { - const stepLog = selectedResult.log.filter( - l => l.body.stepId === step.id, - ); - return { - id: step.id, - name: step.name, - logString: stepLog.map(l => l.body.message).join('\n'), - status: stepLog[stepLog.length - 1]?.body.status ?? 'completed', - }; - }) ?? [] - ); - }, [selectedResult]); - - if (!selectedResult) { - return null; - } - - const selectedStep = steps.find(s => s.id === currentStepId) ?? steps[0]; - - return ( - - - - - ); -} - -function OutputContent() { - const classes = useStyles(); - const { selectedResult } = useDryRun(); - - if (!selectedResult) { - return null; - } - - return ( - - - {selectedResult.output?.links?.length && ( - - )} - - - - ); -} - -export function DryRunResultsView() { - const classes = useStyles(); - const [selectedTab, setSelectedTab] = useState<'files' | 'log' | 'output'>( - 'files', - ); - - return ( -
- setSelectedTab(v)}> - - - - - - -
-
- {selectedTab === 'files' && } - {selectedTab === 'log' && } - {selectedTab === 'output' && } -
-
-
- ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts deleted file mode 100644 index af8ef5214f..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2022 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 { DryRunResults } from './DryRunResults'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx index c5556c3b06..4cdd383f83 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx @@ -20,12 +20,12 @@ import type { NextFieldExtensionOptions, } from '@backstage/plugin-scaffolder-react'; import { TemplateDirectoryAccess } from '../../lib/filesystem'; -import { DirectoryEditorProvider } from './DirectoryEditorContext'; -import { DryRunProvider } from './DryRunContext'; -import { DryRunResults } from './DryRunResults'; -import { TemplateEditorBrowser } from './TemplateEditorBrowser'; +import { DirectoryEditorProvider } from '../../components/TemplateEditorPage/DirectoryEditorContext'; +import { DryRunProvider } from '../../components/TemplateEditorPage/DryRunContext'; +import { DryRunResults } from '../../components/TemplateEditorPage/DryRunResults'; +import { TemplateEditorBrowser } from '../../components/TemplateEditorPage/TemplateEditorBrowser'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; +import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; const useStyles = makeStyles({ // Reset and fix sizing to make sure scrolling behaves correctly diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx deleted file mode 100644 index cec311a5cd..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2022 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 { renderInTestApp } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { MockFileSystemAccess } from '../../lib/filesystem/MockFileSystemAccess'; -import { DirectoryEditorProvider } from './DirectoryEditorContext'; -import { TemplateEditorBrowser } from './TemplateEditorBrowser'; - -Blob.prototype.text = async function text() { - return new Promise(resolve => { - const reader = new FileReader(); - reader.onload = () => resolve(reader.result as string); - reader.readAsText(this); - }); -}; - -describe('TemplateEditorBrowser', () => { - it('should render files and expand dirs without exploding', async () => { - await renderInTestApp( - - - , - ); - - await expect(screen.findByText('foo.txt')).resolves.toBeInTheDocument(); - expect(screen.getByText('dir')).toBeInTheDocument(); - expect(screen.queryByText('bar.txt')).not.toBeInTheDocument(); - expect(screen.queryByText('baz.txt')).not.toBeInTheDocument(); - - await userEvent.click(screen.getByText('dir')); - expect(screen.getByText('bar.txt')).toBeInTheDocument(); - expect(screen.getByText('baz.txt')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx deleted file mode 100644 index a668aa1868..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2022 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 { Divider, IconButton, makeStyles, Tooltip } from '@material-ui/core'; -import CloseIcon from '@material-ui/icons/Close'; -import RefreshIcon from '@material-ui/icons/Refresh'; -import SaveIcon from '@material-ui/icons/Save'; -import React from 'react'; -import { FileBrowser } from '../../components/FileBrowser'; - -import { useDirectoryEditor } from './DirectoryEditorContext'; - -const useStyles = makeStyles(theme => ({ - button: { - padding: theme.spacing(1), - }, - buttons: { - display: 'flex', - flexFlow: 'row nowrap', - alignItems: 'center', - justifyContent: 'flex-start', - }, - buttonsGap: { - flex: '1 1 auto', - }, - buttonsDivider: { - marginBottom: theme.spacing(1), - }, -})); - -/** The local file browser for the template editor */ -export function TemplateEditorBrowser(props: { onClose?: () => void }) { - const classes = useStyles(); - const directoryEditor = useDirectoryEditor(); - const changedFiles = directoryEditor.files.filter(file => file.dirty); - - const handleClose = () => { - if (!props.onClose) { - return; - } - if (changedFiles.length > 0) { - // eslint-disable-next-line no-alert - const accepted = window.confirm( - 'Are you sure? Unsaved changes will be lost', - ); - if (!accepted) { - return; - } - } - props.onClose(); - }; - - return ( - <> -
- - !file.dirty)} - onClick={() => directoryEditor.save()} - > - - - - - directoryEditor.reload()} - > - - - -
- - - - - -
- - file.path)} - /> - - ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx index 0ac604c75d..5dc841cf20 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx @@ -25,9 +25,8 @@ import { Stepper, TemplateParameterSchema, } from '@backstage/plugin-scaffolder-react'; - -import { useDirectoryEditor } from './DirectoryEditorContext'; -import { useDryRun } from './DryRunContext'; +import { useDryRun } from '../../components/TemplateEditorPage/DryRunContext'; +import { useDirectoryEditor } from '../../components/TemplateEditorPage/DirectoryEditorContext'; const useStyles = makeStyles({ containerWrapper: { diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx deleted file mode 100644 index bf9cd8c464..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2022 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 { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { TemplateEditorPage } from './TemplateEditorPage'; - -describe('TemplateEditorPage', () => { - it('renders without exploding', async () => { - await renderInTestApp(); - - expect(screen.getByText('Load Template Directory')).toBeInTheDocument(); - expect(screen.getByText('Edit Template Form')).toBeInTheDocument(); - }); - - it('template directory loading should not be supported in Jest', async () => { - await renderInTestApp(); - - expect( - screen.getByRole('button', { name: /Load Template Directory/ }), - ).toBeDisabled(); - }); - - it('should be able to continue to form preview', async () => { - await renderInTestApp( - - - , - ); - - await userEvent.click(screen.getByText('Edit Template Form')); - - expect(screen.getByLabelText('Load Existing Template')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx deleted file mode 100644 index 588b0cd4ba..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2022 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 { StreamLanguage } from '@codemirror/language'; -import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; -import { showPanel } from '@codemirror/view'; -import { IconButton, makeStyles, Paper, Tooltip } from '@material-ui/core'; -import RefreshIcon from '@material-ui/icons/Refresh'; -import SaveIcon from '@material-ui/icons/Save'; -import { useKeyboardEvent } from '@react-hookz/web'; -import CodeMirror from '@uiw/react-codemirror'; -import React, { useMemo } from 'react'; -import { useDirectoryEditor } from './DirectoryEditorContext'; - -const useStyles = makeStyles(theme => ({ - container: { - position: 'relative', - width: '100%', - height: '100%', - }, - codeMirror: { - position: 'absolute', - top: 0, - bottom: 0, - left: 0, - right: 0, - }, - errorPanel: { - color: theme.palette.error.main, - lineHeight: 2, - margin: theme.spacing(0, 1), - }, - floatingButtons: { - position: 'absolute', - top: theme.spacing(1), - right: theme.spacing(3), - }, - floatingButton: { - padding: theme.spacing(1), - }, -})); - -/** A wrapper around CodeMirror with an error panel and extra actions available */ -export function TemplateEditorTextArea(props: { - content?: string; - onUpdate?: (content: string) => void; - errorText?: string; - onSave?: () => void; - onReload?: () => void; -}) { - const { errorText } = props; - const classes = useStyles(); - - const panelExtension = useMemo(() => { - if (!errorText) { - return showPanel.of(null); - } - - const dom = document.createElement('div'); - dom.classList.add(classes.errorPanel); - dom.textContent = errorText; - return showPanel.of(() => ({ dom, bottom: true })); - }, [classes, errorText]); - - useKeyboardEvent( - e => e.key === 's' && (e.ctrlKey || e.metaKey), - e => { - e.preventDefault(); - if (props.onSave) { - props.onSave(); - } - }, - ); - - return ( -
- - {(props.onSave || props.onReload) && ( -
- - {props.onSave && ( - - props.onSave?.()} - > - - - - )} - {props.onReload && ( - - props.onReload?.()} - > - - - - )} - -
- )} -
- ); -} - -/** A version of the TemplateEditorTextArea that is connected to the DirectoryEditor context */ -export function TemplateEditorDirectoryEditorTextArea(props: { - errorText?: string; -}) { - const directoryEditor = useDirectoryEditor(); - - const actions = directoryEditor.selectedFile?.dirty - ? { - onSave: () => directoryEditor.save(), - onReload: () => directoryEditor.reload(), - } - : { - onReload: () => directoryEditor.reload(), - }; - - return ( - directoryEditor.selectedFile?.updateContent(content)} - {...actions} - /> - ); -} - -TemplateEditorTextArea.DirectoryEditor = TemplateEditorDirectoryEditorTextArea; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx index c5f84a4b66..1476cda2d0 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -37,7 +37,7 @@ import { type LayoutOptions, } from '@backstage/plugin-scaffolder-react'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; +import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI parameters: From e9a8ce97d0f53a6b52294e5e8b280e5419d366c6 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 15:45:30 +0100 Subject: [PATCH 109/417] chore: remove some more uneeded code Signed-off-by: blam --- .../TemplateEditorIntro.tsx | 144 ------------------ .../TemplateEditorPage/TemplateEditorPage.tsx | 2 +- 2 files changed, 1 insertion(+), 145 deletions(-) delete mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx deleted file mode 100644 index 61e6c46964..0000000000 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2022 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 React from 'react'; -import Card from '@material-ui/core/Card'; -import CardActionArea from '@material-ui/core/CardActionArea'; -import CardContent from '@material-ui/core/CardContent'; -import Tooltip from '@material-ui/core/Tooltip'; -import Typography from '@material-ui/core/Typography'; -import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined'; -import { makeStyles } from '@material-ui/core/styles'; -import { WebFileSystemAccess } from '../../lib/filesystem'; - -const useStyles = makeStyles(theme => ({ - introText: { - textAlign: 'center', - marginTop: theme.spacing(2), - }, - card: { - position: 'relative', - maxWidth: 340, - marginTop: theme.spacing(4), - margin: theme.spacing(0, 2), - }, - infoIcon: { - position: 'absolute', - top: theme.spacing(1), - right: theme.spacing(1), - }, -})); - -interface EditorIntroProps { - style?: JSX.IntrinsicElements['div']['style']; - onSelect?: (option: 'local' | 'form' | 'field-explorer') => void; -} - -export function TemplateEditorIntro(props: EditorIntroProps) { - const classes = useStyles(); - const supportsLoad = WebFileSystemAccess.isSupported(); - - const cardLoadLocal = ( - - props.onSelect?.('local')} - > - - - Load Template Directory - - - Load a local template directory, allowing you to both edit and try - executing your own template. - - - - {!supportsLoad && ( -
- - - -
- )} -
- ); - - const cardFormEditor = ( - - props.onSelect?.('form')}> - - - Edit Template Form - - - Preview and edit a template form, either using a sample template or - by loading a template from the catalog. - - - - - ); - - const cardFieldExplorer = ( - - props.onSelect?.('field-explorer')}> - - - Custom Field Explorer - - - View and play around with available installed custom field - extensions. - - - - - ); - - return ( -
- - Get started by choosing one of the options below - -
- {supportsLoad && cardLoadLocal} - {cardFormEditor} - {!supportsLoad && cardLoadLocal} - {cardFieldExplorer} -
-
- ); -} diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx index 03e1619bc8..92387fd69d 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -20,13 +20,13 @@ import { WebFileSystemAccess, } from '../../lib/filesystem'; import { CustomFieldExplorer } from './CustomFieldExplorer'; -import { TemplateEditorIntro } from './TemplateEditorIntro'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; import { NextFieldExtensionOptions, type LayoutOptions, } from '@backstage/plugin-scaffolder-react'; +import { TemplateEditorIntro } from '../../components/TemplateEditorPage/TemplateEditorIntro'; type Selection = | { From 381cf607c6170911d35e7c713a6c7432f6142930 Mon Sep 17 00:00:00 2001 From: Jim Shingler Date: Fri, 10 Feb 2023 20:48:14 -0500 Subject: [PATCH 110/417] Format Section Title for Other Signed-off-by: Jim Shingler --- docs/features/software-catalog/system-model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index 16ad48abcf..ebbec1729b 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -120,7 +120,7 @@ product or use-case, share the same entity types in their APIs, and integrate well with each other. Other domains could be “Content Ingestion”, “Ads” or “Search”. -##Other +## Other ### Location From 72a33126892cdaaf79e058d12e0b705976d40da3 Mon Sep 17 00:00:00 2001 From: Jim Shingler Date: Fri, 10 Feb 2023 20:56:27 -0500 Subject: [PATCH 111/417] Fixing Documentation of GitLab Org Data Spell out PAT and fix time and resourcs Signed-off-by: Jim Shingler --- docs/integrations/gitlab/org.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/gitlab/org.md b/docs/integrations/gitlab/org.md index 100b2c09fd..2ab72b4bd6 100644 --- a/docs/integrations/gitlab/org.md +++ b/docs/integrations/gitlab/org.md @@ -20,9 +20,9 @@ integrations: ``` This will query all users and groups from your gitlab installation. Depending on the size -of the Gitlab Instance, this can take some time our resources. +of the Gitlab Instance, this can take some time and resources. -The token that is used for the Organization Integration, has to be an Admin PAT. +The token that is used for the Organization Integration, has to be an Admin Personal Access Token (PAT). ```yaml catalog: From aece6c57d24b2f24daba70b122f02d6def41563c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 11 Feb 2023 10:54:25 +0100 Subject: [PATCH 112/417] catalog-model: improve location reference validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw --- .changeset/purple-panthers-know.md | 5 +++++ .../catalog-model/src/location/helpers.test.ts | 9 +++++++++ packages/catalog-model/src/location/helpers.ts | 17 +++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 .changeset/purple-panthers-know.md diff --git a/.changeset/purple-panthers-know.md b/.changeset/purple-panthers-know.md new file mode 100644 index 0000000000..c53c6d8890 --- /dev/null +++ b/.changeset/purple-panthers-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-model': patch +--- + +Add additional validation for location references. diff --git a/packages/catalog-model/src/location/helpers.test.ts b/packages/catalog-model/src/location/helpers.test.ts index 91a2137611..28267dcf37 100644 --- a/packages/catalog-model/src/location/helpers.test.ts +++ b/packages/catalog-model/src/location/helpers.test.ts @@ -50,6 +50,9 @@ describe('parseLocationRef', () => { expect(() => parseLocationRef('https://bleh')).toThrow( "Invalid location ref 'https://bleh', please prefix it with 'url:', e.g. 'url:https://bleh'", ); + expect(() => parseLocationRef('url:javascript:alert()')).toThrow( + "Invalid location ref 'url:javascript:alert()', target is a javascript: URL", + ); }); }); @@ -70,6 +73,12 @@ describe('stringifyLocationRef', () => { expect(() => stringifyLocationRef({ type: 'hello', target: '' })).toThrow( 'Unable to stringify location ref, empty target', ); + expect(() => + // eslint-disable-next-line no-script-url + stringifyLocationRef({ type: 'url', target: 'javascript:alert()' }), + ).toThrow( + "Invalid location ref 'url:javascript:alert()', target is a javascript: URL", + ); }); }); diff --git a/packages/catalog-model/src/location/helpers.ts b/packages/catalog-model/src/location/helpers.ts index 6f9800c5a2..a2f4d84f6f 100644 --- a/packages/catalog-model/src/location/helpers.ts +++ b/packages/catalog-model/src/location/helpers.ts @@ -17,6 +17,11 @@ import { Entity, stringifyEntityRef } from '../entity'; import { ANNOTATION_LOCATION, ANNOTATION_SOURCE_LOCATION } from './annotation'; +// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js +const scriptProtocolPattern = + // eslint-disable-next-line no-control-regex + /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; + /** * Parses a string form location reference. * @@ -56,6 +61,12 @@ export function parseLocationRef(ref: string): { ); } + if (scriptProtocolPattern.test(target)) { + throw new TypeError( + `Invalid location ref '${ref}', target is a javascript: URL`, + ); + } + return { type, target }; } @@ -78,6 +89,12 @@ export function stringifyLocationRef(ref: { throw new TypeError(`Unable to stringify location ref, empty target`); } + if (scriptProtocolPattern.test(target)) { + throw new TypeError( + `Invalid location ref '${type}:${target}', target is a javascript: URL`, + ); + } + return `${type}:${target}`; } From 071354eb7deecdb9bd15c9df379e6067cec37436 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 11 Feb 2023 11:11:16 +0100 Subject: [PATCH 113/417] catalog-backend: add additional validation in stitching step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw --- .changeset/big-bags-glow.md | 5 + .../catalog-backend/src/integration.test.ts | 127 ++++++++++++++---- .../catalog-backend/src/stitching/Stitcher.ts | 15 +++ 3 files changed, 121 insertions(+), 26 deletions(-) create mode 100644 .changeset/big-bags-glow.md diff --git a/.changeset/big-bags-glow.md b/.changeset/big-bags-glow.md new file mode 100644 index 0000000000..eb606838fd --- /dev/null +++ b/.changeset/big-bags-glow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Add additional validation as security precations for output entities. diff --git a/plugins/catalog-backend/src/integration.test.ts b/plugins/catalog-backend/src/integration.test.ts index 4ba046834b..f0f916a78d 100644 --- a/plugins/catalog-backend/src/integration.test.ts +++ b/plugins/catalog-backend/src/integration.test.ts @@ -52,9 +52,14 @@ import { } from '@backstage/plugin-catalog-node'; import { RefreshStateItem } from './database/types'; import { DefaultProviderDatabase } from './database/DefaultProviderDatabase'; +import { InputError } from '@backstage/errors'; const voidLogger = getVoidLogger(); +type ProgressTrackerWithErrorReports = ProgressTracker & { + reportError(unprocessedEntity: Entity, errors: Error[]): void; +}; + class TestProvider implements EntityProvider { #connection?: EntityProviderConnection; @@ -74,10 +79,10 @@ class TestProvider implements EntityProvider { } } -class ProxyProgressTracker implements ProgressTracker { - #inner: ProgressTracker; +class ProxyProgressTracker implements ProgressTrackerWithErrorReports { + #inner: ProgressTrackerWithErrorReports; - constructor(inner: ProgressTracker) { + constructor(inner: ProgressTrackerWithErrorReports) { this.#inner = inner; } @@ -85,12 +90,16 @@ class ProxyProgressTracker implements ProgressTracker { return this.#inner.processStart(item, voidLogger); } - setTracker(tracker: ProgressTracker) { + setTracker(tracker: ProgressTrackerWithErrorReports) { this.#inner = tracker; } + + reportError(unprocessedEntity: Entity, errors: Error[]): void { + this.#inner.reportError(unprocessedEntity, errors); + } } -class NoopProgressTracker implements ProgressTracker { +class NoopProgressTracker implements ProgressTrackerWithErrorReports { static emptyTracking = { markFailed() {}, markProcessorsCompleted() {}, @@ -102,18 +111,20 @@ class NoopProgressTracker implements ProgressTracker { processStart() { return NoopProgressTracker.emptyTracking; } + + reportError() {} } -class WaitingProgressTracker implements ProgressTracker { - #resolve: (errors: Record) => void; - #promise: Promise>; +class WaitingProgressTracker implements ProgressTrackerWithErrorReports { + #resolve: (errors: Record) => void; + #promise: Promise>; #counts = new Map(); - #errors = new Map(); + #errors = new Map(); #inFlight = new Array>(); constructor(private readonly entityRefs?: Set) { - let resolve: (errors: Record) => void; - this.#promise = new Promise>(_resolve => { + let resolve: (errors: Record) => void; + this.#promise = new Promise>(_resolve => { resolve = _resolve; }); this.#resolve = resolve!; @@ -143,7 +154,7 @@ class WaitingProgressTracker implements ProgressTracker { }; return { markFailed: (error: Error) => { - this.#errors.set(item.entityRef, error); + this.#errors.set(item.entityRef, [error]); onDone(); resolve(); }, @@ -154,7 +165,6 @@ class WaitingProgressTracker implements ProgressTracker { resolve(); }, markSuccessfulWithErrors: () => { - this.#errors.delete(item.entityRef); onDone(); resolve(); }, @@ -165,7 +175,11 @@ class WaitingProgressTracker implements ProgressTracker { }; } - async wait(): Promise> { + reportError(unprocessedEntity: Entity, errors: Error[]): void { + this.#errors.set(stringifyEntityRef(unprocessedEntity), errors); + } + + async wait(): Promise> { return this.#promise; } @@ -191,10 +205,6 @@ class TestHarness { location: LocationSpec, emit: CatalogProcessorEmit, ): Promise; - onProcessingError?(event: { - unprocessedEntity: Entity; - errors: Error[]; - }): void; }) { const config = new ConfigReader( options?.config ?? { @@ -271,13 +281,7 @@ class TestHarness { () => createHash('sha1'), 50, event => { - if (options?.onProcessingError) { - options.onProcessingError(event); - } else { - throw new Error( - `Catalog processing error, ${event.errors.join(', ')}`, - ); - } + proxyProgressTracker.reportError(event.unprocessedEntity, event.errors); }, proxyProgressTracker, ); @@ -388,7 +392,13 @@ describe('Catalog Backend Integration', () => { triggerError = true; - await expect(harness.process()).resolves.toEqual({}); + await expect(harness.process()).resolves.toEqual({ + 'component:default/test': [ + new InputError( + 'Processor Object threw an error while preprocessing; caused by Error: NOPE', + ), + ], + }); await expect(harness.getOutputEntities()).resolves.toEqual({ 'component:default/test': { @@ -685,4 +695,69 @@ describe('Catalog Backend Integration', () => { .annotations!['backstage.io/orphan'], ).toBeUndefined(); }); + + it('should reject insecure URLs', async () => { + const harness = await TestHarness.create(); + + await harness.setInputEntities([ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test', + annotations: { + 'backstage.io/managed-by-location': 'url:.', + 'backstage.io/managed-by-origin-location': 'url:.', + 'backstage.io/view-url': ' javascript:bad()', + 'backstage.io/edit-url': ' javascript:alert()', + }, + }, + }, + ]); + + await expect(harness.process()).resolves.toEqual({}); + + await expect(harness.getOutputEntities()).resolves.toEqual({ + 'component:default/test': { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: expect.objectContaining({ + name: 'test', + annotations: expect.objectContaining({ + 'backstage.io/view-url': + 'https://backstage.io/annotation-rejected-for-security-reasons', + 'backstage.io/edit-url': + 'https://backstage.io/annotation-rejected-for-security-reasons', + }), + }), + relations: [], + }, + }); + }); + + it('should reject insecure location URLs', async () => { + const harness = await TestHarness.create(); + + await harness.setInputEntities([ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test', + annotations: { + 'backstage.io/managed-by-location': 'url:javascript:bad()', + 'backstage.io/managed-by-origin-location': 'url:javascript:alert()', + }, + }, + }, + ]); + + await expect(harness.process()).resolves.toEqual({ + 'component:default/test': [ + new TypeError( + "Invalid location ref 'url:javascript:bad()', target is a javascript: URL", + ), + ], + }); + }); }); diff --git a/plugins/catalog-backend/src/stitching/Stitcher.ts b/plugins/catalog-backend/src/stitching/Stitcher.ts index 4742c81933..bdf9f8791a 100644 --- a/plugins/catalog-backend/src/stitching/Stitcher.ts +++ b/plugins/catalog-backend/src/stitching/Stitcher.ts @@ -17,6 +17,8 @@ import { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from '@backstage/catalog-client'; import { AlphaEntity, + ANNOTATION_EDIT_URL, + ANNOTATION_VIEW_URL, EntityRelation, EntityStatusItem, } from '@backstage/catalog-model'; @@ -32,6 +34,11 @@ import { import { buildEntitySearch } from './buildEntitySearch'; import { BATCH_SIZE, generateStableHash } from './util'; +// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js +const scriptProtocolPattern = + // eslint-disable-next-line no-control-regex + /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; + /** * Performs the act of stitching - to take all of the various outputs from the * ingestion process, and stitching them together into the final entity JSON @@ -166,6 +173,14 @@ export class Stitcher { })); } } + // We opt to do this check here as we otherwise can't guarantee that it will be run after all processors + for (const annotation of [ANNOTATION_VIEW_URL, ANNOTATION_EDIT_URL]) { + const value = entity.metadata.annotations?.[annotation]; + if (typeof value === 'string' && scriptProtocolPattern.test(value)) { + entity.metadata.annotations![annotation] = + 'https://backstage.io/annotation-rejected-for-security-reasons'; + } + } // TODO: entityRef is lower case and should be uppercase in the final // result From 9fc1e58a5d0d9d5c311a1984740f21471e1a5a7c Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Sat, 11 Feb 2023 09:58:08 -0500 Subject: [PATCH 114/417] chore: Fix install instructions Signed-off-by: Adam Harvey --- plugins/explore-backend/README.md | 11 +++++------ plugins/explore/README.md | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/explore-backend/README.md b/plugins/explore-backend/README.md index 3edf48249a..86f60ae226 100644 --- a/plugins/explore-backend/README.md +++ b/plugins/explore-backend/README.md @@ -76,10 +76,9 @@ To index explore tools you will need to register the search collator in the ```diff +import { ToolDocumentCollatorFactory } from '@backstage/plugin-explore-backend'; -async function createSearchEngine( - env: PluginEnvironment, -): Promise { - ... +... + ++ // collator gathers entities from explore. + indexBuilder.addCollator({ + schedule, + factory: ToolDocumentCollatorFactory.fromConfig(env.config, { @@ -87,8 +86,8 @@ async function createSearchEngine( + logger: env.logger, + }), + }); - ... -} + +... ``` ### Wire up the Frontend diff --git a/plugins/explore/README.md b/plugins/explore/README.md index 2388d97ac1..0bb7258ae6 100644 --- a/plugins/explore/README.md +++ b/plugins/explore/README.md @@ -30,7 +30,7 @@ any path for the route, but we recommend the following: ```diff // packages/app/src/App.tsx -+ import { ExplorePage, explorePlugin } from '@backstage/plugin-explore'; ++ import { ExplorePage } from '@backstage/plugin-explore'; ... From 75cfee5688850b432d79a112ea90bdee3c6b0450 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 19 Nov 2022 16:43:29 -0600 Subject: [PATCH 115/417] Added linguist frontend, backend, and common plugins Signed-off-by: Andre Wanlin Removed refresh and permissions Signed-off-by: Andre Wanlin Small database refactor and improved naming Signed-off-by: Andre Wanlin Refactor stringifyEntityRef usage Signed-off-by: Andre Wanlin Fixed up yarn.lock Signed-off-by: Andre Wanlin --- .changeset/serious-horses-juggle.md | 7 + packages/app/package.json | 2 + .../app/src/components/catalog/EntityPage.tsx | 12 ++ packages/backend/package.json | 1 + packages/backend/src/index.ts | 3 + packages/backend/src/plugins/linguist.ts | 40 ++++ .../components/artist-lookup-component.yaml | 2 + plugins/linguist-backend/.eslintrc.js | 1 + plugins/linguist-backend/README.md | 94 ++++++++++ plugins/linguist-backend/api-report.md | 86 +++++++++ plugins/linguist-backend/config.d.ts | 27 +++ .../migrations/20221115_init.js | 67 +++++++ plugins/linguist-backend/package.json | 57 ++++++ .../src/api/LinguistBackendApi.ts | 173 ++++++++++++++++++ plugins/linguist-backend/src/api/index.ts | 17 ++ .../src/db/LinguistBackendDatabase.ts | 103 +++++++++++ plugins/linguist-backend/src/db/index.ts | 18 ++ plugins/linguist-backend/src/index.ts | 20 ++ plugins/linguist-backend/src/run.ts | 33 ++++ .../src/service/router.test.ts | 83 +++++++++ .../linguist-backend/src/service/router.ts | 108 +++++++++++ .../src/service/standaloneServer.ts | 76 ++++++++ plugins/linguist-backend/src/setupTests.ts | 17 ++ plugins/linguist-common/.eslintrc.js | 1 + plugins/linguist-common/README.md | 3 + plugins/linguist-common/api-report.md | 50 +++++ plugins/linguist-common/package.json | 35 ++++ plugins/linguist-common/src/constants.ts | 18 ++ plugins/linguist-common/src/index.ts | 18 ++ plugins/linguist-common/src/setupTests.ts | 16 ++ plugins/linguist-common/src/types.ts | 54 ++++++ plugins/linguist/.eslintrc.js | 1 + plugins/linguist/README.md | 88 +++++++++ plugins/linguist/api-report.md | 21 +++ plugins/linguist/dev/index.tsx | 27 +++ plugins/linguist/docs/linguist-no-data.png | Bin 0 -> 12616 bytes plugins/linguist/docs/linguist-no-refresh.png | Bin 0 -> 15731 bytes plugins/linguist/docs/linguist-with-data.png | Bin 0 -> 22018 bytes plugins/linguist/package.json | 63 +++++++ plugins/linguist/src/api/LinguistApi.ts | 26 +++ plugins/linguist/src/api/LinguistClient.ts | 59 ++++++ plugins/linguist/src/api/index.ts | 18 ++ .../components/LinguistCard/LinguistCard.tsx | 153 ++++++++++++++++ .../src/components/LinguistCard/index.ts | 17 ++ plugins/linguist/src/hooks/index.ts | 17 ++ plugins/linguist/src/hooks/useLanguages.ts | 41 +++++ plugins/linguist/src/index.ts | 20 ++ plugins/linguist/src/plugin.test.ts | 22 +++ plugins/linguist/src/plugin.ts | 53 ++++++ plugins/linguist/src/setupTests.ts | 18 ++ yarn.lock | 130 +++++++++++-- 51 files changed, 2005 insertions(+), 11 deletions(-) create mode 100644 .changeset/serious-horses-juggle.md create mode 100644 packages/backend/src/plugins/linguist.ts create mode 100644 plugins/linguist-backend/.eslintrc.js create mode 100644 plugins/linguist-backend/README.md create mode 100644 plugins/linguist-backend/api-report.md create mode 100644 plugins/linguist-backend/config.d.ts create mode 100644 plugins/linguist-backend/migrations/20221115_init.js create mode 100644 plugins/linguist-backend/package.json create mode 100644 plugins/linguist-backend/src/api/LinguistBackendApi.ts create mode 100644 plugins/linguist-backend/src/api/index.ts create mode 100644 plugins/linguist-backend/src/db/LinguistBackendDatabase.ts create mode 100644 plugins/linguist-backend/src/db/index.ts create mode 100644 plugins/linguist-backend/src/index.ts create mode 100644 plugins/linguist-backend/src/run.ts create mode 100644 plugins/linguist-backend/src/service/router.test.ts create mode 100644 plugins/linguist-backend/src/service/router.ts create mode 100644 plugins/linguist-backend/src/service/standaloneServer.ts create mode 100644 plugins/linguist-backend/src/setupTests.ts create mode 100644 plugins/linguist-common/.eslintrc.js create mode 100644 plugins/linguist-common/README.md create mode 100644 plugins/linguist-common/api-report.md create mode 100644 plugins/linguist-common/package.json create mode 100644 plugins/linguist-common/src/constants.ts create mode 100644 plugins/linguist-common/src/index.ts create mode 100644 plugins/linguist-common/src/setupTests.ts create mode 100644 plugins/linguist-common/src/types.ts create mode 100644 plugins/linguist/.eslintrc.js create mode 100644 plugins/linguist/README.md create mode 100644 plugins/linguist/api-report.md create mode 100644 plugins/linguist/dev/index.tsx create mode 100644 plugins/linguist/docs/linguist-no-data.png create mode 100644 plugins/linguist/docs/linguist-no-refresh.png create mode 100644 plugins/linguist/docs/linguist-with-data.png create mode 100644 plugins/linguist/package.json create mode 100644 plugins/linguist/src/api/LinguistApi.ts create mode 100644 plugins/linguist/src/api/LinguistClient.ts create mode 100644 plugins/linguist/src/api/index.ts create mode 100644 plugins/linguist/src/components/LinguistCard/LinguistCard.tsx create mode 100644 plugins/linguist/src/components/LinguistCard/index.ts create mode 100644 plugins/linguist/src/hooks/index.ts create mode 100644 plugins/linguist/src/hooks/useLanguages.ts create mode 100644 plugins/linguist/src/index.ts create mode 100644 plugins/linguist/src/plugin.test.ts create mode 100644 plugins/linguist/src/plugin.ts create mode 100644 plugins/linguist/src/setupTests.ts diff --git a/.changeset/serious-horses-juggle.md b/.changeset/serious-horses-juggle.md new file mode 100644 index 0000000000..13be1d9715 --- /dev/null +++ b/.changeset/serious-horses-juggle.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-linguist': minor +'@backstage/plugin-linguist-backend': minor +'@backstage/plugin-linguist-common': minor +--- + +Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! diff --git a/packages/app/package.json b/packages/app/package.json index 80ee11ea15..8c26254268 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -42,6 +42,8 @@ "@backstage/plugin-kubernetes": "workspace:^", "@backstage/plugin-lighthouse": "workspace:^", "@backstage/plugin-microsoft-calendar": "workspace:^", + "@backstage/plugin-linguist": "workspace:^", + "@backstage/plugin-linguist-common": "workspace:^", "@backstage/plugin-newrelic": "workspace:^", "@backstage/plugin-newrelic-dashboard": "workspace:^", "@backstage/plugin-org": "workspace:^", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 3ab0e83238..9118347414 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -157,6 +157,10 @@ import { LightBox, } from '@backstage/plugin-techdocs-module-addons-contrib'; import { EntityCostInsightsContent } from '@backstage/plugin-cost-insights'; +import { + isLinguistAvailable, + EntityLinguistCard, +} from '@backstage/plugin-linguist'; const customEntityFilterKind = ['Component', 'API', 'System']; @@ -406,6 +410,14 @@ const overviewContent = ( + + + + + + + + diff --git a/packages/backend/package.json b/packages/backend/package.json index 3678c1f9ae..776aa18862 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -50,6 +50,7 @@ "@backstage/plugin-kafka-backend": "workspace:^", "@backstage/plugin-kubernetes-backend": "workspace:^", "@backstage/plugin-lighthouse-backend": "workspace:^", + "@backstage/plugin-linguist-backend": "workspace:^", "@backstage/plugin-permission-backend": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index b68b162e52..eb2befca65 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -63,6 +63,7 @@ import permission from './plugins/permission'; import playlist from './plugins/playlist'; import adr from './plugins/adr'; import lighthouse from './plugins/lighthouse'; +import linguist from './plugins/linguist'; import { PluginEnvironment } from './types'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -154,6 +155,7 @@ async function main() { const eventBasedEntityProviders = await catalogEventBasedProviders( catalogEnv, ); + const linguistEnv = useHotMemoize(module, () => createEnv('linguist')); const apiRouter = Router(); apiRouter.use( @@ -180,6 +182,7 @@ async function main() { apiRouter.use('/playlist', await playlist(playlistEnv)); apiRouter.use('/explore', await explore(exploreEnv)); apiRouter.use('/adr', await adr(adrEnv)); + apiRouter.use('/linguist', await linguist(linguistEnv)); apiRouter.use(notFoundHandler()); await lighthouse(lighthouseEnv); diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts new file mode 100644 index 0000000000..d8e56f658b --- /dev/null +++ b/packages/backend/src/plugins/linguist.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2022 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 { TaskScheduleDefinition } from '@backstage/backend-tasks'; +import { createRouter } from '@backstage/plugin-linguist-backend'; +import { Router } from 'express'; +import type { PluginEnvironment } from '../types'; + +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, + }; + + return createRouter({ + logger: env.logger, + config: env.config, + reader: env.reader, + discovery: env.discovery, + database: env.database, + scheduler: env.scheduler, + schedule: schedule, + }); +} diff --git a/packages/catalog-model/examples/components/artist-lookup-component.yaml b/packages/catalog-model/examples/components/artist-lookup-component.yaml index c0022762b4..a3a3780c84 100644 --- a/packages/catalog-model/examples/components/artist-lookup-component.yaml +++ b/packages/catalog-model/examples/components/artist-lookup-component.yaml @@ -28,6 +28,8 @@ metadata: - url: https://example.com/alert title: Alerts icon: alert + annotations: + backstage.io/linguist: 'https://github.com/backstage/backstage/tree/master/plugins/playlist' spec: type: service lifecycle: experimental diff --git a/plugins/linguist-backend/.eslintrc.js b/plugins/linguist-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/linguist-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md new file mode 100644 index 0000000000..d3c39a5fe7 --- /dev/null +++ b/plugins/linguist-backend/README.md @@ -0,0 +1,94 @@ +# Linguist Backend + +Welcome to the Linguist backend plugin! This plugin provides data for the Linguist frontend features. + +## Setup + +The following sections will help you get the Linguist Backend plugin setup and running. + +### Up and Running + +Here's how to get the backend up and running: + +1. First we need to add the `@backstage/plugin-linguist-backend` package to your backend: + + ```sh + # From the Backstage root directory + cd packages/backend + yarn add @backstage/plugin-linguist-backend + ``` + +2. Then we will create a new file named `packages/backend/src/plugins/linguist.ts`, and add the + following to it: + + ```ts + import { TaskScheduleDefinition } from '@backstage/backend-tasks'; + import { createRouter } from '@backstage/plugin-linguist-backend'; + import { Router } from 'express'; + import type { PluginEnvironment } from '../types'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + const schedule: TaskScheduleDefinition = { + frequency: { hours: 24 }, + timeout: { minutes: 30 }, + initialDelay: { seconds: 90 }, + }; + + return createRouter({ + logger: env.logger, + config: env.config, + reader: env.reader, + discovery: env.discovery, + database: env.database, + scheduler: env.scheduler, + schedule: schedule, + }); + } + ``` + +3. Next we wire this into the overall backend router, edit `packages/backend/src/index.ts`: + + ```ts + import linguist from './plugins/linguist'; + // ... + async function main() { + // ... + // Add this line under the other lines that follow the useHotMemoize pattern + const linguistEnv = useHotMemoize(module, () => createEnv('linguist')); + // ... + // Insert this line under the other lines that add their routers to apiRouter in the same way + apiRouter.use('/linguist', await linguist(linguistEnv)); + ``` + +4. Now run `yarn start-backend` from the repo root +5. Finally open `http://localhost:7007/api/linguist/health` in a browser and it should return `{"status":"ok"}` + +## Scheduling + +The Linguist backend can be configured to generate the language breakdown for all the entities with the linguist annotation. This is done by passing a `TaskScheduleDefinition` to the `createRouter` function like in Step 2 of the [Up and Running](#up-and-running) documentation. + +Here's another example of the `TaskScheduleDefinition` that will run the language breakdown processing every 12 hours: + +```ts +const schedule: TaskScheduleDefinition = { + frequency: { hours: 12 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 10 }, +}; +``` + +The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the following configuration to your `app-config.yaml`: + +```yaml +linguist: + age: 15 # Days +``` + +With the configuration setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. + +## Links + +- [Frontend part of the plugin](../linguist/README.md) +- [The Backstage homepage](https://backstage.io) diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md new file mode 100644 index 0000000000..26656416df --- /dev/null +++ b/plugins/linguist-backend/api-report.md @@ -0,0 +1,86 @@ +## API Report File for "@backstage/plugin-linguist-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import { EntitiesOverview } from '@backstage/plugin-linguist-common'; +import { EntityResults } from '@backstage/plugin-linguist-common'; +import express from 'express'; +import { Knex } from 'knex'; +import { Languages } from '@backstage/plugin-linguist-common'; +import { Logger } from 'winston'; +import { PluginDatabaseManager } from '@backstage/backend-common'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; +import { PluginTaskScheduler } from '@backstage/backend-tasks'; +import { ProcessedEntity } from '@backstage/plugin-linguist-common'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; +import { UrlReader } from '@backstage/backend-common'; + +// @public (undocumented) +export function createRouter(options: RouterOptions): Promise; + +// @public (undocumented) +export class LinguistBackendApi { + constructor( + config: Config, + logger: Logger, + store: LinguistBackendStore, + urlReader: UrlReader, + discovery: PluginEndpointDiscovery, + ); + // (undocumented) + getEntitiesOverview(): Promise; + // (undocumented) + getEntityLanguages(entityRef: string): Promise; + // (undocumented) + processEntities(): Promise; + // (undocumented) + processEntity(entityRef: string, url: string): Promise; +} + +// @public (undocumented) +export class LinguistBackendDatabase implements LinguistBackendStore { + constructor(db: Knex); + // (undocumented) + static create(knex: Knex): Promise; + // (undocumented) + getEntityResults(entityRef: string): Promise; + // (undocumented) + getProcessedEntities(): Promise; + // (undocumented) + insertEntityResults(entityLanguages: EntityResults): Promise; +} + +// @public (undocumented) +export interface LinguistBackendStore { + // (undocumented) + getEntityResults(entityRef: string): Promise; + // (undocumented) + getProcessedEntities(): Promise; + // (undocumented) + insertEntityResults(entityLanguages: EntityResults): Promise; +} + +// @public (undocumented) +export interface RouterOptions { + // (undocumented) + config: Config; + // (undocumented) + database: PluginDatabaseManager; + // (undocumented) + discovery: PluginEndpointDiscovery; + // (undocumented) + linguistBackendApi?: LinguistBackendApi; + // (undocumented) + logger: Logger; + // (undocumented) + reader: UrlReader; + // (undocumented) + schedule?: TaskScheduleDefinition; + // (undocumented) + scheduler?: PluginTaskScheduler; +} + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts new file mode 100644 index 0000000000..8e0133c90b --- /dev/null +++ b/plugins/linguist-backend/config.d.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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 interface Config { + /** Configuration options for the linguist-backend plugin */ + linguist?: { + /** + * The age of an entity's languages before a refresh occurs, + * an age of 30 would mean the languages would be regenerated after 30 days. + * The default is 0 meaning languages won't be refreshed once generated. + */ + age: number; + }; +} diff --git a/plugins/linguist-backend/migrations/20221115_init.js b/plugins/linguist-backend/migrations/20221115_init.js new file mode 100644 index 0000000000..9eb0a03a90 --- /dev/null +++ b/plugins/linguist-backend/migrations/20221115_init.js @@ -0,0 +1,67 @@ +/* + * Copyright 2022 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. + */ + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // Note for the reader: the knex increments types automatically make it a + // primary column, whether you like it or not. That's why the id column is + // not marked as primary as one might have expected; it's only used for + // lookups by ID. Because, SQLite and MySQL don't return RETURNING on + // inserts ... so we want a manually generated key for lookups (an uuid), + // and also an index for ordering guarantees :) + await knex.schema.createTable('entity_result', table => { + table.comment('Table containing results from running Linguist'); + table + .bigIncrements('index') + .notNullable() + .comment('An insert counter to ensure ordering'); + table.uuid('id').notNullable().comment('The ID of the Linguist result'); + table + .text('entity_ref') + .unique() + .notNullable() + .comment('The entity ref that this Linguist result applies to'); + table + .text('languages') + .notNullable() + .comment('The results json as a string'); + table + .dateTime('created_at') + .defaultTo(knex.fn.now()) + .notNullable() + .comment('The timestamp when this entry was created'); + table + .dateTime('processed_date') + .defaultTo(knex.fn.now()) + .notNullable() + .comment('The timestamp when this entity was processed'); + table.index('index', 'entity_result_index_idx'); + table.index('entity_ref', 'entity_result_entity_ref_idx'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('entity_result', table => { + table.dropIndex([], 'entity_result_index_idx'); + table.dropIndex([], 'entity_result_entity_ref_idx'); + }); + await knex.schema.dropTable('entity_result'); +}; diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json new file mode 100644 index 0000000000..b79a97decd --- /dev/null +++ b/plugins/linguist-backend/package.json @@ -0,0 +1,57 @@ +{ + "name": "@backstage/plugin-linguist-backend", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-tasks": "workspace:^", + "@backstage/catalog-client": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "@backstage/plugin-linguist-common": "workspace:^", + "@types/express": "*", + "express": "^4.18.1", + "express-promise-router": "^4.1.0", + "fs-extra": "^10.0.0", + "knex": "^2.0.0", + "linguist-js": "^2.5.3", + "luxon": "^2.0.2", + "node-fetch": "^2.6.7", + "uuid": "^8.3.2", + "winston": "^3.2.1", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@types/supertest": "^2.0.8", + "msw": "^0.49.0", + "supertest": "^6.2.4" + }, + "files": [ + "dist", + "config.d.ts", + "migrations/**/*.{js,d.ts}" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts new file mode 100644 index 0000000000..fdabea6d6c --- /dev/null +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -0,0 +1,173 @@ +/* + * Copyright 2022 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 { + EntitiesOverview, + EntityResults, + Language, + Languages, +} from '@backstage/plugin-linguist-common'; +import { + CATALOG_FILTER_EXISTS, + CatalogClient, + GetEntitiesRequest, +} from '@backstage/catalog-client'; +import { PluginEndpointDiscovery, UrlReader } from '@backstage/backend-common'; + +import { Config } from '@backstage/config'; +import { DateTime } from 'luxon'; +import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; +import { LinguistBackendStore } from '../db'; +import { Logger } from 'winston'; +import fs from 'fs-extra'; +import linguist from 'linguist-js'; +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { assertError } from '@backstage/errors'; + +/** @public */ +export class LinguistBackendApi { + public constructor( + private readonly config: Config, + private readonly logger: Logger, + private readonly store: LinguistBackendStore, + private readonly urlReader: UrlReader, + private readonly discovery: PluginEndpointDiscovery, + ) {} + + public async getEntityLanguages(entityRef: string): Promise { + this.logger?.debug(`Getting languages for entity "${entityRef}"`); + + return this.store.getEntityResults(entityRef); + } + + public async processEntity(entityRef: string, url: string): Promise { + this.logger?.info( + `Processing languages for entity ${entityRef} from ${url}`, + ); + + const readTreeResponse = await this.urlReader.readTree(url); + const dir = await readTreeResponse.dir(); + + const results = await linguist(dir); + + try { + const totalBytes = results.languages.bytes; + const langResults = results.languages.results; + + const breakdown: Language[] = []; + for (const key in langResults) { + if (Object.prototype.hasOwnProperty.call(langResults, key)) { + const lang: Language = { + name: key, + percentage: +((langResults[key].bytes / totalBytes) * 100).toFixed( + 2, + ), + bytes: langResults[key].bytes, + type: langResults[key].type, + color: langResults[key].color, + }; + breakdown.push(lang); + } + } + + const languages: Languages = { + languageCount: results.languages.count, + totalBytes: totalBytes, + processedDate: new Date().toISOString(), + breakdown: breakdown, + }; + + const entityResults: EntityResults = { + entityRef: entityRef, + results: languages, + }; + + return await this.store.insertEntityResults(entityResults); + } finally { + this.logger?.info(`Cleaning up files from ${dir}`); + await fs.remove(dir); + } + } + + public async processEntities() { + this.logger?.info('Processing applicable entities through Linguist'); + + const eo = await this.getEntitiesOverview(); + this.logger?.info( + `Entities overview: Entity: ${eo.entityCount}, Processed: ${eo.processedCount}, Pending: ${eo.pendingCount}, Stale ${eo.staleCount}`, + ); + + const entities = eo.filteredEntities; + for (const key in entities) { + if (Object.prototype.hasOwnProperty.call(entities, key)) { + const entityRef = stringifyEntityRef(entities[key]); + + const url = + entities[key].metadata.annotations?.[LINGUIST_ANNOTATION] ?? ''; + + try { + await this.processEntity(entityRef, url); + } catch (e) { + assertError(e); + this.logger.error( + `Unable to process "${entityRef}" using "${url}", ${e.message}`, + ); + } + } + } + } + + public async getEntitiesOverview(): Promise { + this.logger?.debug('Getting pending entities'); + const age = this.config.getOptionalNumber('linguist.age') ?? 0; + const catalogApi = new CatalogClient({ discoveryApi: this.discovery }); + const request: GetEntitiesRequest = { + filter: { + kind: ['API', 'Component', 'Template'], + [`metadata.annotations.${LINGUIST_ANNOTATION}`]: CATALOG_FILTER_EXISTS, + }, + fields: ['kind', 'metadata'], + }; + + const response = await catalogApi.getEntities(request); + const entities = response.items; + + const processedEntities = await this.store.getProcessedEntities(); + + const staleEntities = processedEntities.filter(pe => { + if (age === 0) return false; + const staleDate = DateTime.now().minus({ days: age }); + return DateTime.fromJSDate(pe.processed_date) >= staleDate; + }); + + const filteredEntities = entities.filter(en => { + return processedEntities.every(pe => { + const entityRef = stringifyEntityRef(en); + return pe.entityRef !== entityRef; + }); + }); + + const entitiesOverview: EntitiesOverview = { + entityCount: entities.length, + processedCount: processedEntities.length, + staleCount: staleEntities.length, + pendingCount: filteredEntities.length, + filteredEntities: filteredEntities, + }; + + return entitiesOverview; + } +} diff --git a/plugins/linguist-backend/src/api/index.ts b/plugins/linguist-backend/src/api/index.ts new file mode 100644 index 0000000000..a88fa051d4 --- /dev/null +++ b/plugins/linguist-backend/src/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 { LinguistBackendApi } from './LinguistBackendApi'; diff --git a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts new file mode 100644 index 0000000000..8faa5c3ff0 --- /dev/null +++ b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts @@ -0,0 +1,103 @@ +/* + * Copyright 2022 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 { resolvePackagePath } from '@backstage/backend-common'; +import { Knex } from 'knex'; +import { v4 as uuid } from 'uuid'; +import { + EntityResults, + Languages, + ProcessedEntity, +} from '@backstage/plugin-linguist-common'; + +export type RawDbEntityResultRow = { + id: string; + entity_ref: string; + languages: string; + processed_date: Date; +}; + +/** @public */ +export interface LinguistBackendStore { + insertEntityResults(entityLanguages: EntityResults): Promise; + getEntityResults(entityRef: string): Promise; + getProcessedEntities(): Promise; +} + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-linguist-backend', + 'migrations', +); + +/** @public */ +export class LinguistBackendDatabase implements LinguistBackendStore { + static async create(knex: Knex): Promise { + await knex.migrate.latest({ + directory: migrationsDir, + }); + return new LinguistBackendDatabase(knex); + } + + constructor(private readonly db: Knex) {} + + async insertEntityResults(entityLanguages: EntityResults): Promise { + const entityLanguageId = uuid(); + const entityRef = entityLanguages.entityRef; + + const [result] = await this.db('entity_result') + .insert({ + id: entityLanguageId, + entity_ref: entityRef, + languages: JSON.stringify(entityLanguages.results), + processed_date: new Date(entityLanguages.results.processedDate), + }) + .onConflict('entity_ref') + .merge(['languages', 'processed_date']) + .returning('id'); + + return result.id; + } + + async getEntityResults(entityRef: string): Promise { + const entityResults = await this.db('entity_result') + .where({ entity_ref: entityRef }) + .first(); + + if (!entityResults) { + const emptyResults: Languages = { + languageCount: 0, + totalBytes: 0, + processedDate: 'undefined', + breakdown: [], + }; + return emptyResults; + } + + try { + return JSON.parse(entityResults.languages); + } catch (error) { + throw new Error(`Failed to parse languages for '${entityRef}', ${error}`); + } + } + + async getProcessedEntities(): Promise { + const entityResults = await this.db( + 'entity_result', + ).select('entity_ref', 'processed_date'); + + return entityResults; + } +} diff --git a/plugins/linguist-backend/src/db/index.ts b/plugins/linguist-backend/src/db/index.ts new file mode 100644 index 0000000000..c8ec15da68 --- /dev/null +++ b/plugins/linguist-backend/src/db/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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 { LinguistBackendDatabase } from './LinguistBackendDatabase'; +export type { LinguistBackendStore } from './LinguistBackendDatabase'; diff --git a/plugins/linguist-backend/src/index.ts b/plugins/linguist-backend/src/index.ts new file mode 100644 index 0000000000..da1e0ffb00 --- /dev/null +++ b/plugins/linguist-backend/src/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2022 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 './service/router'; +export { LinguistBackendApi } from './api'; +export { LinguistBackendDatabase } from './db'; +export type { LinguistBackendStore } from './db'; diff --git a/plugins/linguist-backend/src/run.ts b/plugins/linguist-backend/src/run.ts new file mode 100644 index 0000000000..d945aa13f0 --- /dev/null +++ b/plugins/linguist-backend/src/run.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2022 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 { getRootLogger } from '@backstage/backend-common'; +import yn from 'yn'; +import { startStandaloneServer } from './service/standaloneServer'; + +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; +const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); +const logger = getRootLogger(); + +startStandaloneServer({ port, enableCors, logger }).catch(err => { + logger.error(err); + process.exit(1); +}); + +process.on('SIGINT', () => { + logger.info('CTRL+C pressed; exiting.'); + process.exit(0); +}); diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts new file mode 100644 index 0000000000..0e20987a43 --- /dev/null +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -0,0 +1,83 @@ +/* + * Copyright 2022 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 { + DatabaseManager, + getVoidLogger, + PluginDatabaseManager, + PluginEndpointDiscovery, + UrlReaders, +} from '@backstage/backend-common'; +import express from 'express'; +import request from 'supertest'; +import { ConfigReader } from '@backstage/config'; +import { createRouter } from './router'; +import { LinguistBackendApi } from '../api'; + +function createDatabase(): PluginDatabaseManager { + return DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'better-sqlite3', + connection: ':memory:', + }, + }, + }), + ).forPlugin('code-coverage'); +} + +const testDiscovery: jest.Mocked = { + getBaseUrl: jest + .fn() + .mockResolvedValue('http://localhost:7007/api/code-coverage'), + getExternalBaseUrl: jest.fn(), +}; + +const mockUrlReader = UrlReaders.default({ + logger: getVoidLogger(), + config: new ConfigReader({}), +}); + +describe('createRouter', () => { + let linguistBackendApi: jest.Mocked; + let app: express.Express; + + beforeAll(async () => { + const router = await createRouter({ + linguistBackendApi, + config: new ConfigReader({}), + discovery: testDiscovery, + database: createDatabase(), + reader: mockUrlReader, + logger: getVoidLogger(), + }); + app = express().use(router); + }); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + describe('GET /health', () => { + it('returns ok', async () => { + const response = await request(app).get('/health'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ status: 'ok' }); + }); + }); +}); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts new file mode 100644 index 0000000000..091b7f408d --- /dev/null +++ b/plugins/linguist-backend/src/service/router.ts @@ -0,0 +1,108 @@ +/* + * Copyright 2022 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 { + errorHandler, + PluginDatabaseManager, + PluginEndpointDiscovery, + UrlReader, +} from '@backstage/backend-common'; +import { Config } from '@backstage/config'; +import express from 'express'; +import Router from 'express-promise-router'; +import { Logger } from 'winston'; +import { LinguistBackendApi } from '../api'; +import { LinguistBackendDatabase } from '../db'; +import { + PluginTaskScheduler, + TaskScheduleDefinition, +} from '@backstage/backend-tasks'; + +/** @public */ +export interface RouterOptions { + linguistBackendApi?: LinguistBackendApi; + config: Config; + logger: Logger; + reader: UrlReader; + database: PluginDatabaseManager; + discovery: PluginEndpointDiscovery; + scheduler?: PluginTaskScheduler; + schedule?: TaskScheduleDefinition; +} + +/** @public */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { config, logger, reader, database, discovery, scheduler, schedule } = + options; + + const linguistBackendStore = await LinguistBackendDatabase.create( + await database.getClient(), + ); + + const linguistBackendApi = + options.linguistBackendApi || + new LinguistBackendApi( + config, + logger, + linguistBackendStore, + reader, + discovery, + ); + + if (scheduler && schedule) { + logger.info( + `Scheduling processing of entities with: ${JSON.stringify(schedule)}`, + ); + await scheduler.scheduleTask({ + id: 'linguist_process_entities', + frequency: schedule.frequency, + timeout: schedule.timeout, + initialDelay: schedule.initialDelay, + scope: schedule.scope, + fn: async () => { + await linguistBackendApi.processEntities(); + }, + }); + } + + const router = Router(); + router.use(express.json()); + + router.get('/health', (_, response) => { + response.send({ status: 'ok' }); + }); + + /** + * /entity-languages?entity=component:default/my-component + */ + router.get('/entity-languages', async (req, res) => { + const { entityRef: entityRef } = req.query; + + if (!entityRef) { + throw new Error('No entityRef was provided'); + } + + const entityLanguages = await linguistBackendApi.getEntityLanguages( + entityRef as string, + ); + res.status(200).json(entityLanguages); + }); + + router.use(errorHandler()); + return router; +} diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..5578c20e95 --- /dev/null +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2022 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 { + createServiceBuilder, + loadBackendConfig, + SingleHostDiscovery, + UrlReaders, + useHotMemoize, +} from '@backstage/backend-common'; +import { Server } from 'http'; +import { Logger } from 'winston'; +import { createRouter } from './router'; +import knexFactory from 'knex'; + +export interface ServerOptions { + port: number; + enableCors: boolean; + logger: Logger; +} + +export async function startStandaloneServer( + options: ServerOptions, +): Promise { + const logger = options.logger.child({ service: 'linguist-backend' }); + const config = await loadBackendConfig({ logger, argv: process.argv }); + const db = useHotMemoize(module, () => { + const knex = knexFactory({ + client: 'sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }); + + knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { + resource.run('PRAGMA foreign_keys = ON', () => {}); + }); + + return knex; + }); + + logger.debug('Starting application server...'); + const router = await createRouter({ + database: { getClient: async () => db }, + config, + discovery: SingleHostDiscovery.fromConfig(config), + reader: UrlReaders.default({ logger, config }), + logger, + }); + + let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/linguist', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } + + return await service.start().catch(err => { + logger.error(err); + process.exit(1); + }); +} + +module.hot?.accept(); diff --git a/plugins/linguist-backend/src/setupTests.ts b/plugins/linguist-backend/src/setupTests.ts new file mode 100644 index 0000000000..813cdeaae3 --- /dev/null +++ b/plugins/linguist-backend/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 {}; diff --git a/plugins/linguist-common/.eslintrc.js b/plugins/linguist-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/linguist-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/linguist-common/README.md b/plugins/linguist-common/README.md new file mode 100644 index 0000000000..9408f7fcc5 --- /dev/null +++ b/plugins/linguist-common/README.md @@ -0,0 +1,3 @@ +# Linguist Common + +Common types, permissions, and constants for the Linguist plugin. diff --git a/plugins/linguist-common/api-report.md b/plugins/linguist-common/api-report.md new file mode 100644 index 0000000000..a9eceb3839 --- /dev/null +++ b/plugins/linguist-common/api-report.md @@ -0,0 +1,50 @@ +## API Report File for "@backstage/plugin-linguist-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Entity } from '@backstage/catalog-model'; + +// @public (undocumented) +export type EntitiesOverview = { + entityCount: number; + processedCount: number; + pendingCount: number; + staleCount: number; + filteredEntities: Entity[]; +}; + +// @public (undocumented) +export type EntityResults = { + entityRef: string; + results: Languages; +}; + +// @public (undocumented) +export type Language = { + name: string; + percentage: number; + bytes: number; + type: string; + color?: `#${string}`; +}; + +// @public (undocumented) +export type Languages = { + languageCount: number; + totalBytes: number; + processedDate: string; + breakdown: Language[]; +}; + +// @public (undocumented) +export const LINGUIST_ANNOTATION = 'backstage.io/linguist'; + +// @public (undocumented) +export type ProcessedEntity = { + entityRef: string; + processed_date: Date; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/linguist-common/package.json b/plugins/linguist-common/package.json new file mode 100644 index 0000000000..eddc114a67 --- /dev/null +++ b/plugins/linguist-common/package.json @@ -0,0 +1,35 @@ +{ + "name": "@backstage/plugin-linguist-common", + "description": "Common functionalities for the linguist plugin", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "common-library" + }, + "scripts": { + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/catalog-model": "workspace:^", + "@backstage/plugin-permission-common": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/linguist-common/src/constants.ts b/plugins/linguist-common/src/constants.ts new file mode 100644 index 0000000000..55b3d21d02 --- /dev/null +++ b/plugins/linguist-common/src/constants.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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. + */ + +/** @public */ +export const LINGUIST_ANNOTATION = 'backstage.io/linguist'; diff --git a/plugins/linguist-common/src/index.ts b/plugins/linguist-common/src/index.ts new file mode 100644 index 0000000000..88fe08c714 --- /dev/null +++ b/plugins/linguist-common/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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'; +export * from './constants'; diff --git a/plugins/linguist-common/src/setupTests.ts b/plugins/linguist-common/src/setupTests.ts new file mode 100644 index 0000000000..8b9b6bd586 --- /dev/null +++ b/plugins/linguist-common/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 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 {}; diff --git a/plugins/linguist-common/src/types.ts b/plugins/linguist-common/src/types.ts new file mode 100644 index 0000000000..01222492b6 --- /dev/null +++ b/plugins/linguist-common/src/types.ts @@ -0,0 +1,54 @@ +/* + * Copyright 2022 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 { Entity } from '@backstage/catalog-model'; + +/** @public */ +export type EntityResults = { + entityRef: string; + results: Languages; +}; + +/** @public */ +export type Languages = { + languageCount: number; + totalBytes: number; + processedDate: string; + breakdown: Language[]; +}; + +/** @public */ +export type Language = { + name: string; + percentage: number; + bytes: number; + type: string; + color?: `#${string}`; +}; + +/** @public */ +export type ProcessedEntity = { + entityRef: string; + processed_date: Date; +}; + +/** @public */ +export type EntitiesOverview = { + entityCount: number; + processedCount: number; + pendingCount: number; + staleCount: number; + filteredEntities: Entity[]; +}; diff --git a/plugins/linguist/.eslintrc.js b/plugins/linguist/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/linguist/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/linguist/README.md b/plugins/linguist/README.md new file mode 100644 index 0000000000..d5ca2199dd --- /dev/null +++ b/plugins/linguist/README.md @@ -0,0 +1,88 @@ +# Linguist + +Welcome to the Linguist plugin! + +## Features + +The Linguist plugin consists of a card that will give you the breakdown of the languages used by the configured Entity in the Catalog. + +When there is no Linguist data yet the card will be empty: + +![Example of empty Linguist card](./docs/linguist-no-data.png) + +Clicking on the refresh icon will generate the language breakdown: + +![Example of Linguist card with data](./docs/linguist-with-data.png) + +Here's an example where the permissions are hiding the refresh button: + +![Example of Linguist card without the refresh button](./docs/linguist-no-refresh.png) + +## Setup + +The following sections will help you get the Linguist plugin setup and running. + +### Backend + +You need to setup the [Linguist backend plugin](../linguist-backend/README.md) before you move forward with any of the following steps if you haven't already. + +### Entity Annotation + +To be able to use the Linguist plugin you need to add the following annotation to any entities you want to use it with: + +```yaml +backstage.io/linguist: https://url.to/your/srouce/code +``` + +Linguist uses the `UrlReader` to pull down the files before it scans them to determine the languages, this means you can pull files from all the supported providers - GitHub, GitLab, Bitbucket, Azure, Google GCS, AWS S3, etc. + +Here's what that will look like in action using the Backstage repo as an example: + +```yaml +# Example catalog-info.yaml entity definition file +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + # ... + annotations: + backstage.io/linguist: https://github.com/backstage/backstage +spec: + type: service + # ... +``` + +### Frontend + +To setup the Linguist Card frontend you'll need to do the following steps: + +1. First we need to add the `@backstage/plugin-linguist` package to your frontend app: + + ```sh + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-linguist + ``` + +2. Second we need to add the `EntityLinguistCard` extension to the entity page in your app: + + ```tsx + // In packages/app/src/components/catalog/EntityPage.tsx + import { isLinguistAvailable, EntityLinguistCard } from '@backstage/plugin-linguist'; + + // For example in the Overview section + const overviewContent = ( + + // ... + + + + + + + + // ... + + ``` + +**Notes:** + +- The `if` prop is optional on the `EntitySwitch.Case`, you can remove it if you always want to see the tab even if the entity being viewed does not have the needed annotation diff --git a/plugins/linguist/api-report.md b/plugins/linguist/api-report.md new file mode 100644 index 0000000000..469b3b93c0 --- /dev/null +++ b/plugins/linguist/api-report.md @@ -0,0 +1,21 @@ +## API Report File for "@backstage/plugin-linguist" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; + +// @public (undocumented) +export const EntityLinguistCard: () => JSX.Element; + +// @public (undocumented) +export const isLinguistAvailable: (entity: Entity) => boolean; + +// @public (undocumented) +export const linguistPlugin: BackstagePlugin<{}, {}, {}>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/linguist/dev/index.tsx b/plugins/linguist/dev/index.tsx new file mode 100644 index 0000000000..bb6fb64b52 --- /dev/null +++ b/plugins/linguist/dev/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2022 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 React from 'react'; +import { createDevApp } from '@backstage/dev-utils'; +import { linguistPlugin, EntityLinguistCard } from '../src/plugin'; + +createDevApp() + .registerPlugin(linguistPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/linguist', + }) + .render(); diff --git a/plugins/linguist/docs/linguist-no-data.png b/plugins/linguist/docs/linguist-no-data.png new file mode 100644 index 0000000000000000000000000000000000000000..208b8df5d54f73c71a3ae070587c46d0e853a788 GIT binary patch literal 12616 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 Mw4zk5guc)J0^%y>`2YX_ literal 0 HcmV?d00001 diff --git a/plugins/linguist/docs/linguist-no-refresh.png b/plugins/linguist/docs/linguist-no-refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..a3b4e4fde7fa9a38fb1f4e810a14e800c31b0837 GIT binary patch literal 15731 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 literal 0 HcmV?d00001 diff --git a/plugins/linguist/docs/linguist-with-data.png b/plugins/linguist/docs/linguist-with-data.png new file mode 100644 index 0000000000000000000000000000000000000000..e673f994fab4d1db32b0a1cfb1c06bad657efee3 GIT binary patch literal 22018 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 + id: 'plugin.linguist.service', +}); + +export interface LinguistApi { + getLanguages(entityRef: string): Promise; +} diff --git a/plugins/linguist/src/api/LinguistClient.ts b/plugins/linguist/src/api/LinguistClient.ts new file mode 100644 index 0000000000..3e327ff21e --- /dev/null +++ b/plugins/linguist/src/api/LinguistClient.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2022 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 { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import { Languages } from '@backstage/plugin-linguist-common'; +import { LinguistApi } from './LinguistApi'; + +export class LinguistClient implements LinguistApi { + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + + public constructor(options: { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + }) { + this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; + } + + public async getLanguages(entityRef: string): Promise { + const queryString = new URLSearchParams(); + queryString.append('entityRef', entityRef); + + const urlSegment = `entity-languages?${queryString}`; + + const items = await this.get(urlSegment); + return items; + } + + private async get(path: string): Promise { + const baseUrl = `${await this.discoveryApi.getBaseUrl('linguist')}/`; + const url = new URL(path, baseUrl); + + const { token } = await this.identityApi.getCredentials(); + const response = await fetch(url.toString(), { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return response.json() as Promise; + } +} diff --git a/plugins/linguist/src/api/index.ts b/plugins/linguist/src/api/index.ts new file mode 100644 index 0000000000..ca60b60d53 --- /dev/null +++ b/plugins/linguist/src/api/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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 './LinguistApi'; +export * from './LinguistClient'; diff --git a/plugins/linguist/src/components/LinguistCard/LinguistCard.tsx b/plugins/linguist/src/components/LinguistCard/LinguistCard.tsx new file mode 100644 index 0000000000..6014487d30 --- /dev/null +++ b/plugins/linguist/src/components/LinguistCard/LinguistCard.tsx @@ -0,0 +1,153 @@ +/* + * Copyright 2022 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 { + Box, + Chip, + Tooltip, + Typography, + makeStyles, + Grid, + useTheme, +} from '@material-ui/core'; +import { InfoCard, Progress } from '@backstage/core-components'; +import Alert from '@material-ui/lab/Alert'; +import { DateTime } from 'luxon'; +import React from 'react'; +import slugify from 'slugify'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { useLanguages } from '../../hooks'; + +const useStyles = makeStyles(theme => ({ + infoCard: { + marginBottom: theme.spacing(3), + }, + barContainer: { + height: theme.spacing(2), + marginBottom: theme.spacing(3), + borderRadius: '4px', + backgroundColor: 'transparent', + overflow: 'hidden', + }, + bar: { + height: '100%', + position: 'relative', + }, + languageDot: { + width: '10px', + height: '10px', + borderRadius: '50%', + marginRight: theme.spacing(1), + display: 'inline-block', + }, + label: { + color: 'inherit', + }, +})); + +export const LinguistCard = () => { + const classes = useStyles(); + const theme = useTheme(); + const { entity } = useEntity(); + const { items, loading, error } = useLanguages(entity); + let barWidth = 0; + + if (loading) { + return ; + } else if (error) { + return {error.message}; + } + + if (items && items.languageCount === 0 && items.totalBytes === 0) { + return ( + + + + + There is currently no language data for this entity. + + + + + ); + } + + const breakdown = items?.breakdown.sort((a, b) => + a.percentage < b.percentage ? 1 : -1, + ); + const processedDate = items?.processedDate; + + return breakdown && processedDate ? ( + + + {breakdown.map((language, index: number) => { + barWidth = barWidth + language.percentage; + return ( + + + + ); + })} + + + + {breakdown.map(languages => ( + + + {languages.name} - {languages.percentage}% + + } + variant="outlined" + key={slugify(languages.name, { lower: true })} + /> + ))} + + + + ) : ( + <> + ); +}; diff --git a/plugins/linguist/src/components/LinguistCard/index.ts b/plugins/linguist/src/components/LinguistCard/index.ts new file mode 100644 index 0000000000..aefae143fd --- /dev/null +++ b/plugins/linguist/src/components/LinguistCard/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 { LinguistCard } from './LinguistCard'; diff --git a/plugins/linguist/src/hooks/index.ts b/plugins/linguist/src/hooks/index.ts new file mode 100644 index 0000000000..6f8913cf35 --- /dev/null +++ b/plugins/linguist/src/hooks/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 './useLanguages'; diff --git a/plugins/linguist/src/hooks/useLanguages.ts b/plugins/linguist/src/hooks/useLanguages.ts new file mode 100644 index 0000000000..3e99243e94 --- /dev/null +++ b/plugins/linguist/src/hooks/useLanguages.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2022 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 { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { linguistApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; + +import { Languages } from '@backstage/plugin-linguist-common'; + +export function useLanguages(entity: Entity): { + items?: Languages; + loading: boolean; + error?: Error; +} { + const entityRef = stringifyEntityRef(entity); + + const api = useApi(linguistApiRef); + const { value, loading, error } = useAsync(() => { + return api.getLanguages(entityRef); + }, [api, entityRef]); + + return { + items: value, + loading, + error, + }; +} diff --git a/plugins/linguist/src/index.ts b/plugins/linguist/src/index.ts new file mode 100644 index 0000000000..ce9cd98cbd --- /dev/null +++ b/plugins/linguist/src/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2022 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 { + linguistPlugin, + isLinguistAvailable, + EntityLinguistCard, +} from './plugin'; diff --git a/plugins/linguist/src/plugin.test.ts b/plugins/linguist/src/plugin.test.ts new file mode 100644 index 0000000000..d2a1016a22 --- /dev/null +++ b/plugins/linguist/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2022 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 { linguistPlugin } from './plugin'; + +describe('linguist', () => { + it('should export plugin', () => { + expect(linguistPlugin).toBeDefined(); + }); +}); diff --git a/plugins/linguist/src/plugin.ts b/plugins/linguist/src/plugin.ts new file mode 100644 index 0000000000..917a13ca9a --- /dev/null +++ b/plugins/linguist/src/plugin.ts @@ -0,0 +1,53 @@ +/* + * Copyright 2022 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 { + createApiFactory, + createComponentExtension, + createPlugin, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { linguistApiRef, LinguistClient } from './api'; +import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; +import { Entity } from '@backstage/catalog-model'; + +/** @public */ +export const isLinguistAvailable = (entity: Entity) => + Boolean(entity.metadata.annotations?.[LINGUIST_ANNOTATION]); + +/** @public */ +export const linguistPlugin = createPlugin({ + id: 'linguist', + apis: [ + createApiFactory({ + api: linguistApiRef, + deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, + factory: ({ discoveryApi, identityApi }) => + new LinguistClient({ discoveryApi, identityApi }), + }), + ], +}); + +/** @public */ +export const EntityLinguistCard = linguistPlugin.provide( + createComponentExtension({ + name: 'EntityLinguistCard', + component: { + lazy: () => import('./components/LinguistCard').then(m => m.LinguistCard), + }, + }), +); diff --git a/plugins/linguist/src/setupTests.ts b/plugins/linguist/src/setupTests.ts new file mode 100644 index 0000000000..2b5b615b19 --- /dev/null +++ b/plugins/linguist/src/setupTests.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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 '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/yarn.lock b/yarn.lock index 345c28a8b5..9697e098ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6895,6 +6895,78 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-linguist-backend@workspace:^, @backstage/plugin-linguist-backend@workspace:plugins/linguist-backend": + version: 0.0.0-use.local + resolution: "@backstage/plugin-linguist-backend@workspace:plugins/linguist-backend" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-tasks": "workspace:^" + "@backstage/catalog-client": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + "@backstage/plugin-linguist-common": "workspace:^" + "@types/express": "*" + "@types/supertest": ^2.0.8 + express: ^4.18.1 + express-promise-router: ^4.1.0 + fs-extra: ^10.0.0 + knex: ^2.0.0 + linguist-js: ^2.5.3 + luxon: ^2.0.2 + msw: ^0.49.0 + node-fetch: ^2.6.7 + supertest: ^6.2.4 + uuid: ^8.3.2 + winston: ^3.2.1 + yn: ^4.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-linguist-common@workspace:^, @backstage/plugin-linguist-common@workspace:plugins/linguist-common": + version: 0.0.0-use.local + resolution: "@backstage/plugin-linguist-common@workspace:plugins/linguist-common" + dependencies: + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/plugin-permission-common": "workspace:^" + languageName: unknown + linkType: soft + +"@backstage/plugin-linguist@workspace:^, @backstage/plugin-linguist@workspace:plugins/linguist": + version: 0.0.0-use.local + resolution: "@backstage/plugin-linguist@workspace:plugins/linguist" + dependencies: + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/plugin-linguist-common": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": ^4.9.13 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": ^4.0.0-alpha.57 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + luxon: ^2.0.2 + msw: ^0.49.0 + react-use: ^17.2.4 + slugify: ^1.6.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-microsoft-calendar@workspace:^, @backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar": version: 0.0.0-use.local resolution: "@backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar" @@ -11244,7 +11316,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4": +"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4, @material-ui/core@npm:^4.9.13": version: 4.12.4 resolution: "@material-ui/core@npm:4.12.4" dependencies: @@ -17580,10 +17652,10 @@ __metadata: languageName: node linkType: hard -"binary-extensions@npm:^2.0.0": - version: 2.0.0 - resolution: "binary-extensions@npm:2.0.0" - checksum: 554f65d3378cf71c3185c17dec3ca58334b8ff6ae242db3107284765ce33b2af19efd20c11faec41907a40534929e34b3a98e7d391c61e4211b45732dccb1115 +"binary-extensions@npm:^2.0.0, binary-extensions@npm:^2.2.0": + version: 2.2.0 + resolution: "binary-extensions@npm:2.2.0" + checksum: ccd267956c58d2315f5d3ea6757cf09863c5fc703e50fbeb13a7dc849b812ef76e3cf9ca8f35a0c48498776a7478d7b4a0418e1e2b8cb9cb9731f2922aaad7f8 languageName: node linkType: hard @@ -18943,7 +19015,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:*, commander@npm:^9.1.0, commander@npm:^9.4.1": +"commander@npm:*, commander@npm:^9.1.0, commander@npm:^9.4.1, commander@npm:^9.5.0": version: 9.5.0 resolution: "commander@npm:9.5.0" checksum: c7a3e27aa59e913b54a1bafd366b88650bc41d6651f0cbe258d4ff09d43d6a7394232a4dadd0bf518b3e696fdf595db1028a0d82c785b88bd61f8a440cecfade @@ -22227,6 +22299,8 @@ __metadata: "@backstage/plugin-kafka": "workspace:^" "@backstage/plugin-kubernetes": "workspace:^" "@backstage/plugin-lighthouse": "workspace:^" + "@backstage/plugin-linguist": "workspace:^" + "@backstage/plugin-linguist-common": "workspace:^" "@backstage/plugin-microsoft-calendar": "workspace:^" "@backstage/plugin-newrelic": "workspace:^" "@backstage/plugin-newrelic-dashboard": "workspace:^" @@ -22326,6 +22400,7 @@ __metadata: "@backstage/plugin-kafka-backend": "workspace:^" "@backstage/plugin-kubernetes-backend": "workspace:^" "@backstage/plugin-lighthouse-backend": "workspace:^" + "@backstage/plugin-linguist-backend": "workspace:^" "@backstage/plugin-permission-backend": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" @@ -24806,10 +24881,10 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.1.4, ignore@npm:^5.2.0": - version: 5.2.0 - resolution: "ignore@npm:5.2.0" - checksum: 6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77 +"ignore@npm:^5.1.4, ignore@npm:^5.2.0, ignore@npm:^5.2.4": + version: 5.2.4 + resolution: "ignore@npm:5.2.4" + checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef languageName: node linkType: hard @@ -25826,7 +25901,7 @@ __metadata: languageName: node linkType: hard -"isbinaryfile@npm:^4.0.10, isbinaryfile@npm:^4.0.8": +"isbinaryfile@npm:^4.0.10, isbinaryfile@npm:^4.0.8, isbinaryfile@npm:^4.0.8 <5": version: 4.0.10 resolution: "isbinaryfile@npm:4.0.10" checksum: a6b28db7e23ac7a77d3707567cac81356ea18bd602a4f21f424f862a31d0e7ab4f250759c98a559ece35ffe4d99f0d339f1ab884ffa9795172f632ab8f88e686 @@ -27699,6 +27774,25 @@ __metadata: languageName: node linkType: hard +"linguist-js@npm:^2.5.3": + version: 2.5.4 + resolution: "linguist-js@npm:2.5.4" + dependencies: + binary-extensions: ^2.2.0 + commander: ^9.5.0 + common-path-prefix: ^3.0.0 + cross-fetch: ^3.1.5 + ignore: ^5.2.4 + isbinaryfile: ^4.0.8 <5 + js-yaml: ^4.1.0 + node-cache: ^5.1.2 + bin: + linguist: bin/index.js + linguist-js: bin/index.js + checksum: 92ebfc45f0f17a056153068f7e939a3e6755307d3696673597e824011d83b698063241aa7d082a7f9059416efce85a49056f0a31b3158c25f79e273e2f51e309 + languageName: node + linkType: hard + "linkify-it@npm:^3.0.1": version: 3.0.2 resolution: "linkify-it@npm:3.0.2" @@ -28244,6 +28338,13 @@ __metadata: languageName: node linkType: hard +"luxon@npm:^2.0.2": + version: 2.5.2 + resolution: "luxon@npm:2.5.2" + checksum: d8b671ffd2ff0b438af862ac11082a81b3aedd9f8b6a4ca636f944224f8dd381125cd4d274ca0a8aedcaf2cfca0fc2ca96fe4cc1b16a28b7af701afb95c0bff8 + languageName: node + linkType: hard + "luxon@npm:^3.0.0, luxon@npm:^3.2.1": version: 3.2.1 resolution: "luxon@npm:3.2.1" @@ -35075,6 +35176,13 @@ __metadata: languageName: node linkType: hard +"slugify@npm:^1.6.4": + version: 1.6.5 + resolution: "slugify@npm:1.6.5" + checksum: a955a1b600201030f4c1daa9bb74a17d4402a0693fc40978bbd17e44e64fd72dad3bac4037422aa8aed55b5170edd57f3f4cd8f59ba331f5cf0f10f1a7795609 + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" From bb1cfedc3399b4c7ab4ef23cd3f51b8a18ce0084 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Wed, 8 Feb 2023 15:55:50 -0600 Subject: [PATCH 116/417] Refactor age to use HumanDuration Signed-off-by: Andre Wanlin --- packages/backend/src/plugins/linguist.ts | 1 + plugins/linguist-backend/README.md | 18 +++++++++---- plugins/linguist-backend/api-report.md | 4 +++ plugins/linguist-backend/config.d.ts | 27 ------------------- plugins/linguist-backend/package.json | 5 ++-- .../src/api/LinguistBackendApi.ts | 6 +++-- .../linguist-backend/src/service/router.ts | 15 +++++++++-- yarn.lock | 1 + 8 files changed, 38 insertions(+), 39 deletions(-) delete mode 100644 plugins/linguist-backend/config.d.ts diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index d8e56f658b..85bf3a72ec 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -36,5 +36,6 @@ export default async function createPlugin( database: env.database, scheduler: env.scheduler, schedule: schedule, + age: { days: 30 }, }); } diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index d3c39a5fe7..0ad585dedd 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -79,14 +79,22 @@ const schedule: TaskScheduleDefinition = { }; ``` -The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the following configuration to your `app-config.yaml`: +The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` in your `packages/backend/src/plugins/linguist.ts`: -```yaml -linguist: - age: 15 # Days +```diff + return createRouter({ + logger: env.logger, + config: env.config, + reader: env.reader, + discovery: env.discovery, + database: env.database, + scheduler: env.scheduler, + schedule: schedule, ++ age: { days: 15 }, + }); ``` -With the configuration setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. +With the `age` setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. ## Links diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 26656416df..3524c02611 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -7,6 +7,7 @@ import { Config } from '@backstage/config'; import { EntitiesOverview } from '@backstage/plugin-linguist-common'; import { EntityResults } from '@backstage/plugin-linguist-common'; import express from 'express'; +import { HumanDuration } from '@backstage/types'; import { Knex } from 'knex'; import { Languages } from '@backstage/plugin-linguist-common'; import { Logger } from 'winston'; @@ -28,6 +29,7 @@ export class LinguistBackendApi { store: LinguistBackendStore, urlReader: UrlReader, discovery: PluginEndpointDiscovery, + age?: HumanDuration | undefined, ); // (undocumented) getEntitiesOverview(): Promise; @@ -64,6 +66,8 @@ export interface LinguistBackendStore { // @public (undocumented) export interface RouterOptions { + // (undocumented) + age?: HumanDuration; // (undocumented) config: Config; // (undocumented) diff --git a/plugins/linguist-backend/config.d.ts b/plugins/linguist-backend/config.d.ts deleted file mode 100644 index 8e0133c90b..0000000000 --- a/plugins/linguist-backend/config.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2022 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 interface Config { - /** Configuration options for the linguist-backend plugin */ - linguist?: { - /** - * The age of an entity's languages before a refresh occurs, - * an age of 30 would mean the languages would be regenerated after 30 days. - * The default is 0 meaning languages won't be refreshed once generated. - */ - age: number; - }; -} diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index b79a97decd..b1bf7be071 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -30,6 +30,7 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-linguist-common": "workspace:^", + "@backstage/types": "workspace:^", "@types/express": "*", "express": "^4.18.1", "express-promise-router": "^4.1.0", @@ -50,8 +51,6 @@ }, "files": [ "dist", - "config.d.ts", "migrations/**/*.{js,d.ts}" - ], - "configSchema": "config.d.ts" + ] } diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index fdabea6d6c..816d731d7f 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -36,6 +36,7 @@ import fs from 'fs-extra'; import linguist from 'linguist-js'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; +import { HumanDuration } from '@backstage/types'; /** @public */ export class LinguistBackendApi { @@ -45,6 +46,7 @@ export class LinguistBackendApi { private readonly store: LinguistBackendStore, private readonly urlReader: UrlReader, private readonly discovery: PluginEndpointDiscovery, + private readonly age?: HumanDuration, ) {} public async getEntityLanguages(entityRef: string): Promise { @@ -148,8 +150,8 @@ export class LinguistBackendApi { const processedEntities = await this.store.getProcessedEntities(); const staleEntities = processedEntities.filter(pe => { - if (age === 0) return false; - const staleDate = DateTime.now().minus({ days: age }); + if (age === undefined) return false; + const staleDate = DateTime.now().minus(this.age as HumanDuration); return DateTime.fromJSDate(pe.processed_date) >= staleDate; }); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 091b7f408d..122cb939e3 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -30,6 +30,7 @@ import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; +import { HumanDuration } from '@backstage/types'; /** @public */ export interface RouterOptions { @@ -41,14 +42,23 @@ export interface RouterOptions { discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; schedule?: TaskScheduleDefinition; + age?: HumanDuration; } /** @public */ export async function createRouter( options: RouterOptions, ): Promise { - const { config, logger, reader, database, discovery, scheduler, schedule } = - options; + const { + config, + logger, + reader, + database, + discovery, + scheduler, + schedule, + age, + } = options; const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), @@ -62,6 +72,7 @@ export async function createRouter( linguistBackendStore, reader, discovery, + age, ); if (scheduler && schedule) { diff --git a/yarn.lock b/yarn.lock index 9697e098ce..9dd67caa8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6908,6 +6908,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-linguist-common": "workspace:^" + "@backstage/types": "workspace:^" "@types/express": "*" "@types/supertest": ^2.0.8 express: ^4.18.1 From d327896ecbb5524f3c413dcdfe46c5ceadc8daa1 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Wed, 8 Feb 2023 17:08:51 -0600 Subject: [PATCH 117/417] Refactored createRouter args Signed-off-by: Andre Wanlin --- packages/backend/src/plugins/linguist.ts | 11 +------- plugins/linguist-backend/README.md | 25 +++-------------- plugins/linguist-backend/api-report.md | 15 ++++++++--- .../src/service/router.test.ts | 26 ++++++++++++------ .../linguist-backend/src/service/router.ts | 27 +++++++++---------- .../src/service/standaloneServer.ts | 24 ++++++++++++----- 6 files changed, 64 insertions(+), 64 deletions(-) diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index 85bf3a72ec..948ca7fbb5 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -28,14 +28,5 @@ export default async function createPlugin( initialDelay: { seconds: 15 }, }; - return createRouter({ - logger: env.logger, - config: env.config, - reader: env.reader, - discovery: env.discovery, - database: env.database, - scheduler: env.scheduler, - schedule: schedule, - age: { days: 30 }, - }); + return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); } diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index 0ad585dedd..c42112b694 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -36,15 +36,7 @@ Here's how to get the backend up and running: initialDelay: { seconds: 90 }, }; - return createRouter({ - logger: env.logger, - config: env.config, - reader: env.reader, - discovery: env.discovery, - database: env.database, - scheduler: env.scheduler, - schedule: schedule, - }); + return createRouter({ schedule: schedule }, { ...env }); } ``` @@ -79,19 +71,10 @@ const schedule: TaskScheduleDefinition = { }; ``` -The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` in your `packages/backend/src/plugins/linguist.ts`: +The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` (as a `HumanDuration`) in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: -```diff - return createRouter({ - logger: env.logger, - config: env.config, - reader: env.reader, - discovery: env.discovery, - database: env.database, - scheduler: env.scheduler, - schedule: schedule, -+ age: { days: 15 }, - }); +```ts +return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); ``` With the `age` setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 3524c02611..3fd2823815 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -19,7 +19,10 @@ import { TaskScheduleDefinition } from '@backstage/backend-tasks'; import { UrlReader } from '@backstage/backend-common'; // @public (undocumented) -export function createRouter(options: RouterOptions): Promise; +export function createRouter( + pluginOptions: PluginOptions, + routerOptions: RouterOptions, +): Promise; // @public (undocumented) export class LinguistBackendApi { @@ -65,9 +68,15 @@ export interface LinguistBackendStore { } // @public (undocumented) -export interface RouterOptions { +export interface PluginOptions { // (undocumented) age?: HumanDuration; + // (undocumented) + schedule?: TaskScheduleDefinition; +} + +// @public (undocumented) +export interface RouterOptions { // (undocumented) config: Config; // (undocumented) @@ -81,8 +90,6 @@ export interface RouterOptions { // (undocumented) reader: UrlReader; // (undocumented) - schedule?: TaskScheduleDefinition; - // (undocumented) scheduler?: PluginTaskScheduler; } diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index 0e20987a43..1de162c97a 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -26,6 +26,7 @@ import request from 'supertest'; import { ConfigReader } from '@backstage/config'; import { createRouter } from './router'; import { LinguistBackendApi } from '../api'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; function createDatabase(): PluginDatabaseManager { return DatabaseManager.fromConfig( @@ -52,19 +53,28 @@ const mockUrlReader = UrlReaders.default({ config: new ConfigReader({}), }); +const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, +}; + describe('createRouter', () => { let linguistBackendApi: jest.Mocked; let app: express.Express; beforeAll(async () => { - const router = await createRouter({ - linguistBackendApi, - config: new ConfigReader({}), - discovery: testDiscovery, - database: createDatabase(), - reader: mockUrlReader, - logger: getVoidLogger(), - }); + const router = await createRouter( + { schedule: schedule, age: { days: 30 } }, + { + linguistBackendApi, + config: new ConfigReader({}), + discovery: testDiscovery, + database: createDatabase(), + reader: mockUrlReader, + logger: getVoidLogger(), + }, + ); app = express().use(router); }); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 122cb939e3..8cf426f2b3 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -32,6 +32,12 @@ import { } from '@backstage/backend-tasks'; import { HumanDuration } from '@backstage/types'; +/** @public */ +export interface PluginOptions { + schedule?: TaskScheduleDefinition; + age?: HumanDuration; +} + /** @public */ export interface RouterOptions { linguistBackendApi?: LinguistBackendApi; @@ -41,31 +47,24 @@ export interface RouterOptions { database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; - schedule?: TaskScheduleDefinition; - age?: HumanDuration; } /** @public */ export async function createRouter( - options: RouterOptions, + pluginOptions: PluginOptions, + routerOptions: RouterOptions, ): Promise { - const { - config, - logger, - reader, - database, - discovery, - scheduler, - schedule, - age, - } = options; + const { schedule, age } = pluginOptions; + + const { config, logger, reader, database, discovery, scheduler } = + routerOptions; const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), ); const linguistBackendApi = - options.linguistBackendApi || + routerOptions.linguistBackendApi || new LinguistBackendApi( config, logger, diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 5578c20e95..874806e788 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -25,6 +25,7 @@ import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; import knexFactory from 'knex'; +import { TaskScheduleDefinition } from '@backstage/backend-tasks'; export interface ServerOptions { port: number; @@ -51,14 +52,23 @@ export async function startStandaloneServer( return knex; }); + const schedule: TaskScheduleDefinition = { + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, + initialDelay: { seconds: 15 }, + }; + logger.debug('Starting application server...'); - const router = await createRouter({ - database: { getClient: async () => db }, - config, - discovery: SingleHostDiscovery.fromConfig(config), - reader: UrlReaders.default({ logger, config }), - logger, - }); + const router = await createRouter( + { schedule: schedule, age: { days: 30 } }, + { + database: { getClient: async () => db }, + config, + discovery: SingleHostDiscovery.fromConfig(config), + reader: UrlReaders.default({ logger, config }), + logger, + }, + ); let service = createServiceBuilder(module) .setPort(options.port) From 54f08f8bd9671bb87bf5b0932856bc1fd6dc25c5 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Thu, 9 Feb 2023 14:58:01 -0600 Subject: [PATCH 118/417] Refactored processing Signed-off-by: Andre Wanlin --- packages/backend/src/plugins/linguist.ts | 10 +- plugins/linguist-backend/README.md | 33 +++-- plugins/linguist-backend/api-report.md | 24 ++- .../migrations/20221115_init.js | 6 +- .../src/api/LinguistBackendApi.ts | 140 +++++++++++------- .../src/db/LinguistBackendDatabase.ts | 56 ++++++- .../src/service/router.test.ts | 3 +- .../linguist-backend/src/service/router.ts | 12 +- .../src/service/standaloneServer.ts | 3 +- plugins/linguist-common/api-report.md | 6 +- plugins/linguist-common/package.json | 4 - plugins/linguist-common/src/types.ts | 5 +- yarn.lock | 2 - 13 files changed, 199 insertions(+), 105 deletions(-) diff --git a/packages/backend/src/plugins/linguist.ts b/packages/backend/src/plugins/linguist.ts index 948ca7fbb5..2c8713a7e3 100644 --- a/packages/backend/src/plugins/linguist.ts +++ b/packages/backend/src/plugins/linguist.ts @@ -28,5 +28,13 @@ export default async function createPlugin( initialDelay: { seconds: 15 }, }; - return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); + return createRouter( + { + schedule: schedule, + age: { days: 30 }, + batchSize: 2, + useSourceLocation: false, + }, + { ...env }, + ); } diff --git a/plugins/linguist-backend/README.md b/plugins/linguist-backend/README.md index c42112b694..cd63f5db03 100644 --- a/plugins/linguist-backend/README.md +++ b/plugins/linguist-backend/README.md @@ -31,8 +31,8 @@ Here's how to get the backend up and running: env: PluginEnvironment, ): Promise { const schedule: TaskScheduleDefinition = { - frequency: { hours: 24 }, - timeout: { minutes: 30 }, + frequency: { minutes: 2 }, + timeout: { minutes: 15 }, initialDelay: { seconds: 90 }, }; @@ -57,20 +57,18 @@ Here's how to get the backend up and running: 4. Now run `yarn start-backend` from the repo root 5. Finally open `http://localhost:7007/api/linguist/health` in a browser and it should return `{"status":"ok"}` -## Scheduling +## Batch Size -The Linguist backend can be configured to generate the language breakdown for all the entities with the linguist annotation. This is done by passing a `TaskScheduleDefinition` to the `createRouter` function like in Step 2 of the [Up and Running](#up-and-running) documentation. - -Here's another example of the `TaskScheduleDefinition` that will run the language breakdown processing every 12 hours: +The Linguist backend is setup to process entities by acting as a queue where it will pull down all the applicable entities from the Catalog and add them to it's database (saving just the `entityRef`). Then it will grab the `n` oldest entities that have not been processed to determine their languages and process them. To control the batch size simply provide that to the `createRouter` function in your `packages/backend/src/plugins/linguist.ts` like this: ```ts -const schedule: TaskScheduleDefinition = { - frequency: { hours: 12 }, - timeout: { minutes: 15 }, - initialDelay: { seconds: 10 }, -}; +return createRouter({ schedule: schedule, batchSize: 40 }, { ...env }); ``` +**Note:** The default batch size is 20 + +## Refresh + The default setup will only generate the language breakdown for entities with the linguist annotation that have not been generated yet. If you want this process to also refresh the data you can do so by adding the `age` (as a `HumanDuration`) in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: ```ts @@ -79,6 +77,19 @@ return createRouter({ schedule: schedule, age: { days: 30 } }, { ...env }); With the `age` setup like this if the language breakdown is older than 15 days it will get regenerated. It's recommended that if you choose to use this configuration to set it to a large value - 30, 90, or 180 - as this data generally does not change drastically. +## Use Source Location + +You may wish to use the `backstage.io/source-location` annotation over using the `backstage.io/linguist` as you may not be able to quickly add that annotation to your Entities. To do this you'll just need to set the `useSourceLocation` boolean to `true` in your `packages/backend/src/plugins/linguist.ts` when you call `createRouter`: + +```ts +return createRouter( + { schedule: schedule, useSourceLocation: true }, + { ...env }, +); +``` + +**Note:** This has the potential to cause a lot of processing, be very thoughtful about this before hand + ## Links - [Frontend part of the plugin](../linguist/README.md) diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 3fd2823815..484998b099 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { Config } from '@backstage/config'; import { EntitiesOverview } from '@backstage/plugin-linguist-common'; import { EntityResults } from '@backstage/plugin-linguist-common'; import express from 'express'; @@ -27,12 +26,13 @@ export function createRouter( // @public (undocumented) export class LinguistBackendApi { constructor( - config: Config, logger: Logger, store: LinguistBackendStore, urlReader: UrlReader, discovery: PluginEndpointDiscovery, - age?: HumanDuration | undefined, + age?: HumanDuration, + batchSize?: number, + useSourceLocation?: boolean, ); // (undocumented) getEntitiesOverview(): Promise; @@ -52,9 +52,13 @@ export class LinguistBackendDatabase implements LinguistBackendStore { // (undocumented) getEntityResults(entityRef: string): Promise; // (undocumented) - getProcessedEntities(): Promise; + getProcessedEntities(): Promise; + // (undocumented) + getUnprocessedEntities(): Promise; // (undocumented) insertEntityResults(entityLanguages: EntityResults): Promise; + // (undocumented) + insertNewEntity(entityRef: string): Promise; } // @public (undocumented) @@ -62,9 +66,13 @@ export interface LinguistBackendStore { // (undocumented) getEntityResults(entityRef: string): Promise; // (undocumented) - getProcessedEntities(): Promise; + getProcessedEntities(): Promise; + // (undocumented) + getUnprocessedEntities(): Promise; // (undocumented) insertEntityResults(entityLanguages: EntityResults): Promise; + // (undocumented) + insertNewEntity(entityRef: string): Promise; } // @public (undocumented) @@ -72,13 +80,15 @@ export interface PluginOptions { // (undocumented) age?: HumanDuration; // (undocumented) + batchSize?: number; + // (undocumented) schedule?: TaskScheduleDefinition; + // (undocumented) + useSourceLocation?: boolean; } // @public (undocumented) export interface RouterOptions { - // (undocumented) - config: Config; // (undocumented) database: PluginDatabaseManager; // (undocumented) diff --git a/plugins/linguist-backend/migrations/20221115_init.js b/plugins/linguist-backend/migrations/20221115_init.js index 9eb0a03a90..3bcf99e08b 100644 --- a/plugins/linguist-backend/migrations/20221115_init.js +++ b/plugins/linguist-backend/migrations/20221115_init.js @@ -36,10 +36,7 @@ exports.up = async function up(knex) { .unique() .notNullable() .comment('The entity ref that this Linguist result applies to'); - table - .text('languages') - .notNullable() - .comment('The results json as a string'); + table.text('languages').comment('The results json as a string'); table .dateTime('created_at') .defaultTo(knex.fn.now()) @@ -48,7 +45,6 @@ exports.up = async function up(knex) { table .dateTime('processed_date') .defaultTo(knex.fn.now()) - .notNullable() .comment('The timestamp when this entity was processed'); table.index('index', 'entity_result_index_idx'); table.index('entity_ref', 'entity_result_entity_ref_idx'); diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index 816d731d7f..a5bbc5e639 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -27,27 +27,48 @@ import { } from '@backstage/catalog-client'; import { PluginEndpointDiscovery, UrlReader } from '@backstage/backend-common'; -import { Config } from '@backstage/config'; import { DateTime } from 'luxon'; import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; import { LinguistBackendStore } from '../db'; import { Logger } from 'winston'; import fs from 'fs-extra'; import linguist from 'linguist-js'; -import { stringifyEntityRef } from '@backstage/catalog-model'; +import { + ANNOTATION_SOURCE_LOCATION, + stringifyEntityRef, +} from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; import { HumanDuration } from '@backstage/types'; /** @public */ export class LinguistBackendApi { + private readonly logger: Logger; + private readonly store: LinguistBackendStore; + private readonly urlReader: UrlReader; + private readonly discovery: PluginEndpointDiscovery; + private readonly catalogClient: CatalogClient; + private readonly age?: HumanDuration; + private readonly batchSize?: number; + private readonly useSourceLocation?: boolean; public constructor( - private readonly config: Config, - private readonly logger: Logger, - private readonly store: LinguistBackendStore, - private readonly urlReader: UrlReader, - private readonly discovery: PluginEndpointDiscovery, - private readonly age?: HumanDuration, - ) {} + logger: Logger, + store: LinguistBackendStore, + urlReader: UrlReader, + discovery: PluginEndpointDiscovery, + age?: HumanDuration, + batchSize?: number, + useSourceLocation?: boolean, + ) { + this.logger = logger; + this.store = store; + this.urlReader = urlReader; + this.discovery = discovery; + this.catalogClient = new CatalogClient({ discoveryApi: this.discovery }); + + this.batchSize = batchSize; + this.age = age; + this.useSourceLocation = useSourceLocation; + } public async getEntityLanguages(entityRef: string): Promise { this.logger?.debug(`Getting languages for entity "${entityRef}"`); @@ -105,65 +126,59 @@ export class LinguistBackendApi { } public async processEntities() { + this.logger?.info('Updating list of entities'); + + await this.addNewEntities(); + this.logger?.info('Processing applicable entities through Linguist'); - const eo = await this.getEntitiesOverview(); + const entitiesOverview = await this.getEntitiesOverview(); this.logger?.info( - `Entities overview: Entity: ${eo.entityCount}, Processed: ${eo.processedCount}, Pending: ${eo.pendingCount}, Stale ${eo.staleCount}`, + `Entities overview: Entity: ${entitiesOverview.entityCount}, Processed: ${entitiesOverview.processedCount}, Pending: ${entitiesOverview.pendingCount}, Stale ${entitiesOverview.staleCount}`, ); - const entities = eo.filteredEntities; - for (const key in entities) { - if (Object.prototype.hasOwnProperty.call(entities, key)) { - const entityRef = stringifyEntityRef(entities[key]); + const entities = entitiesOverview.filteredEntities.slice( + this.batchSize ?? 20, + ); + entities.forEach(async entityRef => { + const entity = await this.catalogClient.getEntityByRef(entityRef); + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; - const url = - entities[key].metadata.annotations?.[LINGUIST_ANNOTATION] ?? ''; - - try { - await this.processEntity(entityRef, url); - } catch (e) { - assertError(e); - this.logger.error( - `Unable to process "${entityRef}" using "${url}", ${e.message}`, - ); - } + let url = entity?.metadata.annotations?.[annotationKey] ?? ''; + if (url.startsWith('url:')) { + url = url.slice(4); } - } + + try { + await this.processEntity(entityRef, url); + } catch (error) { + assertError(error); + this.logger.error( + `Unable to process "${entityRef}" using "${url}", message: ${error.message}, stack: ${error.stack}`, + ); + } + }); } public async getEntitiesOverview(): Promise { this.logger?.debug('Getting pending entities'); - const age = this.config.getOptionalNumber('linguist.age') ?? 0; - const catalogApi = new CatalogClient({ discoveryApi: this.discovery }); - const request: GetEntitiesRequest = { - filter: { - kind: ['API', 'Component', 'Template'], - [`metadata.annotations.${LINGUIST_ANNOTATION}`]: CATALOG_FILTER_EXISTS, - }, - fields: ['kind', 'metadata'], - }; - - const response = await catalogApi.getEntities(request); - const entities = response.items; const processedEntities = await this.store.getProcessedEntities(); + const staleEntities = processedEntities + .filter(pe => { + if (this.age === undefined) return false; + const staleDate = DateTime.now().minus(this.age as HumanDuration); + return DateTime.fromJSDate(pe.processedDate) <= staleDate; + }) + .map(pe => pe.entityRef); - const staleEntities = processedEntities.filter(pe => { - if (age === undefined) return false; - const staleDate = DateTime.now().minus(this.age as HumanDuration); - return DateTime.fromJSDate(pe.processed_date) >= staleDate; - }); - - const filteredEntities = entities.filter(en => { - return processedEntities.every(pe => { - const entityRef = stringifyEntityRef(en); - return pe.entityRef !== entityRef; - }); - }); + const unprocessedEntities = await this.store.getUnprocessedEntities(); + const filteredEntities = staleEntities.concat(unprocessedEntities); const entitiesOverview: EntitiesOverview = { - entityCount: entities.length, + entityCount: unprocessedEntities.length, processedCount: processedEntities.length, staleCount: staleEntities.length, pendingCount: filteredEntities.length, @@ -172,4 +187,25 @@ export class LinguistBackendApi { return entitiesOverview; } + + private async addNewEntities() { + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; + const request: GetEntitiesRequest = { + filter: { + kind: ['API', 'Component', 'Template'], + [`metadata.annotations.${annotationKey}`]: CATALOG_FILTER_EXISTS, + }, + fields: ['kind', 'metadata'], + }; + + const response = await this.catalogClient.getEntities(request); + const entities = response.items; + + entities.forEach(entity => { + const entityRef = stringifyEntityRef(entity); + this.store.insertNewEntity(entityRef); + }); + } } diff --git a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts index 8faa5c3ff0..cf93374800 100644 --- a/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts +++ b/plugins/linguist-backend/src/db/LinguistBackendDatabase.ts @@ -33,8 +33,10 @@ export type RawDbEntityResultRow = { /** @public */ export interface LinguistBackendStore { insertEntityResults(entityLanguages: EntityResults): Promise; + insertNewEntity(entityRef: string): Promise; getEntityResults(entityRef: string): Promise; - getProcessedEntities(): Promise; + getProcessedEntities(): Promise; + getUnprocessedEntities(): Promise; } const migrationsDir = resolvePackagePath( @@ -71,8 +73,21 @@ export class LinguistBackendDatabase implements LinguistBackendStore { return result.id; } + async insertNewEntity(entityRef: string): Promise { + const entityLanguageId = uuid(); + + await this.db('entity_result') + .insert({ + id: entityLanguageId, + entity_ref: entityRef, + }) + .onConflict('entity_ref') + .ignore(); // If the entity_ref is in the table already then we don't want to add it again + } + async getEntityResults(entityRef: string): Promise { const entityResults = await this.db('entity_result') + .whereNotNull('languages') .where({ entity_ref: entityRef }) .first(); @@ -93,11 +108,40 @@ export class LinguistBackendDatabase implements LinguistBackendStore { } } - async getProcessedEntities(): Promise { - const entityResults = await this.db( - 'entity_result', - ).select('entity_ref', 'processed_date'); + async getProcessedEntities(): Promise { + const rawEntities = await this.db('entity_result') + .whereNotNull('processed_date') + .whereNotNull('languages'); - return entityResults; + if (!rawEntities) { + return []; + } + + const processedEntities = rawEntities.map(rawEntity => { + const processEntity = { + entityRef: rawEntity.entity_ref, + processedDate: rawEntity.processed_date, + }; + + return processEntity; + }); + + return processedEntities; + } + + async getUnprocessedEntities(): Promise { + const rawEntities = await this.db('entity_result') + .whereNull('languages') + .orderBy('created_at', 'asc'); + + if (!rawEntities) { + return []; + } + + const unprocessedEntities = rawEntities.map(rawEntity => { + return rawEntity.entity_ref; + }); + + return unprocessedEntities; } } diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index 1de162c97a..34f16f4b21 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -65,10 +65,9 @@ describe('createRouter', () => { beforeAll(async () => { const router = await createRouter( - { schedule: schedule, age: { days: 30 } }, + { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, { linguistBackendApi, - config: new ConfigReader({}), discovery: testDiscovery, database: createDatabase(), reader: mockUrlReader, diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index 8cf426f2b3..e3aeec604e 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -20,7 +20,6 @@ import { PluginEndpointDiscovery, UrlReader, } from '@backstage/backend-common'; -import { Config } from '@backstage/config'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; @@ -36,12 +35,13 @@ import { HumanDuration } from '@backstage/types'; export interface PluginOptions { schedule?: TaskScheduleDefinition; age?: HumanDuration; + batchSize?: number; + useSourceLocation?: boolean; } /** @public */ export interface RouterOptions { linguistBackendApi?: LinguistBackendApi; - config: Config; logger: Logger; reader: UrlReader; database: PluginDatabaseManager; @@ -54,10 +54,9 @@ export async function createRouter( pluginOptions: PluginOptions, routerOptions: RouterOptions, ): Promise { - const { schedule, age } = pluginOptions; + const { schedule, age, batchSize, useSourceLocation } = pluginOptions; - const { config, logger, reader, database, discovery, scheduler } = - routerOptions; + const { logger, reader, database, discovery, scheduler } = routerOptions; const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), @@ -66,12 +65,13 @@ export async function createRouter( const linguistBackendApi = routerOptions.linguistBackendApi || new LinguistBackendApi( - config, logger, linguistBackendStore, reader, discovery, age, + batchSize, + useSourceLocation, ); if (scheduler && schedule) { diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 874806e788..828c83630a 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -60,10 +60,9 @@ export async function startStandaloneServer( logger.debug('Starting application server...'); const router = await createRouter( - { schedule: schedule, age: { days: 30 } }, + { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, { database: { getClient: async () => db }, - config, discovery: SingleHostDiscovery.fromConfig(config), reader: UrlReaders.default({ logger, config }), logger, diff --git a/plugins/linguist-common/api-report.md b/plugins/linguist-common/api-report.md index a9eceb3839..954bef7904 100644 --- a/plugins/linguist-common/api-report.md +++ b/plugins/linguist-common/api-report.md @@ -3,15 +3,13 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { Entity } from '@backstage/catalog-model'; - // @public (undocumented) export type EntitiesOverview = { entityCount: number; processedCount: number; pendingCount: number; staleCount: number; - filteredEntities: Entity[]; + filteredEntities: string[]; }; // @public (undocumented) @@ -43,7 +41,7 @@ export const LINGUIST_ANNOTATION = 'backstage.io/linguist'; // @public (undocumented) export type ProcessedEntity = { entityRef: string; - processed_date: Date; + processedDate: Date; }; // (No @packageDocumentation comment for this package) diff --git a/plugins/linguist-common/package.json b/plugins/linguist-common/package.json index eddc114a67..116f785216 100644 --- a/plugins/linguist-common/package.json +++ b/plugins/linguist-common/package.json @@ -22,10 +22,6 @@ "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack" }, - "dependencies": { - "@backstage/catalog-model": "workspace:^", - "@backstage/plugin-permission-common": "workspace:^" - }, "devDependencies": { "@backstage/cli": "workspace:^" }, diff --git a/plugins/linguist-common/src/types.ts b/plugins/linguist-common/src/types.ts index 01222492b6..28a25ed059 100644 --- a/plugins/linguist-common/src/types.ts +++ b/plugins/linguist-common/src/types.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; /** @public */ export type EntityResults = { @@ -41,7 +40,7 @@ export type Language = { /** @public */ export type ProcessedEntity = { entityRef: string; - processed_date: Date; + processedDate: Date; }; /** @public */ @@ -50,5 +49,5 @@ export type EntitiesOverview = { processedCount: number; pendingCount: number; staleCount: number; - filteredEntities: Entity[]; + filteredEntities: string[]; }; diff --git a/yarn.lock b/yarn.lock index 9dd67caa8b..4120623904 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6930,9 +6930,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-linguist-common@workspace:plugins/linguist-common" dependencies: - "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" - "@backstage/plugin-permission-common": "workspace:^" languageName: unknown linkType: soft From 672eade89960801ea392167c86a6d5f664ec1277 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 11 Feb 2023 14:57:08 -0600 Subject: [PATCH 119/417] Organized backend API Signed-off-by: Andre Wanlin --- .../src/api/LinguistBackendApi.ts | 177 +++++++++--------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index a5bbc5e639..34d04b02f9 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -76,7 +76,98 @@ export class LinguistBackendApi { return this.store.getEntityResults(entityRef); } - public async processEntity(entityRef: string, url: string): Promise { + public async processEntities() { + this.logger?.info('Updating list of entities'); + + await this.addNewEntities(); + + this.logger?.info('Processing applicable entities through Linguist'); + + await this.generateEntitiesLanguages(); + } + + private async addNewEntities() { + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; + const request: GetEntitiesRequest = { + filter: { + kind: ['API', 'Component', 'Template'], + [`metadata.annotations.${annotationKey}`]: CATALOG_FILTER_EXISTS, + }, + fields: ['kind', 'metadata'], + }; + + const response = await this.catalogClient.getEntities(request); + const entities = response.items; + + entities.forEach(entity => { + const entityRef = stringifyEntityRef(entity); + this.store.insertNewEntity(entityRef); + }); + } + + private async generateEntitiesLanguages() { + const entitiesOverview = await this.getEntitiesOverview(); + this.logger?.info( + `Entities overview: Entity: ${entitiesOverview.entityCount}, Processed: ${entitiesOverview.processedCount}, Pending: ${entitiesOverview.pendingCount}, Stale ${entitiesOverview.staleCount}`, + ); + + const entities = entitiesOverview.filteredEntities.slice( + this.batchSize ?? 20, + ); + entities.forEach(async entityRef => { + const entity = await this.catalogClient.getEntityByRef(entityRef); + const annotationKey = this.useSourceLocation + ? ANNOTATION_SOURCE_LOCATION + : LINGUIST_ANNOTATION; + + let url = entity?.metadata.annotations?.[annotationKey] ?? ''; + if (url.startsWith('url:')) { + url = url.slice(4); + } + + try { + await this.generateEntityLanguages(entityRef, url); + } catch (error) { + assertError(error); + this.logger.error( + `Unable to process "${entityRef}" using "${url}", message: ${error.message}, stack: ${error.stack}`, + ); + } + }); + } + + private async getEntitiesOverview(): Promise { + this.logger?.debug('Getting pending entities'); + + const processedEntities = await this.store.getProcessedEntities(); + const staleEntities = processedEntities + .filter(pe => { + if (this.age === undefined) return false; + const staleDate = DateTime.now().minus(this.age as HumanDuration); + return DateTime.fromJSDate(pe.processedDate) <= staleDate; + }) + .map(pe => pe.entityRef); + + const unprocessedEntities = await this.store.getUnprocessedEntities(); + const filteredEntities = staleEntities.concat(unprocessedEntities); + + const entitiesOverview: EntitiesOverview = { + entityCount: unprocessedEntities.length, + processedCount: processedEntities.length, + staleCount: staleEntities.length, + pendingCount: filteredEntities.length, + filteredEntities: filteredEntities, + }; + + return entitiesOverview; + } + + private async generateEntityLanguages( + entityRef: string, + url: string, + ): Promise { this.logger?.info( `Processing languages for entity ${entityRef} from ${url}`, ); @@ -124,88 +215,4 @@ export class LinguistBackendApi { await fs.remove(dir); } } - - public async processEntities() { - this.logger?.info('Updating list of entities'); - - await this.addNewEntities(); - - this.logger?.info('Processing applicable entities through Linguist'); - - const entitiesOverview = await this.getEntitiesOverview(); - this.logger?.info( - `Entities overview: Entity: ${entitiesOverview.entityCount}, Processed: ${entitiesOverview.processedCount}, Pending: ${entitiesOverview.pendingCount}, Stale ${entitiesOverview.staleCount}`, - ); - - const entities = entitiesOverview.filteredEntities.slice( - this.batchSize ?? 20, - ); - entities.forEach(async entityRef => { - const entity = await this.catalogClient.getEntityByRef(entityRef); - const annotationKey = this.useSourceLocation - ? ANNOTATION_SOURCE_LOCATION - : LINGUIST_ANNOTATION; - - let url = entity?.metadata.annotations?.[annotationKey] ?? ''; - if (url.startsWith('url:')) { - url = url.slice(4); - } - - try { - await this.processEntity(entityRef, url); - } catch (error) { - assertError(error); - this.logger.error( - `Unable to process "${entityRef}" using "${url}", message: ${error.message}, stack: ${error.stack}`, - ); - } - }); - } - - public async getEntitiesOverview(): Promise { - this.logger?.debug('Getting pending entities'); - - const processedEntities = await this.store.getProcessedEntities(); - const staleEntities = processedEntities - .filter(pe => { - if (this.age === undefined) return false; - const staleDate = DateTime.now().minus(this.age as HumanDuration); - return DateTime.fromJSDate(pe.processedDate) <= staleDate; - }) - .map(pe => pe.entityRef); - - const unprocessedEntities = await this.store.getUnprocessedEntities(); - const filteredEntities = staleEntities.concat(unprocessedEntities); - - const entitiesOverview: EntitiesOverview = { - entityCount: unprocessedEntities.length, - processedCount: processedEntities.length, - staleCount: staleEntities.length, - pendingCount: filteredEntities.length, - filteredEntities: filteredEntities, - }; - - return entitiesOverview; - } - - private async addNewEntities() { - const annotationKey = this.useSourceLocation - ? ANNOTATION_SOURCE_LOCATION - : LINGUIST_ANNOTATION; - const request: GetEntitiesRequest = { - filter: { - kind: ['API', 'Component', 'Template'], - [`metadata.annotations.${annotationKey}`]: CATALOG_FILTER_EXISTS, - }, - fields: ['kind', 'metadata'], - }; - - const response = await this.catalogClient.getEntities(request); - const entities = response.items; - - entities.forEach(entity => { - const entityRef = stringifyEntityRef(entity); - this.store.insertNewEntity(entityRef); - }); - } } From 027d58f938e85f7e4b37c721643642e483ba76b4 Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 11 Feb 2023 15:02:12 -0600 Subject: [PATCH 120/417] Fixed ordering Signed-off-by: Andre Wanlin --- packages/app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/package.json b/packages/app/package.json index 8c26254268..f27afa2ff9 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -41,9 +41,9 @@ "@backstage/plugin-kafka": "workspace:^", "@backstage/plugin-kubernetes": "workspace:^", "@backstage/plugin-lighthouse": "workspace:^", - "@backstage/plugin-microsoft-calendar": "workspace:^", "@backstage/plugin-linguist": "workspace:^", "@backstage/plugin-linguist-common": "workspace:^", + "@backstage/plugin-microsoft-calendar": "workspace:^", "@backstage/plugin-newrelic": "workspace:^", "@backstage/plugin-newrelic-dashboard": "workspace:^", "@backstage/plugin-org": "workspace:^", From a021b247991bfe8a74c6934396e60fa89bbe57fe Mon Sep 17 00:00:00 2001 From: Andre Wanlin Date: Sat, 11 Feb 2023 15:05:30 -0600 Subject: [PATCH 121/417] Updated API Report Signed-off-by: Andre Wanlin --- plugins/linguist-backend/api-report.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index 484998b099..c11296b0b3 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { EntitiesOverview } from '@backstage/plugin-linguist-common'; import { EntityResults } from '@backstage/plugin-linguist-common'; import express from 'express'; import { HumanDuration } from '@backstage/types'; @@ -35,13 +34,9 @@ export class LinguistBackendApi { useSourceLocation?: boolean, ); // (undocumented) - getEntitiesOverview(): Promise; - // (undocumented) getEntityLanguages(entityRef: string): Promise; // (undocumented) processEntities(): Promise; - // (undocumented) - processEntity(entityRef: string, url: string): Promise; } // @public (undocumented) From 0a1f04170cfada36020728234182657dc0d6506c Mon Sep 17 00:00:00 2001 From: Charlie Chiang Date: Sun, 12 Feb 2023 21:13:48 +0800 Subject: [PATCH 122/417] Add kubevela to plugin marketplace Signed-off-by: Charlie Chiang --- microsite/data/plugins/kubevela.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 microsite/data/plugins/kubevela.yaml diff --git a/microsite/data/plugins/kubevela.yaml b/microsite/data/plugins/kubevela.yaml new file mode 100644 index 0000000000..524a046025 --- /dev/null +++ b/microsite/data/plugins/kubevela.yaml @@ -0,0 +1,15 @@ +--- +title: KubeVela +author: Charlie Chiang +authorUrl: https://github.com/charlie0129 +category: App Delivery +description: KubeVela is a modern software delivery platform that makes deploying and operating applications across today's hybrid, multi-cloud environments easier, faster and more reliable. +documentation: https://github.com/kubevela-contrib/backstage-plugin-kubevela +iconUrl: https://kubevela.io/img/logo.svg +npmPackageName: '@oamdev/plugin-kubevela-backend' +tags: + - cd + - delivery + - multi-cluster + - deployment as code +addedDate: '2023-02-12' From 0c1d0229aa6530dc7bf2fdaf18380c75e2a27a71 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 13 Feb 2023 13:46:03 +0100 Subject: [PATCH 123/417] remove not needed test dependencies Signed-off-by: Katharina Sick --- plugins/auth-backend/package.json | 2 -- .../src/providers/bitbucketServer/provider.test.ts | 5 ++--- plugins/auth-backend/src/setupTests.ts | 3 +-- yarn.lock | 4 +--- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 91fb5bed5b..a95465dbad 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -78,7 +78,6 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@testing-library/jest-dom": "^5.16.5", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", @@ -90,7 +89,6 @@ "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", - "cross-fetch": "^3.1.5", "msw": "^0.49.0", "supertest": "^6.1.3" }, diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts index 3934cafd36..1a661b82bc 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -15,7 +15,7 @@ */ import * as helpers from '../../lib/passport/PassportStrategyHelper'; -import { makeProfileInfo } from '../../lib/passport/PassportStrategyHelper'; +import { makeProfileInfo } from '../../lib/passport'; import { AuthResolverContext } from '../types'; import { bitbucketServer, @@ -24,10 +24,9 @@ import { } from './provider'; import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/test-utils'; -import { fetch } from 'cross-fetch'; import { rest } from 'msw'; -global.fetch = fetch; +global.fetch = require('node-fetch'); jest.mock('../../lib/passport/PassportStrategyHelper', () => { return { diff --git a/plugins/auth-backend/src/setupTests.ts b/plugins/auth-backend/src/setupTests.ts index c1d649f2ad..d3232290a7 100644 --- a/plugins/auth-backend/src/setupTests.ts +++ b/plugins/auth-backend/src/setupTests.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -import '@testing-library/jest-dom'; -import 'cross-fetch/polyfill'; +export {}; diff --git a/yarn.lock b/yarn.lock index 7bfbb5ea1f..1621cdc5b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4537,7 +4537,6 @@ __metadata: "@backstage/types": "workspace:^" "@davidzemon/passport-okta-oauth": ^0.0.5 "@google-cloud/firestore": ^6.0.0 - "@testing-library/jest-dom": ^5.16.5 "@types/body-parser": ^1.19.0 "@types/cookie-parser": ^1.4.2 "@types/express": ^4.17.6 @@ -4554,7 +4553,6 @@ __metadata: compression: ^1.7.4 cookie-parser: ^1.4.5 cors: ^2.8.5 - cross-fetch: ^3.1.5 express: ^4.17.1 express-promise-router: ^4.1.0 express-session: ^1.17.1 @@ -13580,7 +13578,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4, @testing-library/jest-dom@npm:^5.16.5": +"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4": version: 5.16.5 resolution: "@testing-library/jest-dom@npm:5.16.5" dependencies: From 006f84dc86d8cb18d8cef8b6600a41711724807a Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 13 Feb 2023 14:50:03 +0100 Subject: [PATCH 124/417] Updated the 'Debugging Jest Tests' section Signed-off-by: bnechyporenko --- docs/local-dev/cli-build-system.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index ba65bedb9f..bef0ef9d97 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -597,7 +597,11 @@ If you also want to enable source maps when debugging tests, you can do so by se ### Debugging Jest Tests -To configure the debugging of your tests in IntelliJ, you have to: +For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. + +Each of IDE has own way to set it up. We started with giving an example how to configure it in Intellij IDEA. In a near future we might also add the information for VS Code. + +#### Intellij IDEA 1. Update Jest configuration template by: From a8c0c0383e013a8a50b84678eab28baa475a87a6 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Mon, 13 Feb 2023 15:28:27 +0100 Subject: [PATCH 125/417] Updated the 'Debugging Jest Tests' section Signed-off-by: bnechyporenko --- docs/local-dev/cli-build-system.md | 39 +++++++++++++----------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index bef0ef9d97..ec0f3273fb 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -556,7 +556,22 @@ The overrides in a single `package.json` may for example look like this: }, ``` -If you want to configure editor integration for tests we recommend executing the bundled configuration directly with Jest rather than running through the Yarn test script. For example, with the Jest extension for VS Code the configuration would look something like this: +### Debugging Jest Tests + +For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. + +#### Intellij IDEA + +1. Update Jest configuration template by: + +- Click on "Edit Configurations" on top panel +- In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. +- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest +- In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` + +2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. + +#### VS Code ```jsonc { @@ -571,7 +586,7 @@ If you want to configure editor integration for tests we recommend executing the } ``` -If you also want to enable source maps when debugging tests, you can do so by setting the `ENABLE_SOURCE_MAPS` environment variable. For example, a complete launch configuration for VS Code debugging may look like this: +A complete launch configuration for VS Code debugging may look like this: ```json { @@ -583,9 +598,6 @@ If you also want to enable source maps when debugging tests, you can do so by se "disableOptimisticBPs": true, "program": "${workspaceFolder}/node_modules/.bin/jest", "cwd": "${workspaceFolder}", - "env": { - "ENABLE_SOURCE_MAPS": "true" - }, "args": [ "--config", "node_modules/@backstage/cli/config/jest.js", @@ -595,23 +607,6 @@ If you also want to enable source maps when debugging tests, you can do so by se } ``` -### Debugging Jest Tests - -For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. - -Each of IDE has own way to set it up. We started with giving an example how to configure it in Intellij IDEA. In a near future we might also add the information for VS Code. - -#### Intellij IDEA - -1. Update Jest configuration template by: - -- Click on "Edit Configurations" on top panel -- In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. -- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest -- In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` - -2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. - ## Publishing Package publishing is an optional part of the Backstage build system and not From 08b7ac6f07d4d50f5c65ff9cf24b618a1c669377 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 13 Feb 2023 16:02:09 +0100 Subject: [PATCH 126/417] microsite: add fold to last two blog posts Signed-off-by: Patrik Oldsberg --- microsite/blog/2023-01-31-incremental-entity-provider.md | 4 +++- microsite/blog/2023-02-06-whats-ahead-in-2023.md | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/microsite/blog/2023-01-31-incremental-entity-provider.md b/microsite/blog/2023-01-31-incremental-entity-provider.md index c14c3fc15d..fd273af208 100644 --- a/microsite/blog/2023-01-31-incremental-entity-provider.md +++ b/microsite/blog/2023-01-31-incremental-entity-provider.md @@ -4,10 +4,12 @@ author: Paul Cowan & Taras Mankovski authorURL: https://frontside.com/ --- -At the heart of [Backstage](https://backstage.io/) is the [Backstage Software Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), which is a data store that allows an organization to centralize and visualize its many software services and components. Backstage inspects and transforms an organization's disparate software services and parts into a centralized data store. +At the heart of [Backstage](https://backstage.io/) is the [Backstage Software Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), which is a data store that allows an organization to centralize and visualize its many software services and components. Backstage inspects and transforms an organization's disparate software services and parts into a centralized data store. This blog post introduces the concept of incremental entity providers, which allow Backstage to scale ingestion to even larger datasets. ![catalog pipeline](assets/2023-01-31/catalog-pipeline.png) + + A common use case is for an organization to want to surface ownership and metadata about repositories. Backstage provides a mechanism for discovering and transforming repository information into a standard data structure and persisting it into the Backstage [Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview). This process is known as ingestion, where all data is transformed into a standard Backstage data structure known as an entity. Entities in the Catalog’s data store are accessible to the Backstage App via the REST API. Data is transformed into entities via what is known as the ingestion and processing loop, which can be thought of as an [extract, transform and load (ETL) pipeline](https://en.wikipedia.org/wiki/Extract,_transform,_load), where raw data such as GitHub repositories are loaded from GitHub, transformed into entities and outputted to the Catalog. diff --git a/microsite/blog/2023-02-06-whats-ahead-in-2023.md b/microsite/blog/2023-02-06-whats-ahead-in-2023.md index a9f06d9ea0..f989973ca0 100644 --- a/microsite/blog/2023-02-06-whats-ahead-in-2023.md +++ b/microsite/blog/2023-02-06-whats-ahead-in-2023.md @@ -10,6 +10,8 @@ authorURL: https://github.com/leemills83 Okay, everyone. Time to move on from all the 2022 reflections, Top 10 lists, and Wrapped(s), and turn our gaze in the other direction — towards 2023. As the Backstage team moves into the new year, we find ourselves asking those perennial questions: How can we continue to grow and enhance the Backstage community? How can we improve the experience for those adopting Backstage? How can we give the best support to Backstage contributors? + + Well, we don’t have all the answers, but we do have some. So we wanted to share more on three ongoing initiatives aimed at moving the needle forward for these three distinct, yet interrelated, questions. - Grow your influence by climbing the contribution ladder From 0303587bcefb28694bd9d43d2fb6e8af2796ef7d Mon Sep 17 00:00:00 2001 From: Justin De Burgo <57914589+jpdeburgo@users.noreply.github.com> Date: Mon, 13 Feb 2023 09:21:44 -0600 Subject: [PATCH 127/417] Update .changeset/famous-squids-wonder.md Co-authored-by: Patrik Oldsberg Signed-off-by: Justin De Burgo <57914589+jpdeburgo@users.noreply.github.com> --- .changeset/famous-squids-wonder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/famous-squids-wonder.md b/.changeset/famous-squids-wonder.md index 11ca76ddc1..5b027e9a63 100644 --- a/.changeset/famous-squids-wonder.md +++ b/.changeset/famous-squids-wonder.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-backend': patch --- -Adding dot option to mini match used in catalog rules to allow for catalog imports with hidden folders +Location rule target patterns now also match hidden files, i.e. path components with a leading dot. From 1fad33684e4f6aac04b3865b924a19e16a110b5a Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 13 Feb 2023 16:31:49 +0100 Subject: [PATCH 128/417] use node-fetch Signed-off-by: Katharina Sick --- plugins/auth-backend/package.json | 2 +- .../bitbucketServer/provider.test.ts | 2 - .../src/providers/bitbucketServer/provider.ts | 3 +- yarn.lock | 49 ++++++++++++++++--- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a95465dbad..67a532e6fd 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -59,7 +59,7 @@ "minimatch": "^5.0.0", "morgan": "^1.10.0", "node-cache": "^5.1.2", - "node-fetch": "^2.6.7", + "node-fetch": "^3.3.0", "openid-client": "^5.2.1", "passport": "^0.6.0", "passport-auth0": "^1.4.3", diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts index 1a661b82bc..fc48cdbe8b 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -26,8 +26,6 @@ import { setupServer } from 'msw/node'; import { setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; -global.fetch = require('node-fetch'); - jest.mock('../../lib/passport/PassportStrategyHelper', () => { return { ...jest.requireActual('../../lib/passport/PassportStrategyHelper'), diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts index cd082ee953..fb8dd3d5b8 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -42,6 +42,7 @@ import express from 'express'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; import { Profile as PassportProfile } from 'passport'; import { commonByEmailResolver } from '../resolvers'; +import fetch from 'node-fetch'; type PrivateInfo = { refreshToken: string; @@ -215,7 +216,7 @@ export class BitbucketServerAuthProvider implements OAuthHandlers { throw new Error(`Failed to retrieve the user '${username}'`); } - const user = await userResponse.json(); + const user = (await userResponse.json()) as any; const passportProfile = { provider: 'bitbucketServer', diff --git a/yarn.lock b/yarn.lock index 1621cdc5b1..232efe185c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4567,7 +4567,7 @@ __metadata: morgan: ^1.10.0 msw: ^0.49.0 node-cache: ^5.1.2 - node-fetch: ^2.6.7 + node-fetch: ^3.3.0 openid-client: ^5.2.1 passport: ^0.6.0 passport-auth0: ^1.4.3 @@ -20160,6 +20160,13 @@ __metadata: languageName: node linkType: hard +"data-uri-to-buffer@npm:^4.0.0": + version: 4.0.1 + resolution: "data-uri-to-buffer@npm:4.0.1" + checksum: 0d0790b67ffec5302f204c2ccca4494f70b4e2d940fea3d36b09f0bb2b8539c2e86690429eb1f1dc4bcc9e4df0644193073e63d9ee48ac9fce79ec1506e4aa4c + languageName: node + linkType: hard + "data-urls@npm:^2.0.0": version: 2.0.0 resolution: "data-urls@npm:2.0.0" @@ -22814,6 +22821,16 @@ __metadata: languageName: node linkType: hard +"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": + version: 3.2.0 + resolution: "fetch-blob@npm:3.2.0" + dependencies: + node-domexception: ^1.0.0 + web-streams-polyfill: ^3.0.3 + checksum: f19bc28a2a0b9626e69fd7cf3a05798706db7f6c7548da657cbf5026a570945f5eeaedff52007ea35c8bcd3d237c58a20bf1543bc568ab2422411d762dd3d5bf + languageName: node + linkType: hard + "figures@npm:^3.0.0, figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -23204,6 +23221,15 @@ __metadata: languageName: node linkType: hard +"formdata-polyfill@npm:^4.0.10": + version: 4.0.10 + resolution: "formdata-polyfill@npm:4.0.10" + dependencies: + fetch-blob: ^3.1.2 + checksum: 82a34df292afadd82b43d4a740ce387bc08541e0a534358425193017bf9fb3567875dc5f69564984b1da979979b70703aa73dee715a17b6c229752ae736dd9db + languageName: node + linkType: hard + "formidable@npm:^2.0.1": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -29791,7 +29817,7 @@ __metadata: languageName: node linkType: hard -"node-domexception@npm:1.0.0": +"node-domexception@npm:1.0.0, node-domexception@npm:^1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0" checksum: ee1d37dd2a4eb26a8a92cd6b64dfc29caec72bff5e1ed9aba80c294f57a31ba4895a60fd48347cf17dd6e766da0ae87d75657dfd1f384ebfa60462c2283f5c7f @@ -29836,6 +29862,17 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^3.3.0": + version: 3.3.0 + resolution: "node-fetch@npm:3.3.0" + dependencies: + data-uri-to-buffer: ^4.0.0 + fetch-blob: ^3.1.4 + formdata-polyfill: ^4.0.10 + checksum: e9936908d2783d3c48a038e187f8062de294d75ef43ec8ab812d7cbd682be2b67605868758d2e9cad6103706dcfe4a9d21d78f6df984e8edf10e7a5ce2e665f8 + languageName: node + linkType: hard + "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -38005,10 +38042,10 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:^3.2.0": - version: 3.2.0 - resolution: "web-streams-polyfill@npm:3.2.0" - checksum: e23ad0649392fa0159dbfc6bb27474c308c3f332d9078cfef3c06c154165bef18732c5814126147c6c712f604216ddc950c171c854e3821f020e0d2d721a5958 +"web-streams-polyfill@npm:^3.0.3, web-streams-polyfill@npm:^3.2.0": + version: 3.2.1 + resolution: "web-streams-polyfill@npm:3.2.1" + checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02 languageName: node linkType: hard From 02ac23ea90cf369af8c2eda9b721dd311236e3a8 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Mon, 13 Feb 2023 16:34:37 +0100 Subject: [PATCH 129/417] reset node-fetch version Signed-off-by: Katharina Sick --- plugins/auth-backend/package.json | 2 +- yarn.lock | 43 +++---------------------------- 2 files changed, 4 insertions(+), 41 deletions(-) diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 67a532e6fd..a95465dbad 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -59,7 +59,7 @@ "minimatch": "^5.0.0", "morgan": "^1.10.0", "node-cache": "^5.1.2", - "node-fetch": "^3.3.0", + "node-fetch": "^2.6.7", "openid-client": "^5.2.1", "passport": "^0.6.0", "passport-auth0": "^1.4.3", diff --git a/yarn.lock b/yarn.lock index 232efe185c..4f9bfd99af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4567,7 +4567,7 @@ __metadata: morgan: ^1.10.0 msw: ^0.49.0 node-cache: ^5.1.2 - node-fetch: ^3.3.0 + node-fetch: ^2.6.7 openid-client: ^5.2.1 passport: ^0.6.0 passport-auth0: ^1.4.3 @@ -20160,13 +20160,6 @@ __metadata: languageName: node linkType: hard -"data-uri-to-buffer@npm:^4.0.0": - version: 4.0.1 - resolution: "data-uri-to-buffer@npm:4.0.1" - checksum: 0d0790b67ffec5302f204c2ccca4494f70b4e2d940fea3d36b09f0bb2b8539c2e86690429eb1f1dc4bcc9e4df0644193073e63d9ee48ac9fce79ec1506e4aa4c - languageName: node - linkType: hard - "data-urls@npm:^2.0.0": version: 2.0.0 resolution: "data-urls@npm:2.0.0" @@ -22821,16 +22814,6 @@ __metadata: languageName: node linkType: hard -"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": - version: 3.2.0 - resolution: "fetch-blob@npm:3.2.0" - dependencies: - node-domexception: ^1.0.0 - web-streams-polyfill: ^3.0.3 - checksum: f19bc28a2a0b9626e69fd7cf3a05798706db7f6c7548da657cbf5026a570945f5eeaedff52007ea35c8bcd3d237c58a20bf1543bc568ab2422411d762dd3d5bf - languageName: node - linkType: hard - "figures@npm:^3.0.0, figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -23221,15 +23204,6 @@ __metadata: languageName: node linkType: hard -"formdata-polyfill@npm:^4.0.10": - version: 4.0.10 - resolution: "formdata-polyfill@npm:4.0.10" - dependencies: - fetch-blob: ^3.1.2 - checksum: 82a34df292afadd82b43d4a740ce387bc08541e0a534358425193017bf9fb3567875dc5f69564984b1da979979b70703aa73dee715a17b6c229752ae736dd9db - languageName: node - linkType: hard - "formidable@npm:^2.0.1": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -29817,7 +29791,7 @@ __metadata: languageName: node linkType: hard -"node-domexception@npm:1.0.0, node-domexception@npm:^1.0.0": +"node-domexception@npm:1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0" checksum: ee1d37dd2a4eb26a8a92cd6b64dfc29caec72bff5e1ed9aba80c294f57a31ba4895a60fd48347cf17dd6e766da0ae87d75657dfd1f384ebfa60462c2283f5c7f @@ -29862,17 +29836,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^3.3.0": - version: 3.3.0 - resolution: "node-fetch@npm:3.3.0" - dependencies: - data-uri-to-buffer: ^4.0.0 - fetch-blob: ^3.1.4 - formdata-polyfill: ^4.0.10 - checksum: e9936908d2783d3c48a038e187f8062de294d75ef43ec8ab812d7cbd682be2b67605868758d2e9cad6103706dcfe4a9d21d78f6df984e8edf10e7a5ce2e665f8 - languageName: node - linkType: hard - "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -38042,7 +38005,7 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:^3.0.3, web-streams-polyfill@npm:^3.2.0": +"web-streams-polyfill@npm:^3.2.0": version: 3.2.1 resolution: "web-streams-polyfill@npm:3.2.1" checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02 From c51efce2a0e0f6cef6c4994ca361c8a75a6fd118 Mon Sep 17 00:00:00 2001 From: Jan Van Bruggen Date: Thu, 9 Feb 2023 13:34:03 -0700 Subject: [PATCH 130/417] Update docs to always use `yarn add --cwd` for app & backend Some commands currently error, and others are simply formatted inconsistently. This format seems to work and be the most popular/common, so I applied it to all similar occurrences. Signed-off-by: Jan Van Bruggen --- .changeset/empty-games-cheer.md | 22 +++++++++++++++++++ .../configure-app-with-plugins.md | 3 ++- docs/integrations/aws-s3/discovery.md | 2 +- docs/integrations/gerrit/discovery.md | 2 +- docs/integrations/gitlab/discovery.md | 2 +- docs/permissions/getting-started.md | 3 ++- docs/permissions/plugin-authors/01-setup.md | 7 +++--- docs/plugins/backend-plugin.md | 2 +- .../tutorials/configuring-plugin-databases.md | 2 +- packages/backend-test-utils/README.md | 2 +- plugins/adr-backend/README.md | 5 ++--- plugins/allure/README.md | 11 ++-------- plugins/analytics-module-ga/README.md | 7 +++++- .../api-docs-module-protoc-gen-doc/README.md | 5 +++-- plugins/azure-devops-backend/README.md | 5 ++--- plugins/azure-sites-backend/README.md | 2 +- plugins/azure-sites/README.md | 5 +++-- .../README.md | 2 +- plugins/catalog-graph/README.md | 5 +++-- plugins/code-coverage-backend/README.md | 5 ++++- plugins/code-coverage/README.md | 5 ++++- plugins/home/README.md | 2 +- plugins/ilert/README.md | 2 +- .../lighthouse/src/components/Intro/index.tsx | 4 ++-- plugins/microsoft-calendar/README.md | 2 +- plugins/shortcuts/README.md | 3 ++- plugins/xcmetrics/README.md | 5 ++--- 27 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 .changeset/empty-games-cheer.md diff --git a/.changeset/empty-games-cheer.md b/.changeset/empty-games-cheer.md new file mode 100644 index 0000000000..d17e97f752 --- /dev/null +++ b/.changeset/empty-games-cheer.md @@ -0,0 +1,22 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-api-docs-module-protoc-gen-doc': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-azure-devops-backend': patch +'@backstage/backend-test-utils': patch +'@backstage/plugin-analytics-module-ga': patch +'@backstage/plugin-azure-sites-backend': patch +'@backstage/plugin-microsoft-calendar': patch +'@backstage/plugin-catalog-graph': patch +'@backstage/plugin-code-coverage': patch +'@backstage/plugin-adr-backend': patch +'@backstage/plugin-azure-sites': patch +'@backstage/plugin-lighthouse': patch +'@backstage/plugin-shortcuts': patch +'@backstage/plugin-xcmetrics': patch +'@backstage/plugin-allure': patch +'@backstage/plugin-ilert': patch +'@backstage/plugin-home': patch +--- + +Update docs to always use `yarn add --cwd` for app & backend diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index ebe98f9ddc..835da0cd49 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -22,7 +22,8 @@ to an entity in the software catalog. 1. Add the plugin's npm package to the repo: ```bash - yarn workspace app add @backstage/plugin-circleci + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-circleci ``` Note the plugin is added to the `app` package, rather than the root diff --git a/docs/integrations/aws-s3/discovery.md b/docs/integrations/aws-s3/discovery.md index 748aeb2392..4a2b953bc9 100644 --- a/docs/integrations/aws-s3/discovery.md +++ b/docs/integrations/aws-s3/discovery.md @@ -63,7 +63,7 @@ As this provider is not one of the default providers, you will first need to ins the AWS catalog plugin: ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-aws ``` diff --git a/docs/integrations/gerrit/discovery.md b/docs/integrations/gerrit/discovery.md index 7ed05d2b3b..5d822effb5 100644 --- a/docs/integrations/gerrit/discovery.md +++ b/docs/integrations/gerrit/discovery.md @@ -17,7 +17,7 @@ As this provider is not one of the default providers, you will first need to ins the Gerrit provider plugin: ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-gerrit ``` diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index 51c34b67ac..3d554ce6b2 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -36,7 +36,7 @@ As this provider is not one of the default providers, you will first need to ins the gitlab catalog plugin: ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-gitlab ``` diff --git a/docs/permissions/getting-started.md b/docs/permissions/getting-started.md index d2c467ff08..e71601b703 100644 --- a/docs/permissions/getting-started.md +++ b/docs/permissions/getting-started.md @@ -47,7 +47,8 @@ The permissions framework uses a new `permission-backend` plugin to accept autho 1. Add `@backstage/plugin-permission-backend` as a dependency of your Backstage backend: ```bash -$ yarn workspace backend add @backstage/plugin-permission-backend +# From your Backstage root directory +$ yarn add --cwd packages/backend @backstage/plugin-permission-backend ``` 2. Add the following to a new file, `packages/backend/src/plugins/permission.ts`. This adds the permission-backend router, and configures it with a policy which allows everything. diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md index a38b81e679..c368505849 100644 --- a/docs/permissions/plugin-authors/01-setup.md +++ b/docs/permissions/plugin-authors/01-setup.md @@ -39,9 +39,10 @@ The source code is available here: 2. Add these packages as dependencies for your Backstage app: - ``` - $ yarn workspace backend add @internal/plugin-todo-list-backend @internal/plugin-todo-list-common - $ yarn workspace app add @internal/plugin-todo-list + ```sh + # From your Backstage root directory + $ yarn add --cwd packages/backend @internal/plugin-todo-list-backend @internal/plugin-todo-list-common + $ yarn add --cwd packages/app @internal/plugin-todo-list ``` 3. Include the backend and frontend plugin in your application: diff --git a/docs/plugins/backend-plugin.md b/docs/plugins/backend-plugin.md index 517779d161..c4414c8e55 100644 --- a/docs/plugins/backend-plugin.md +++ b/docs/plugins/backend-plugin.md @@ -66,7 +66,7 @@ To actually attach and run the plugin router, you will make some modifications to your backend. ```bash -# From the Backstage root directory +# From your Backstage root directory yarn add --cwd packages/backend @internal/plugin-carmen-backend@^0.1.1 # Change this to match the plugin's package.json ``` diff --git a/docs/tutorials/configuring-plugin-databases.md b/docs/tutorials/configuring-plugin-databases.md index ed550f1801..34e62c285a 100644 --- a/docs/tutorials/configuring-plugin-databases.md +++ b/docs/tutorials/configuring-plugin-databases.md @@ -37,7 +37,7 @@ package. If you intend to use both PostgreSQL and SQLite, you can install both of them. ```bash -# From the Backstage root directory +# From your Backstage root directory # install pg if you need PostgreSQL yarn add --cwd packages/backend pg diff --git a/packages/backend-test-utils/README.md b/packages/backend-test-utils/README.md index 38756fa5d7..7ccf4e2798 100644 --- a/packages/backend-test-utils/README.md +++ b/packages/backend-test-utils/README.md @@ -7,7 +7,7 @@ Test helpers library for Backstage backends. Add the library as a `devDependency` to your backend package: ```sh -# From the Backstage root directory, go to your backend package, or to a backend plugin +# From your Backstage root directory, go to your backend package, or to a backend plugin cd plugins/my-plugin-backend yarn add --dev @backstage/backend-test-utils ``` diff --git a/plugins/adr-backend/README.md b/plugins/adr-backend/README.md index b751a3b56d..29fead7c84 100644 --- a/plugins/adr-backend/README.md +++ b/plugins/adr-backend/README.md @@ -19,9 +19,8 @@ Here's how to get the backend up and running: 1. First we need to add the `@backstage/plugin-adr-backend` package to your backend: ```sh -# From the Backstage root directory -cd packages/backend -yarn add @backstage/plugin-adr-backend +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-adr-backend ``` 2. Then we will create a new file named `packages/backend/src/plugins/adr.ts`, and add the diff --git a/plugins/allure/README.md b/plugins/allure/README.md index b9a8435a34..3a1137fc39 100644 --- a/plugins/allure/README.md +++ b/plugins/allure/README.md @@ -4,16 +4,9 @@ Welcome to the Backstage Allure plugin. This plugin add an entity service page t ## Install -Run the below command from the `app` package directory. - ```shell -yarn add @backstage/plugin-allure -``` - -alternatively, you can execute below command from the root directory of your Backstage app. - -```shell -yarn workspace app add @backstage/plugin-allure +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-allure ``` ## Configure diff --git a/plugins/analytics-module-ga/README.md b/plugins/analytics-module-ga/README.md index c2d79aa45d..d6e2642e2b 100644 --- a/plugins/analytics-module-ga/README.md +++ b/plugins/analytics-module-ga/README.md @@ -9,7 +9,12 @@ This plugin contains no other functionality. ## Installation 1. Install the plugin package in your Backstage app: - `cd packages/app && yarn add @backstage/plugin-analytics-module-ga` + +```sh +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-analytics-module-ga +``` + 2. Wire up the API implementation to your App: ```tsx diff --git a/plugins/api-docs-module-protoc-gen-doc/README.md b/plugins/api-docs-module-protoc-gen-doc/README.md index 4d90cd74c2..a921fafc0b 100644 --- a/plugins/api-docs-module-protoc-gen-doc/README.md +++ b/plugins/api-docs-module-protoc-gen-doc/README.md @@ -6,8 +6,9 @@ This package contains ApiDefinitionWidgets for the following projects: ## Setup -``` -yarn add @backstage/plugin-api-docs-module-protoc-gen-doc +```sh +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-api-docs-module-protoc-gen-doc ``` ## Add the GrpcDocsApiWidget to your apis diff --git a/plugins/azure-devops-backend/README.md b/plugins/azure-devops-backend/README.md index 301ae5b2b9..ba2a847c0a 100644 --- a/plugins/azure-devops-backend/README.md +++ b/plugins/azure-devops-backend/README.md @@ -30,9 +30,8 @@ Here's how to get the backend up and running: 1. First we need to add the `@backstage/plugin-azure-devops-backend` package to your backend: ```sh - # From the Backstage root directory - cd packages/backend - yarn add @backstage/plugin-azure-devops-backend + # From your Backstage root directory + yarn add --cwd packages/backend @backstage/plugin-azure-devops-backend ``` 2. Then we will create a new file named `packages/backend/src/plugins/azure-devops.ts`, and add the diff --git a/plugins/azure-sites-backend/README.md b/plugins/azure-sites-backend/README.md index 5f19267499..0d44b9a4e4 100644 --- a/plugins/azure-sites-backend/README.md +++ b/plugins/azure-sites-backend/README.md @@ -36,7 +36,7 @@ Here's how to get the backend plugin up and running: 1. First we need to add the `@backstage/plugin-azure-sites-backend` package to your backend: ```sh - # From the Backstage root directory + # From your Backstage root directory yarn add --cwd packages/backend @backstage/plugin-azure-sites-backend ``` diff --git a/plugins/azure-sites/README.md b/plugins/azure-sites/README.md index f240dab140..57bf84ccc5 100644 --- a/plugins/azure-sites/README.md +++ b/plugins/azure-sites/README.md @@ -44,10 +44,11 @@ azure.com/microsoft-web-sites: func-testapp ### Install the component -1. Install the plugin in the `packages/app` directory +1. Install the plugin ```sh -yarn add @backstage/plugin-azure-sites +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-azure-sites ``` 2. Add widget component to your Backstage instance: diff --git a/plugins/catalog-backend-module-incremental-ingestion/README.md b/plugins/catalog-backend-module-incremental-ingestion/README.md index aa23b8dfc1..7fe36eeec7 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/README.md +++ b/plugins/catalog-backend-module-incremental-ingestion/README.md @@ -41,7 +41,7 @@ The Incremental Entity Provider backend is designed for data sources that provid ## Installation -1. Install `@backstage/plugin-catalog-backend-module-incremental-ingestion` with `yarn workspace backend add @backstage/plugin-catalog-backend-module-incremental-ingestion` +1. Install `@backstage/plugin-catalog-backend-module-incremental-ingestion` with `yarn add --cwd packages/backend @backstage/plugin-catalog-backend-module-incremental-ingestion` from the Backstage root directory. 2. In your catalog.ts, import `IncrementalCatalogBuilder` from `@backstage/plugin-catalog-backend-module-incremental-ingestion` and instantiate it with `await IncrementalCatalogBuilder.create(env, builder)`. You have to pass `builder` into `IncrementalCatalogBuilder.create` function because `IncrementalCatalogBuilder` will convert an `IncrementalEntityProvider` into an `EntityProvider` and call `builder.addEntityProvider`. ```ts diff --git a/plugins/catalog-graph/README.md b/plugins/catalog-graph/README.md index 33dee92935..f723523716 100644 --- a/plugins/catalog-graph/README.md +++ b/plugins/catalog-graph/README.md @@ -24,9 +24,10 @@ The plugin comes with these features: To use the catalog graph plugin, you have to add some things to your Backstage app: -1. Add a dependency to your `packages/app/package.json`, run: +1. Add a dependency to your `packages/app/package.json`: ```sh - yarn add @backstage/plugin-catalog-graph + # From your Backstage root directory + yarn add --cwd packages/app @backstage/plugin-catalog-graph ``` 2. Add the `CatalogGraphPage` to your `packages/app/src/App.tsx`: diff --git a/plugins/code-coverage-backend/README.md b/plugins/code-coverage-backend/README.md index ae6021b07c..802e538125 100644 --- a/plugins/code-coverage-backend/README.md +++ b/plugins/code-coverage-backend/README.md @@ -4,7 +4,10 @@ This is the backend part of the `code-coverage` plugin. It takes care of process ## Installation -`yarn workspace backend add @backstage/plugin-code-coverage-backend` +```sh +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/plugin-code-coverage-backend +``` First create a `codecoverage.ts` file here: `packages/backend/src/plugins`. Now add the following as its content: diff --git a/plugins/code-coverage/README.md b/plugins/code-coverage/README.md index ce793a78d3..d4daa6ec00 100644 --- a/plugins/code-coverage/README.md +++ b/plugins/code-coverage/README.md @@ -4,7 +4,10 @@ This is the frontend part of the code-coverage plugin. It displays code coverage ## Installation -`yarn workspace app add @backstage/plugin-code-coverage` +```sh +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-code-coverage +``` Finally you need to import and render the code coverage entity, in `packages/app/src/components/catalog/EntityPage.tsx` add the following: diff --git a/plugins/home/README.md b/plugins/home/README.md index 0cd307b706..1fdface722 100644 --- a/plugins/home/README.md +++ b/plugins/home/README.md @@ -9,7 +9,7 @@ For App Integrators, the system is designed to be composable to give total freed If you have a standalone app (you didn't clone this repo), then do ```bash -# From the Backstage repository root +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-home ``` diff --git a/plugins/ilert/README.md b/plugins/ilert/README.md index c704108126..814baea507 100644 --- a/plugins/ilert/README.md +++ b/plugins/ilert/README.md @@ -26,7 +26,7 @@ In detail this plugin provides: Install the plugin: ```bash -# From the Backstage repository root +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-ilert ``` diff --git a/plugins/lighthouse/src/components/Intro/index.tsx b/plugins/lighthouse/src/components/Intro/index.tsx index 57609476b8..69fcf21cf3 100644 --- a/plugins/lighthouse/src/components/Intro/index.tsx +++ b/plugins/lighthouse/src/components/Intro/index.tsx @@ -50,8 +50,8 @@ with the environment variable \`LAS_CORS\` set to \`true\`._ When you have an instance running that Backstage can hook into, first install the plugin into your app: \`\`\`sh -cd packages/app -yarn add @backstage/plugin-lighthouse +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-lighthouse \`\`\` Modify your app routes in \`App.tsx\` to include the \`LighthousePage\` component exported from the plugin, for example: diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md index 73a66b15f5..219a7cf2dc 100644 --- a/plugins/microsoft-calendar/README.md +++ b/plugins/microsoft-calendar/README.md @@ -25,7 +25,7 @@ The following sections will help you set up the Microsoft calendar plugin. 1. Install the plugin by running this command ```bash -# From the Backstage repository root +# From your Backstage root directory yarn add --cwd packages/app @backstage/plugin-microsoft-calendar ``` diff --git a/plugins/shortcuts/README.md b/plugins/shortcuts/README.md index d7f8f19aec..cd79901656 100644 --- a/plugins/shortcuts/README.md +++ b/plugins/shortcuts/README.md @@ -7,7 +7,8 @@ The shortcuts plugin allows a user to have easy access to pages within a Backsta ### Install the package: ```bash -yarn add @backstage/plugin-shortcuts +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-shortcuts ``` ### Register plugin: diff --git a/plugins/xcmetrics/README.md b/plugins/xcmetrics/README.md index a3bb93d2af..7c003722a0 100644 --- a/plugins/xcmetrics/README.md +++ b/plugins/xcmetrics/README.md @@ -7,10 +7,9 @@ With this plugin, you can view data from XCMetrics directly in Backstage. ## Getting started -From `packages/app`: - ```bash -yarn add @backstage/plugin-xcmetrics +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-xcmetrics ``` In `packages/app/src/App.tsx`, add the following: From 79c6b9aa0e1982da010c1bdd2c2969c395ac76fc Mon Sep 17 00:00:00 2001 From: bogdannechyporenko Date: Mon, 13 Feb 2023 19:18:20 +0100 Subject: [PATCH 131/417] Added Intellij to a Vale vocabulary Signed-off-by: bogdannechyporenko --- .github/vale/Vocab/Backstage/accept.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index e6380a17f0..a488ad8f87 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -160,6 +160,7 @@ indexable inlined inlinehilite integrator's +Intellij interop JaCoCo JavaScript From 67ed63552446b512d549e911e13cd7d36eb36186 Mon Sep 17 00:00:00 2001 From: Christopher Kruse Date: Mon, 13 Feb 2023 10:28:03 -0800 Subject: [PATCH 132/417] fix: use `NotFoundError` for missing team in org Per [PR comment][1], better to use the provided error type that more closely matches the error encountered. [1]: https://github.com/backstage/backstage/pull/16059#discussion_r1103873709 Signed-off-by: Christopher Kruse --- .../src/scaffolder/actions/builtin/github/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts index dc8c4cd856..75c8f25d8b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/helpers.ts @@ -15,7 +15,7 @@ */ import { Config } from '@backstage/config'; -import { assertError, InputError } from '@backstage/errors'; +import { assertError, InputError, NotFoundError } from '@backstage/errors'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, @@ -370,7 +370,7 @@ async function validateAccessTeam(client: Octokit, access: string) { if (e.response.data.message === 'Not Found') { const message = `Received 'Not Found' from the API; one of org: ${org} or team: ${team_slug} was not found within GitHub.`; - throw new Error(message, { cause: e }); + throw new NotFoundError(message); } } } From f52b9828fa73d56a1bb7ec2849619e51a3fc29ad Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 13 Feb 2023 21:13:31 -0500 Subject: [PATCH 133/417] fix: Missing headers Signed-off-by: Adam Harvey --- docs/features/software-catalog/system-model.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index 16ad48abcf..a9b89ef4f4 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -63,7 +63,7 @@ BigTable databases, Pub/Sub topics, S3 buckets or CDNs. Modelling them together with components and systems will better allow us to visualize resource footprint, and create tooling around them. -##Organizational Entities +## Organizational Entities ### User @@ -120,7 +120,7 @@ product or use-case, share the same entity types in their APIs, and integrate well with each other. Other domains could be “Content Ingestion”, “Ads” or “Search”. -##Other +## Other ### Location From 7bd24b919c15ad103f5b15303c47c9869caac9f6 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Mon, 13 Feb 2023 21:20:50 -0500 Subject: [PATCH 134/417] chore: Link on page reference to diagram Signed-off-by: Adam Harvey --- docs/features/software-catalog/system-model.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index a9b89ef4f4..af359bb18a 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -128,7 +128,8 @@ A location is a marker that references other places to look for catalog data. ### Type -The type field in the system has no set meaning. It is up to the user to assign their own types and use them as desired, such as for link validation or creating custom UI components. Some common pre-defined types are depicted in the ecosystem modeling diagram. +The type field in the system has no set meaning. It is up to the user to assign their own types and use them as desired, such as for link validation or creating custom UI components. Some common pre-defined types are depicted in the +[ecosystem modeling diagram](#ecosystem-modeling). ### Template From b16a9c59f5de06b27854c79abcd713c3d5cb7183 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Tue, 14 Feb 2023 08:40:29 +0100 Subject: [PATCH 135/417] Renamed Intellij to IntelliJ Signed-off-by: bnechyporenko --- .github/vale/Vocab/Backstage/accept.txt | 1 - docs/local-dev/cli-build-system.md | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index a488ad8f87..e6380a17f0 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -160,7 +160,6 @@ indexable inlined inlinehilite integrator's -Intellij interop JaCoCo JavaScript diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index ec0f3273fb..424b5f2c0c 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -560,7 +560,7 @@ The overrides in a single `package.json` may for example look like this: For your productivity working with unit tests it's quite essential to have your debugging configured in IDE. It will help you to identify the root cause of the issue faster. -#### Intellij IDEA +#### IntelliJ IDEA 1. Update Jest configuration template by: From 40298b02778c34f4c63c898a19cd4155bcb2fda2 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Tue, 14 Feb 2023 08:44:52 +0000 Subject: [PATCH 136/417] docs error more explanatory Signed-off-by: Brian Fletcher --- .changeset/flat-peaches-act.md | 5 +++++ plugins/techdocs-backend/src/service/DocsSynchronizer.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/flat-peaches-act.md diff --git a/.changeset/flat-peaches-act.md b/.changeset/flat-peaches-act.md new file mode 100644 index 0000000000..577e17231f --- /dev/null +++ b/.changeset/flat-peaches-act.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Techdocs backend explains a bit more about about what might have caused the docs not being found when building techdocs. diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts index 3d89d1647f..8456f64a6a 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts @@ -165,7 +165,7 @@ export class DocsSynchronizer { ); error( new NotFoundError( - 'Sorry! It took too long for the generated docs to show up in storage. Check back later.', + 'Sorry! It took too long for the generated docs to show up in storage. Are you sure the docs project is generating an `index.html` file? Otherwise, check back later.', ), ); return; From c2593f150fda7e782b081ce732a820ef09d6f860 Mon Sep 17 00:00:00 2001 From: Brian Fletcher Date: Tue, 14 Feb 2023 08:52:49 +0000 Subject: [PATCH 137/417] remove double word Signed-off-by: Brian Fletcher --- .changeset/flat-peaches-act.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/flat-peaches-act.md b/.changeset/flat-peaches-act.md index 577e17231f..e4b4138ee5 100644 --- a/.changeset/flat-peaches-act.md +++ b/.changeset/flat-peaches-act.md @@ -2,4 +2,4 @@ '@backstage/plugin-techdocs-backend': patch --- -Techdocs backend explains a bit more about about what might have caused the docs not being found when building techdocs. +Techdocs backend explains a bit more about what might have caused the docs not being found when building techdocs. From 4bdd6bcb3c2cb1a87c2955862815d6e62c225373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 14 Feb 2023 10:21:48 +0100 Subject: [PATCH 138/417] Prefer Link over plain anchors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/tidy-kids-hide.md | 7 +++++++ .../DagTableComponent/DagTableComponent.tsx | 16 +++++++++------- .../AzureSitesOverviewTable.tsx | 5 ++--- .../lighthouse/src/components/Intro/index.tsx | 6 +++--- 4 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 .changeset/tidy-kids-hide.md diff --git a/.changeset/tidy-kids-hide.md b/.changeset/tidy-kids-hide.md new file mode 100644 index 0000000000..194497d05c --- /dev/null +++ b/.changeset/tidy-kids-hide.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-apache-airflow': patch +'@backstage/plugin-azure-sites': patch +'@backstage/plugin-lighthouse': patch +--- + +Prefer Link over plain anchors diff --git a/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx b/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx index 2660e9380e..2cd136c7fa 100644 --- a/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx +++ b/plugins/apache-airflow/src/components/DagTableComponent/DagTableComponent.tsx @@ -15,6 +15,7 @@ */ import { + Link, Progress, StatusError, StatusOK, @@ -144,13 +145,14 @@ export const DenseTable = ({ dags, rowClick }: DenseTableProps) => { { title: 'Link', field: 'dagUrl', - render: (row: Partial) => ( - - - - - - ), + render: (row: Partial) => + !row.dagUrl ? null : ( + + + + + + ), width: '5%', disableClick: true, hidden: hiddenColumns.some(field => field === 'dagUrl'), diff --git a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx index dc059b2f15..5b67fe844a 100644 --- a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx +++ b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx @@ -164,9 +164,8 @@ const ActionButtons = ({ )} diff --git a/plugins/lighthouse/src/components/Intro/index.tsx b/plugins/lighthouse/src/components/Intro/index.tsx index 57609476b8..519b0a3f21 100644 --- a/plugins/lighthouse/src/components/Intro/index.tsx +++ b/plugins/lighthouse/src/components/Intro/index.tsx @@ -22,6 +22,7 @@ import LighthouseSupportButton from '../SupportButton'; import { ContentHeader, InfoCard, + Link, MarkdownContent, } from '@backstage/core-components'; @@ -108,10 +109,9 @@ function GettingStartedCard() { From 17b573e4be9c2277b4f83d9a03a21ba73773e93f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:51:23 +0100 Subject: [PATCH 139/417] backend-test-utils: mark backend system utils as stable Signed-off-by: Patrik Oldsberg --- .changeset/silent-roses-join.md | 5 +++++ packages/backend-test-utils/api-report.md | 8 ++++---- .../backend-test-utils/src/next/services/mockServices.ts | 2 +- .../backend-test-utils/src/next/wiring/TestBackend.ts | 6 +++--- 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .changeset/silent-roses-join.md diff --git a/.changeset/silent-roses-join.md b/.changeset/silent-roses-join.md new file mode 100644 index 0000000000..5794c8701c --- /dev/null +++ b/.changeset/silent-roses-join.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +The new backend system testing utilities have now been marked as stable API. diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 0b3d7dd843..c13d1bb859 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -28,7 +28,7 @@ import { UrlReaderService } from '@backstage/backend-plugin-api'; // @public (undocumented) export function isDockerDisabledForTests(): boolean; -// @alpha (undocumented) +// @public (undocumented) export namespace mockServices { // (undocumented) export namespace cache { @@ -126,7 +126,7 @@ export function setupRequestMockHandlers(worker: { resetHandlers: () => void; }): void; -// @alpha (undocumented) +// @public (undocumented) export function startTestBackend< TServices extends any[], TExtensionPoints extends any[], @@ -134,12 +134,12 @@ export function startTestBackend< options: TestBackendOptions, ): Promise; -// @alpha (undocumented) +// @public (undocumented) export interface TestBackend extends Backend { readonly server: ExtendedHttpServer; } -// @alpha (undocumented) +// @public (undocumented) export interface TestBackendOptions< TServices extends any[], TExtensionPoints extends any[], diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index 2e97cc63fb..8a3125214c 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -58,7 +58,7 @@ function simpleFactory< } /** - * @alpha + * @public */ export namespace mockServices { export function config(options?: config.Options): ConfigService { diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index bbda9854d4..66bbb62193 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -36,7 +36,7 @@ import { mockServices } from '../services'; import { ConfigReader } from '@backstage/config'; import express from 'express'; -/** @alpha */ +/** @public */ export interface TestBackendOptions< TServices extends any[], TExtensionPoints extends any[], @@ -60,7 +60,7 @@ export interface TestBackendOptions< features?: BackendFeature[]; } -/** @alpha */ +/** @public */ export interface TestBackend extends Backend { /** * Provides access to the underling HTTP server for use with utilities @@ -89,7 +89,7 @@ const defaultServiceFactories = [ const backendInstancesToCleanUp = new Array(); -/** @alpha */ +/** @public */ export async function startTestBackend< TServices extends any[], TExtensionPoints extends any[], From d4ba79253b70945b6c2c054c3f2195e0c608f891 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:52:40 +0100 Subject: [PATCH 140/417] docs/local-dev: codeblock Signed-off-by: Patrik Oldsberg --- docs/local-dev/cli-build-system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index 424b5f2c0c..cf8ac626b9 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -566,7 +566,7 @@ For your productivity working with unit tests it's quite essential to have your - Click on "Edit Configurations" on top panel - In the modal dialog click on link "Edit configuration templates..." located in the bottom left corner. -- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. ~/proj/backstage/node_modules/jest +- In "Jest package" you have to point to relative path of jest module (it will be suggested by IntelliJ), i.e. `~/proj/backstage/node_modules/jest` - In "Jest config" point to your jest configuration file, use absolute path for that, i.e. `--config /Users/user/proj/backstage/packages/cli/config/jest.js --runInBand` 2. Now you can run any tests by clicking on green arrow located on `describe` or `it`. From d746d81bdd1fa37b5ac0c6e39410a228e0535676 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho Date: Wed, 8 Feb 2023 15:10:41 +0100 Subject: [PATCH 141/417] renaming(getMkDocsYml): Renamed to getMkdocsYml Suggested by kmatyukhin on https://github.com/backstage/backstage/pull/15417 Signed-off-by: Renan Mendes Carvalho Co-authored-by: Konstantin Matyukhin --- .../techdocs-cli/src/commands/generate/generate.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/mkdocs.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/serve.ts | 4 ++-- plugins/techdocs-node/api-report.md | 2 +- .../src/stages/generate/helpers.test.ts | 12 ++++++------ plugins/techdocs-node/src/stages/generate/helpers.ts | 2 +- plugins/techdocs-node/src/stages/generate/index.ts | 2 +- .../techdocs-node/src/stages/generate/techdocs.ts | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index 8445dd9ec6..db58ea4faf 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -21,7 +21,7 @@ import Docker from 'dockerode'; import { TechdocsGenerator, ParsedLocationAnnotation, - getMkDocsYml, + getMkdocsYml, } from '@backstage/plugin-techdocs-node'; import { ContainerRunner, @@ -55,7 +55,7 @@ export default async function generate(opts: OptionValues) { await fs.ensureDir(outputDir); - const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( sourceDir, ); diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index 1a471cf1a6..50aa94e346 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -19,7 +19,7 @@ import openBrowser from 'react-dev-utils/openBrowser'; import { createLogger } from '../../lib/utility'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; -import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; import fs from 'fs-extra'; export default async function serveMkdocs(opts: OptionValues) { @@ -29,7 +29,7 @@ export default async function serveMkdocs(opts: OptionValues) { const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 48e48d4f66..bf67606481 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -22,7 +22,7 @@ import HTTPServer from '../../lib/httpServer'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; import { createLogger } from '../../lib/utility'; -import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import { getMkdocsYml } from '@backstage/plugin-techdocs-node'; import fs from 'fs-extra'; function findPreviewBundlePath(): string { @@ -66,7 +66,7 @@ export default async function serve(opts: OptionValues) { ? mkdocsDockerAddr : mkdocsLocalAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index ce5bd1ae09..314a46a405 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -89,7 +89,7 @@ export const getLocationForEntity: ( ) => ParsedLocationAnnotation; // @public -export const getMkDocsYml: ( +export const getMkdocsYml: ( inputDir: string, siteOptions?: { name?: string; diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index e635542a7c..aad7706ab1 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -25,7 +25,7 @@ import { ParsedLocationAnnotation } from '../../helpers'; import { createOrUpdateMetadata, getGeneratorKey, - getMkDocsYml, + getMkdocsYml, getRepoUrlFromLocationAnnotation, patchIndexPreBuild, storeEtagMetadata, @@ -517,7 +517,7 @@ describe('helpers', () => { }); }); - describe('getMkDocsYml', () => { + describe('getMkdocsYml', () => { const inputDir = resolvePath(__filename, '../__fixtures__/'); const siteOptions = { name: mockEntity.metadata.title, @@ -530,7 +530,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkDocsYml(inputDir, siteOptions); + } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); @@ -544,7 +544,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkDocsYml(inputDir, siteOptions); + } = await getMkdocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); expect(configIsTemporary).toBe(false); @@ -562,7 +562,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkDocsYml(inputDir, defaultSiteOptions); + } = await getMkdocsYml(inputDir, defaultSiteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsDefaultYml.toString()); @@ -571,7 +571,7 @@ describe('helpers', () => { it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect(getMkDocsYml(invalidInputDir, siteOptions)).rejects.toThrow( + await expect(getMkdocsYml(invalidInputDir, siteOptions)).rejects.toThrow( /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 27c24ea66e..e16293f906 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -193,7 +193,7 @@ export const generateMkdocsYml = async ( * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the * required `site_name` property, default value is "Documentation Site" */ -export const getMkDocsYml = async ( +export const getMkdocsYml = async ( inputDir: string, siteOptions?: { name?: string }, ): Promise<{ path: string; content: string; configIsTemporary: boolean }> => { diff --git a/plugins/techdocs-node/src/stages/generate/index.ts b/plugins/techdocs-node/src/stages/generate/index.ts index fa36486a0f..3bd42643c1 100644 --- a/plugins/techdocs-node/src/stages/generate/index.ts +++ b/plugins/techdocs-node/src/stages/generate/index.ts @@ -15,7 +15,7 @@ */ export { TechdocsGenerator } from './techdocs'; export { Generators } from './generators'; -export { getMkDocsYml } from './helpers'; +export { getMkdocsYml } from './helpers'; export type { GeneratorBase, GeneratorOptions, diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 93285b7468..b71148060e 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -24,7 +24,7 @@ import { } from '@backstage/integration'; import { createOrUpdateMetadata, - getMkDocsYml, + getMkdocsYml, patchIndexPreBuild, runCommand, storeEtagMetadata, @@ -100,7 +100,7 @@ export class TechdocsGenerator implements GeneratorBase { } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url - const { path: mkdocsYmlPath, content } = await getMkDocsYml( + const { path: mkdocsYmlPath, content } = await getMkdocsYml( inputDir, siteOptions, ); From c5d51ad7d4106e4f44d5179c24be2f6464b77f81 Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho Date: Wed, 8 Feb 2023 15:46:10 +0100 Subject: [PATCH 142/417] renaming(mkDocs): To mkdocs Suggested by kmatyukhin on https://github.com/backstage/backstage/pull/15417 Signed-off-by: Renan Mendes Carvalho Co-authored-by: Konstantin Matyukhin --- .../techdocs-cli/cypress/e2e/mkdocs_serve.cy.js | 4 ++-- .../techdocs-cli/src/commands/generate/generate.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/mkdocs.ts | 4 ++-- packages/techdocs-cli/src/commands/serve/serve.ts | 4 ++-- plugins/techdocs-node/api-report.md | 14 ++++++++++++++ .../src/stages/generate/helpers.test.ts | 2 +- plugins/techdocs-node/src/stages/generate/index.ts | 7 +++++++ .../{mkDocsPatchers.ts => mkdocsPatchers.ts} | 0 .../techdocs-node/src/stages/generate/techdocs.ts | 2 +- 9 files changed, 31 insertions(+), 10 deletions(-) rename plugins/techdocs-node/src/stages/generate/{mkDocsPatchers.ts => mkdocsPatchers.ts} (100%) diff --git a/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js index d9da6caeca..d5417e615f 100644 --- a/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js +++ b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js @@ -16,7 +16,7 @@ /// describe('TechDocs Live Preview - MkDocs Serve', () => { it('successfully serves documentation', () => { - cy.visit(Cypress.env('mkDocsBaseUrl')); + cy.visit(Cypress.env('mkdocsBaseUrl')); cy.contains('hello mock docs'); }); @@ -41,7 +41,7 @@ describe('TechDocs Live Preview - MkDocs Serve', () => { }); it('matchImage - MkDocs Page', () => { - cy.visit(Cypress.env('mkDocsBaseUrl')).then(() => { + cy.visit(Cypress.env('mkdocsBaseUrl')).then(() => { cy.document().matchImage(); }); }); diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index db58ea4faf..b8ad466bb3 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -55,7 +55,7 @@ export default async function generate(opts: OptionValues) { await fs.ensureDir(outputDir); - const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( sourceDir, ); @@ -116,7 +116,7 @@ export default async function generate(opts: OptionValues) { if (configIsTemporary) { process.on('exit', async () => { - fs.rmSync(mkDocsYmlPath, {}); + fs.rmSync(mkdocsYmlPath, {}); }); } diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index 50aa94e346..c061d4474f 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -29,7 +29,7 @@ export default async function serveMkdocs(opts: OptionValues) { const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); @@ -81,7 +81,7 @@ export default async function serveMkdocs(opts: OptionValues) { if (configIsTemporary) { process.on('exit', async () => { - fs.rmSync(mkDocsYmlPath, {}); + fs.rmSync(mkdocsYmlPath, {}); }); } } diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index bf67606481..9cfc24b629 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -66,7 +66,7 @@ export default async function serve(opts: OptionValues) { ? mkdocsDockerAddr : mkdocsLocalAddr; - const { path: mkDocsYmlPath, configIsTemporary } = await getMkdocsYml( + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( './', opts.siteName, ); @@ -150,7 +150,7 @@ export default async function serve(opts: OptionValues) { if (configIsTemporary) { process.on('exit', async () => { - fs.rmSync(mkDocsYmlPath, {}); + fs.rmSync(mkdocsYmlPath, {}); }); } } diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 314a46a405..11ff53514b 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -88,6 +88,20 @@ export const getLocationForEntity: ( scmIntegration: ScmIntegrationRegistry, ) => ParsedLocationAnnotation; +// @public @deprecated (undocumented) +export const getMkDocsYml: ( + inputDir: string, + siteOptions?: + | { + name?: string | undefined; + } + | undefined, +) => Promise<{ + path: string; + content: string; + configIsTemporary: boolean; +}>; + // @public export const getMkdocsYml: ( inputDir: string, diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index aad7706ab1..b24d85430b 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -34,7 +34,7 @@ import { import { patchMkdocsYmlPreBuild, pathMkdocsYmlWithTechdocsPlugin, -} from './mkDocsPatchers'; +} from './mkdocsPatchers'; import yaml from 'js-yaml'; const mockEntity = { diff --git a/plugins/techdocs-node/src/stages/generate/index.ts b/plugins/techdocs-node/src/stages/generate/index.ts index 3bd42643c1..aaf27026c2 100644 --- a/plugins/techdocs-node/src/stages/generate/index.ts +++ b/plugins/techdocs-node/src/stages/generate/index.ts @@ -23,3 +23,10 @@ export type { GeneratorRunOptions, SupportedGeneratorKey, } from './types'; +import { getMkdocsYml } from './helpers'; +/** + * @public + * @deprecated + * Deprecated in favor of getMkdocsYml (lowercase 'd') + */ +export const getMkDocsYml = getMkdocsYml; diff --git a/plugins/techdocs-node/src/stages/generate/mkDocsPatchers.ts b/plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts similarity index 100% rename from plugins/techdocs-node/src/stages/generate/mkDocsPatchers.ts rename to plugins/techdocs-node/src/stages/generate/mkdocsPatchers.ts diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index b71148060e..2f88e1a8ad 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -34,7 +34,7 @@ import { import { patchMkdocsYmlPreBuild, pathMkdocsYmlWithTechdocsPlugin, -} from './mkDocsPatchers'; +} from './mkdocsPatchers'; import { GeneratorBase, GeneratorConfig, From dd1e37649fefd548e11d8fa103189b2a4e983f4a Mon Sep 17 00:00:00 2001 From: Renan Mendes Carvalho Date: Fri, 10 Feb 2023 14:40:14 +0100 Subject: [PATCH 143/417] changeset(@techdocs/cli@,@backstage/plugin-techdocs-node) Signed-off-by: Renan Mendes Carvalho --- .changeset/cool-radios-hope.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/cool-radios-hope.md diff --git a/.changeset/cool-radios-hope.md b/.changeset/cool-radios-hope.md new file mode 100644 index 0000000000..4a66925d05 --- /dev/null +++ b/.changeset/cool-radios-hope.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-techdocs-node': minor +'@techdocs/cli': patch +--- + +Deprecated getMkDocsYml in favor of getMkdocsYml (lowercase 'd') From 869d658d2eaa527418ea4f6dab9aa7d1b0a55811 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:38:02 +0100 Subject: [PATCH 144/417] e2e-test: ignore AWS SDK v2 deprecation message Signed-off-by: Patrik Oldsberg --- packages/e2e-test/src/commands/run.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/e2e-test/src/commands/run.ts b/packages/e2e-test/src/commands/run.ts index 254198ebb4..b3fb8d9a3c 100644 --- a/packages/e2e-test/src/commands/run.ts +++ b/packages/e2e-test/src/commands/run.ts @@ -490,6 +490,17 @@ async function testBackendStart(appDir: string, ...args: string[]) { !l.includes('Update this package.json to use a subpath') && !l.includes( '(Use `node --trace-deprecation ...` to show where the warning was created)', + ) && + // These 4 are all for the AWS SDK v2 deprecation + !l.includes( + 'The AWS SDK for JavaScript (v2) will be put into maintenance mode', + ) && + !l.includes( + 'Please migrate your code to use AWS SDK for JavaScript', + ) && + !l.includes('check the migration guide at https://a.co/7PzMCcy') && + !l.includes( + '(Use `node --trace-warnings ...` to show where the warning was created)', ), ).length !== 0 ); From f244b58916334a38151181918cace632b0becabe Mon Sep 17 00:00:00 2001 From: Tomasz Szuba Date: Mon, 13 Feb 2023 18:19:37 +0100 Subject: [PATCH 145/417] Add new index to techinsights This improved query for latest facts from several seconds to milliseconds on our instance Signed-off-by: Tomasz Szuba --- .changeset/grumpy-bikes-begin.md | 5 +++ plugins/tech-insights-backend/knexfile.js | 26 ++++++++++++++ .../20230213170839_latest-facts-index.js | 36 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 .changeset/grumpy-bikes-begin.md create mode 100644 plugins/tech-insights-backend/knexfile.js create mode 100644 plugins/tech-insights-backend/migrations/20230213170839_latest-facts-index.js diff --git a/.changeset/grumpy-bikes-begin.md b/.changeset/grumpy-bikes-begin.md new file mode 100644 index 0000000000..a98e6651f5 --- /dev/null +++ b/.changeset/grumpy-bikes-begin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-insights-backend': patch +--- + +Add DB index to improve latency of latest fact query diff --git a/plugins/tech-insights-backend/knexfile.js b/plugins/tech-insights-backend/knexfile.js new file mode 100644 index 0000000000..b771c202f5 --- /dev/null +++ b/plugins/tech-insights-backend/knexfile.js @@ -0,0 +1,26 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This file makes it possible to run "yarn knex migrate:make some_file_name" +// to assist in making new migrations +module.exports = { + client: 'better-sqlite3', + connection: ':memory:', + useNullAsDefault: true, + migrations: { + directory: './migrations', + }, +}; diff --git a/plugins/tech-insights-backend/migrations/20230213170839_latest-facts-index.js b/plugins/tech-insights-backend/migrations/20230213170839_latest-facts-index.js new file mode 100644 index 0000000000..94a589f59d --- /dev/null +++ b/plugins/tech-insights-backend/migrations/20230213170839_latest-facts-index.js @@ -0,0 +1,36 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const indexName = 'fact_id_entity_timestamp_idx'; +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async knex => { + await knex.schema.alterTable('facts', table => { + table.index(['id', 'entity', 'timestamp'], indexName); + }); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = async knex => { + await knex.schema.alterTable('facts', table => { + table.dropIndex(indexName); + }); +}; From 207d8df70300f794310562208a9d0f667c0ec0aa Mon Sep 17 00:00:00 2001 From: Tomasz Szuba Date: Tue, 14 Feb 2023 10:51:33 +0100 Subject: [PATCH 146/417] Remove knexfile.js from tech-insights-backend Signed-off-by: Tomasz Szuba --- plugins/tech-insights-backend/knexfile.js | 26 ----------------------- 1 file changed, 26 deletions(-) delete mode 100644 plugins/tech-insights-backend/knexfile.js diff --git a/plugins/tech-insights-backend/knexfile.js b/plugins/tech-insights-backend/knexfile.js deleted file mode 100644 index b771c202f5..0000000000 --- a/plugins/tech-insights-backend/knexfile.js +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// This file makes it possible to run "yarn knex migrate:make some_file_name" -// to assist in making new migrations -module.exports = { - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - migrations: { - directory: './migrations', - }, -}; From 725383f69de0f181c6907950ac83a63f6c9017b6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 13:55:45 +0100 Subject: [PATCH 147/417] backend-*: updated READMEs Signed-off-by: Patrik Oldsberg --- .changeset/pretty-icons-glow.md | 8 ++++++++ packages/backend-app-api/README.md | 3 ++- packages/backend-defaults/README.md | 5 +++-- packages/backend-dev-utils/README.md | 21 ++++++++++++++++++--- packages/backend-plugin-api/README.md | 9 +++++---- 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 .changeset/pretty-icons-glow.md diff --git a/.changeset/pretty-icons-glow.md b/.changeset/pretty-icons-glow.md new file mode 100644 index 0000000000..6023e47307 --- /dev/null +++ b/.changeset/pretty-icons-glow.md @@ -0,0 +1,8 @@ +--- +'@backstage/backend-plugin-api': patch +'@backstage/backend-dev-utils': patch +'@backstage/backend-defaults': patch +'@backstage/backend-app-api': patch +--- + +Tweaked messaging in the README. diff --git a/packages/backend-app-api/README.md b/packages/backend-app-api/README.md index ee608ceb43..44705cde52 100644 --- a/packages/backend-app-api/README.md +++ b/packages/backend-app-api/README.md @@ -1,6 +1,6 @@ # @backstage/backend-app-api -**This package is HIGHLY EXPERIMENTAL, do not use this for production** +**This package is EXPERIMENTAL, we recommend against using it for production deployments** This package provides the core API used by Backstage backend apps. @@ -17,3 +17,4 @@ yarn add --cwd packages/backend @backstage/backend-app-api - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) - [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) diff --git a/packages/backend-defaults/README.md b/packages/backend-defaults/README.md index 3128159f7c..826994da23 100644 --- a/packages/backend-defaults/README.md +++ b/packages/backend-defaults/README.md @@ -1,8 +1,8 @@ # @backstage/backend-defaults -**This package is HIGHLY EXPERIMENTAL, do not use this for production** +**This package is EXPERIMENTAL, we recommend against using it for production deployments** -This package provides the core API used by Backstage backend apps. +This package provides the default implementations and setup for a standard Backstage backend app. ## Installation @@ -17,3 +17,4 @@ yarn add --cwd packages/backend @backstage/backend-defaults - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) - [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) diff --git a/packages/backend-dev-utils/README.md b/packages/backend-dev-utils/README.md index 8acce94cf0..c60f5a4ad7 100644 --- a/packages/backend-dev-utils/README.md +++ b/packages/backend-dev-utils/README.md @@ -1,5 +1,20 @@ -# backend-dev-utils +# @backstage/backend-dev-utils -Welcome to the backend-dev-utils package! +**This package is EXPERIMENTAL, but we encourage use of it to add support for the new backend system in your own plugins** -_This package is experimental._ +This package helps set up local development environments for Backstage backend packages. + +## Installation + +Add the library to your backend plugin or module package: + +```bash +# From your Backstage root directory +yarn add --cwd plugins/-backend @backstage/backend-dev-utils +``` + +## Documentation + +- [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) +- [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) diff --git a/packages/backend-plugin-api/README.md b/packages/backend-plugin-api/README.md index 364655dd60..02b19a0c40 100644 --- a/packages/backend-plugin-api/README.md +++ b/packages/backend-plugin-api/README.md @@ -1,19 +1,20 @@ # @backstage/backend-plugin-api -**This package is HIGHLY EXPERIMENTAL, do not use this for production** +**This package is EXPERIMENTAL, but we encourage use of it to add support for the new backend system in your own plugins** -This package provides the core API used by Backstage backend plugins. +This package provides the core API used by Backstage backend plugins and modules. ## Installation -Add the library to your backend plugin package: +Add the library to your backend plugin or module package: ```bash # From your Backstage root directory -yarn add --cwd plugin/-backend @backstage/backend-plugin-api +yarn add --cwd plugins/-backend @backstage/backend-plugin-api ``` ## Documentation - [Backstage Readme](https://github.com/backstage/backstage/blob/master/README.md) - [Backstage Documentation](https://github.com/backstage/backstage/blob/master/docs/README.md) +- [Backstage Backend System](https://backstage.io/docs/backend-system/) From 14916877dd267a7dd0488bd30e350bb84bfa941c Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 17:27:16 +0100 Subject: [PATCH 148/417] docs: added some documentation about how to test the alpha version of the scaffolder Signed-off-by: blam --- .../testing-scaffolder-alpha.md | 234 ++++++++++++++++++ microsite/sidebars.json | 1 + 2 files changed, 235 insertions(+) create mode 100644 docs/features/software-templates/testing-scaffolder-alpha.md diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md new file mode 100644 index 0000000000..68a4c5486d --- /dev/null +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -0,0 +1,234 @@ +--- +id: testing-scaffolder-alpha +title: 'Experimental: Testing out the `alpha` Scaffolder plugin' +# prettier-ignore +description: Docs on the upcoming breaking release for the scaffolder plugin +--- + +## What's `scaffolder/next`? + +The `alpha` version, or as you might have seen referred to in other places the `scaffolder/next` release, is a new version of the `scaffolder` plugin that will be the first breaking change to the plugin, so you can also think of it as `@backstage/plugin-scaffolder@2.0.0`. +Its mostly a rewrite of a lot of the frontend components and pages that had very limited test coverage, which made adding new features to the `scaffolder` plugin quite hard, and we were lacking in confidence when making changes. + +There is of course some other things that have changed when re-writing this, which are essentially what has caused some breaking changes. +Now, this is not like previous scaffolder changes where you would have to change all of your templates as this is only the frontend plugin that is going to have breaking changes. You can read more about the [breaking changes](#breaking-changes) below. + +## What's new? + +First off, the main dependency that we have for the frontend which is responsible for rendering the `JSONSchema` into `material-ui` components is [react-jsonschema-form](https://github.com/rjsf-team/react-jsonschema-form). +This dependency in the current verison of the plugin is 3.x.x, which is now 2 major versions out of date. Long story short, `v4` of this plugin contained some bug fixes, and new features but we we're unable to upragde due to some issues with having support for `material-ui@v4`, so we had to wait for `v5` to be released, and because of the `FieldExtensions` and how they are very tightly coupled to the `react-jsonschema-form` library, we also wanted to make sure that this release was stable before getting people to migrate their `Field Extensions`. + +With that in mind, this release has `v5` of `react-jsonschema-form`, and with that comes all the new features and bugfixes in `v4` that we were waiting for - one of the main ones being the ability to use `if / then else` syntax in the `template.yaml` definitions! 🎉 + +We've also rebuilt how validation works in the `scaffolder` components, which now means that we've opened the ability to have `async` validation functions in your `Field Extensions`. + +Some of the pages have gotten a little bit of an overhaul in terms of UI based on some research and feedback from the community and internally. + +- The `TemplateList` page has gotten some new `Card` components which show a little more information than the previous version with a little `material-ui` standards. +- The `WizardPage` has recieved some new updates with the stepper now running horizontally, and the `Review` step being a dedicated step in the stepper. +- The `OngoingTask` page now does not show the logs by default, and instead has a much cleaner interface for tracking the ongoing steps and the pipeline of actions that are currently showing. + - You can also now provide your own `OutputsComponent` which can be used to render the outputs from an ongoing / completed task in a way that suits your templates the best. For instance, if your template produces `Pull Requests`, it could be useful to render these in an interactive way where you can see the statuses of each of these `Pull Requests` in the `Ongoing Task` page. + +There's also a lot of bug fixes, and other things, but these are the main ones that we wanted to highlight. + +## How do I test out the `alpha` version? + +With the release of `v1.12.0` it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing is, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. + +It's also worth calling out that if you do test this out, and find some issues or something not working out as expected, feel free to raise an issue in the [repo](https://github.com/backstage/backstage) or reach out to us on Discord! + +### Make the required changes to `App.tsx` + +The `ScaffolderPage` router has a completely different export for the `scaffolder/next` work, so you will want to change any import from the old `ScaffolderPage` to the new `NextScaffolderPage` + +```diff +- import { ScaffolderPage } from '@backstage/plugin-scaffolder'; ++ import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; + +``` + +And this API should be the exact same as the previous Router, so you should be able to make a change like the following futher down in this file: + +```diff + + entity?.metadata?.tags?.includes('recommended') ?? false, + }, + ]} + /> + } + > + + + ... other extensions + + + + ... other layouts + + +``` + +### Make the required changes to your `CustomFieldExtensions` + +There's differently named function for creating field extensions part of the `/alpha` exports as these are the ones that can contain breaking changes because of the breaking changes that have been applied in `react-jsonschema-form`. + +Let's take the following example: + +```ts +export const EntityNamePickerFieldExtension = scaffolderPlugin.provide( + createScaffolderFieldExtension({ + component: EntityNamePicker, + name: 'EntityNamePicker', + validation: entityNamePickerValidation, + schema: EntityNamePickerSchema, + }), +); +``` + +References for `createScaffolderFieldExtension` have an `/alpha` version of `createNextScaffolderFieldExtension`, which should be used instead. + +```diff +-import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder'; ++import { createNextScaffolderFieldExtension } from '@backstage/plugin-scaffolder/alpha'; + +export const EntityNamePickerFieldExtension = scaffolderPlugin.provide( +- createScaffolderFieldExtension({ ++ createNextScaffolderFieldExtension({ + component: EntityNamePicker, + name: 'EntityNamePicker', + validation: entityNamePickerValidation, + }), +); +``` + +Once you've done this you will find that you will have two squiggly lines under the properties that are passed in. One for the component and one for the validation (if provided.) + +Let's take the following code for the `EntityNamePicker` component: + +```ts +export const EntityNamePicker = ( + props: FieldExtensionComponentProps, +) => { + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, + formData, + uiSchema: { 'ui:autofocus': autoFocus }, + idSchema, + placeholder, + } = props; + ... +} +``` + +There's another `/alpha` export that's you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`. + +```diff +- import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react'; ++ import { NextFieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react/alpha'; + +export const EntityNamePicker = ( +- props: FieldExtensionComponentProps, ++ props: NextFieldExtensionComponentProps, +) => { + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, + formData, +- uiSchema: { 'ui:autofocus': autoFocus }, ++ uiSchema: { 'ui:autofocus': autoFocus } = {}, + idSchema, + placeholder, + } = props; + ... +} +``` + +You'll notice that there's an additional change here, which is that we're now defaulting the `uiSchema` to an empty object. This is because the `uiSchema` is now optional, and if you don't provide it, it will be `undefined` instead of an empty object. There's more around this in the [breaking changes](#breaking-changes) section. + +To fix the previous validation error, you will need to change the import for the `FieldValidation` type that is used in the `validation` function. + +Let's take the following example of the validation function: + +```ts +import { FieldValidation } from '@rjsf/utils'; +import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; + +export const entityNamePickerValidation = ( + value: string, + validation: FieldValidation, +) => { + if (!KubernetesValidatorFunctions.isValidObjectName(value)) { + validation.addError( + 'Must start and end with an alphanumeric character, and contain only alphanumeric characters, hyphens, underscores, and periods. Maximum length is 63 characters.', + ); + } +}; +``` + +You will need to change the import for `FieldValidation` to point at the new `react-jsonschema-form` dependency. + +> Note: you will proabably need to install this dependency too, by using `yarn add @rjsf/utils` in the package where you define these validation functions, this could also be in the `packages/app` folder, so you can install it there if needed. + +```diff +- import { FieldValidation } from '@rjsf/core'; ++ import { FieldValidation } from '@rjsf/utils; +import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; + +export const entityNamePickerValidation = ( + value: string, + validation: FieldValidation, +) => { +``` + +## Breaking Changes + +Once we fully release the code that is in the `/alpha` exports right now onto the current API and release v2.0.0 of `@backstage/plugin-scaffolder` the breaking changes will be as follows: + +### `uiSchema` is now optional + +Later releases of `react-jsonschema-form` have made the `uiSchema` optional, and if you don't provide it, it will be `undefined` instead of an empty object. This means that you will need to make sure that you're defaulting the `uiSchema` to an empty object if you're using it in your code. + +```diff + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, + formData, +- uiSchema: { 'ui:autofocus': autoFocus }, ++ uiSchema: { 'ui:autofocus': autoFocus } = {}, + idSchema, + placeholder, + } = props; +``` + +### `formData` can also be `undefined` + +If you were using the `formData` and assuming that it was set to an empty object when building `Field Extensions` that return objects, then this will be `undefined` now due to a change in the `react-jsonschema-form` library. + +```diff + const { + onChange, + required, + schema: { title = 'Name', description = 'Unique name of the component' }, + rawErrors, +- formData, ++ formData = {}, // or mayube some other default value that you would prefer + uiSchema: { 'ui:autofocus': autoFocus } = {}, + idSchema, + placeholder, + } = props; +``` diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 6baeb20e8b..fea976a5d6 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -104,6 +104,7 @@ "features/software-templates/writing-custom-actions", "features/software-templates/writing-custom-field-extensions", "features/software-templates/writing-custom-step-layouts", + "features/software-templates/testing-scaffolder-alpah", "features/software-templates/migrating-from-v1beta2-to-v1beta3" ] }, From be4474135a4a76287aaf458834ffdf735b136a63 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 17:37:32 +0100 Subject: [PATCH 149/417] chore: make vale and @kuangp happy :D Signed-off-by: blam --- .github/vale/Vocab/Backstage/accept.txt | 1 + .../software-templates/testing-scaffolder-alpha.md | 10 +++++----- microsite/sidebars.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index e6380a17f0..08e325c38b 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -33,6 +33,7 @@ Blackbox bool boolean Brex +bugfixes builtins callout CDNs diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md index 68a4c5486d..b8b63330d1 100644 --- a/docs/features/software-templates/testing-scaffolder-alpha.md +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -16,16 +16,16 @@ Now, this is not like previous scaffolder changes where you would have to change ## What's new? First off, the main dependency that we have for the frontend which is responsible for rendering the `JSONSchema` into `material-ui` components is [react-jsonschema-form](https://github.com/rjsf-team/react-jsonschema-form). -This dependency in the current verison of the plugin is 3.x.x, which is now 2 major versions out of date. Long story short, `v4` of this plugin contained some bug fixes, and new features but we we're unable to upragde due to some issues with having support for `material-ui@v4`, so we had to wait for `v5` to be released, and because of the `FieldExtensions` and how they are very tightly coupled to the `react-jsonschema-form` library, we also wanted to make sure that this release was stable before getting people to migrate their `Field Extensions`. +This dependency in the current version of the plugin is 3.x.x, which is now 2 major versions out of date. Long story short, `v4` of this plugin contained some bug fixes, and new features but we we're unable to upgrade due to some issues with having support for `material-ui@v4`, so we had to wait for `v5` to be released, and because of the `FieldExtensions` and how they are very tightly coupled to the `react-jsonschema-form` library, we also wanted to make sure that this release was stable before getting people to migrate their `Field Extensions`. -With that in mind, this release has `v5` of `react-jsonschema-form`, and with that comes all the new features and bugfixes in `v4` that we were waiting for - one of the main ones being the ability to use `if / then else` syntax in the `template.yaml` definitions! 🎉 +With that in mind, this release has `v5` of `react-jsonschema-form`, and with that comes all the new features and bugfixes in `v4` that we were waiting for - one of the main ones being the ability to use `if / then / else` syntax in the `template.yaml` definitions! 🎉 We've also rebuilt how validation works in the `scaffolder` components, which now means that we've opened the ability to have `async` validation functions in your `Field Extensions`. Some of the pages have gotten a little bit of an overhaul in terms of UI based on some research and feedback from the community and internally. - The `TemplateList` page has gotten some new `Card` components which show a little more information than the previous version with a little `material-ui` standards. -- The `WizardPage` has recieved some new updates with the stepper now running horizontally, and the `Review` step being a dedicated step in the stepper. +- The `WizardPage` has received some new updates with the stepper now running horizontally, and the `Review` step being a dedicated step in the stepper. - The `OngoingTask` page now does not show the logs by default, and instead has a much cleaner interface for tracking the ongoing steps and the pipeline of actions that are currently showing. - You can also now provide your own `OutputsComponent` which can be used to render the outputs from an ongoing / completed task in a way that suits your templates the best. For instance, if your template produces `Pull Requests`, it could be useful to render these in an interactive way where you can see the statuses of each of these `Pull Requests` in the `Ongoing Task` page. @@ -47,7 +47,7 @@ The `ScaffolderPage` router has a completely different export for the `scaffolde ``` -And this API should be the exact same as the previous Router, so you should be able to make a change like the following futher down in this file: +And this API should be the exact same as the previous Router, so you should be able to make a change like the following further down in this file: ```diff Note: you will proabably need to install this dependency too, by using `yarn add @rjsf/utils` in the package where you define these validation functions, this could also be in the `packages/app` folder, so you can install it there if needed. +> Note: you will probably need to install this dependency too, by using `yarn add @rjsf/utils` in the package where you define these validation functions, this could also be in the `packages/app` folder, so you can install it there if needed. ```diff - import { FieldValidation } from '@rjsf/core'; diff --git a/microsite/sidebars.json b/microsite/sidebars.json index fea976a5d6..b7e2068aca 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -104,7 +104,7 @@ "features/software-templates/writing-custom-actions", "features/software-templates/writing-custom-field-extensions", "features/software-templates/writing-custom-step-layouts", - "features/software-templates/testing-scaffolder-alpah", + "features/software-templates/testing-scaffolder-alpha", "features/software-templates/migrating-from-v1beta2-to-v1beta3" ] }, From e900342bb6bdc4240d7395d6b6902683567c1d7d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 14 Feb 2023 10:02:15 +0100 Subject: [PATCH 150/417] Apply suggestions from code review Co-authored-by: Phil Kuang Signed-off-by: Patrik Oldsberg --- .../features/software-templates/testing-scaffolder-alpha.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md index b8b63330d1..d10c7e7a0f 100644 --- a/docs/features/software-templates/testing-scaffolder-alpha.md +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -33,7 +33,7 @@ There's also a lot of bug fixes, and other things, but these are the main ones t ## How do I test out the `alpha` version? -With the release of `v1.12.0` it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing is, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. +With the release of `v1.12.0` it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes as part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. It's also worth calling out that if you do test this out, and find some issues or something not working out as expected, feel free to raise an issue in the [repo](https://github.com/backstage/backstage) or reach out to us on Discord! @@ -131,7 +131,7 @@ export const EntityNamePicker = ( } ``` -There's another `/alpha` export that's you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`. +There's another `/alpha` export that you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`. ```diff - import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react'; @@ -226,7 +226,7 @@ If you were using the `formData` and assuming that it was set to an empty object schema: { title = 'Name', description = 'Unique name of the component' }, rawErrors, - formData, -+ formData = {}, // or mayube some other default value that you would prefer ++ formData = {}, // or maybe some other default value that you would prefer uiSchema: { 'ui:autofocus': autoFocus } = {}, idSchema, placeholder, From 4226e75198f01258e930d9db4d0acdf3bffd7a74 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:00:45 +0000 Subject: [PATCH 151/417] chore(deps): update dependency lint-staged to v13.1.2 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index af1a8fd1b0..ac66cab7ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27871,8 +27871,8 @@ __metadata: linkType: hard "lint-staged@npm:^13.0.0": - version: 13.1.1 - resolution: "lint-staged@npm:13.1.1" + version: 13.1.2 + resolution: "lint-staged@npm:13.1.2" dependencies: cli-truncate: ^3.1.0 colorette: ^2.0.19 @@ -27889,7 +27889,7 @@ __metadata: yaml: ^2.1.3 bin: lint-staged: bin/lint-staged.js - checksum: 8e5093c7e982a2f6d6449927a40156a812644479df1d2760aee8bf05df3a314e022d8f7e275e57fd61769ee57e3cf7b062ed3c6e4934a63848300b877e269daa + checksum: f854ad5c88542b8f06e27f3b4046927a4f3d4a451a04e079526559d819a325762268f65bd2df7156bcc0cb5f531f621c42cdb824b403f537c78305adc9e56a54 languageName: node linkType: hard From e9ecc5ea980f10712c637b1e8a73eafd39449829 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:05:46 +0000 Subject: [PATCH 152/417] fix(deps): update dependency esbuild-loader to v2.21.0 Signed-off-by: Renovate Bot --- yarn.lock | 365 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 298 insertions(+), 67 deletions(-) diff --git a/yarn.lock b/yarn.lock index af1a8fd1b0..1fde08bb9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9441,6 +9441,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/android-arm64@npm:0.16.17" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/android-arm64@npm:0.17.6" @@ -9455,6 +9462,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/android-arm@npm:0.16.17" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/android-arm@npm:0.17.6" @@ -9462,6 +9476,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/android-x64@npm:0.16.17" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/android-x64@npm:0.17.6" @@ -9469,6 +9490,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/darwin-arm64@npm:0.16.17" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/darwin-arm64@npm:0.17.6" @@ -9476,6 +9504,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/darwin-x64@npm:0.16.17" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/darwin-x64@npm:0.17.6" @@ -9483,6 +9518,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/freebsd-arm64@npm:0.16.17" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/freebsd-arm64@npm:0.17.6" @@ -9490,6 +9532,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/freebsd-x64@npm:0.16.17" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/freebsd-x64@npm:0.17.6" @@ -9497,6 +9546,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-arm64@npm:0.16.17" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-arm64@npm:0.17.6" @@ -9504,6 +9560,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-arm@npm:0.16.17" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-arm@npm:0.17.6" @@ -9511,6 +9574,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-ia32@npm:0.16.17" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-ia32@npm:0.17.6" @@ -9525,6 +9595,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-loong64@npm:0.16.17" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-loong64@npm:0.17.6" @@ -9532,6 +9609,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-mips64el@npm:0.16.17" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-mips64el@npm:0.17.6" @@ -9539,6 +9623,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-ppc64@npm:0.16.17" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-ppc64@npm:0.17.6" @@ -9546,6 +9637,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-riscv64@npm:0.16.17" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-riscv64@npm:0.17.6" @@ -9553,6 +9651,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-s390x@npm:0.16.17" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-s390x@npm:0.17.6" @@ -9560,6 +9665,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-x64@npm:0.16.17" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/linux-x64@npm:0.17.6" @@ -9567,6 +9679,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/netbsd-x64@npm:0.16.17" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/netbsd-x64@npm:0.17.6" @@ -9574,6 +9693,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/openbsd-x64@npm:0.16.17" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/openbsd-x64@npm:0.17.6" @@ -9581,6 +9707,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/sunos-x64@npm:0.16.17" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/sunos-x64@npm:0.17.6" @@ -9588,6 +9721,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/win32-arm64@npm:0.16.17" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/win32-arm64@npm:0.17.6" @@ -9595,6 +9735,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/win32-ia32@npm:0.16.17" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/win32-ia32@npm:0.17.6" @@ -9602,6 +9749,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/win32-x64@npm:0.16.17" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.17.6": version: 0.17.6 resolution: "@esbuild/win32-x64@npm:0.17.6" @@ -21545,18 +21699,18 @@ __metadata: linkType: hard "esbuild-loader@npm:^2.18.0": - version: 2.20.0 - resolution: "esbuild-loader@npm:2.20.0" + version: 2.21.0 + resolution: "esbuild-loader@npm:2.21.0" dependencies: - esbuild: ^0.15.6 + esbuild: ^0.16.17 joycon: ^3.0.1 json5: ^2.2.0 loader-utils: ^2.0.0 tapable: ^2.2.0 - webpack-sources: ^2.2.0 + webpack-sources: ^1.4.3 peerDependencies: webpack: ^4.40.0 || ^5.0.0 - checksum: 81faee7155b35af1fdef3dffa273a14ec83e56b9efa1efb76cb1eb64964dd738809c147a87ab9d3507de11946eed51fd1ee42d476b2c9654cbda145da0d9479b + checksum: a0456ed7794e2c220a6068e92d739bc19765bff352bf7e44442aa8127631cc517ecd02a3ee969e31fa6b6a91befeac928296488c95e3818a776cd3b11d46348c languageName: node linkType: hard @@ -21602,80 +21756,80 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.15.6, esbuild@npm:~0.15.10": - version: 0.15.18 - resolution: "esbuild@npm:0.15.18" +"esbuild@npm:^0.16.17": + version: 0.16.17 + resolution: "esbuild@npm:0.16.17" dependencies: - "@esbuild/android-arm": 0.15.18 - "@esbuild/linux-loong64": 0.15.18 - esbuild-android-64: 0.15.18 - esbuild-android-arm64: 0.15.18 - esbuild-darwin-64: 0.15.18 - esbuild-darwin-arm64: 0.15.18 - esbuild-freebsd-64: 0.15.18 - esbuild-freebsd-arm64: 0.15.18 - esbuild-linux-32: 0.15.18 - esbuild-linux-64: 0.15.18 - esbuild-linux-arm: 0.15.18 - esbuild-linux-arm64: 0.15.18 - esbuild-linux-mips64le: 0.15.18 - esbuild-linux-ppc64le: 0.15.18 - esbuild-linux-riscv64: 0.15.18 - esbuild-linux-s390x: 0.15.18 - esbuild-netbsd-64: 0.15.18 - esbuild-openbsd-64: 0.15.18 - esbuild-sunos-64: 0.15.18 - esbuild-windows-32: 0.15.18 - esbuild-windows-64: 0.15.18 - esbuild-windows-arm64: 0.15.18 + "@esbuild/android-arm": 0.16.17 + "@esbuild/android-arm64": 0.16.17 + "@esbuild/android-x64": 0.16.17 + "@esbuild/darwin-arm64": 0.16.17 + "@esbuild/darwin-x64": 0.16.17 + "@esbuild/freebsd-arm64": 0.16.17 + "@esbuild/freebsd-x64": 0.16.17 + "@esbuild/linux-arm": 0.16.17 + "@esbuild/linux-arm64": 0.16.17 + "@esbuild/linux-ia32": 0.16.17 + "@esbuild/linux-loong64": 0.16.17 + "@esbuild/linux-mips64el": 0.16.17 + "@esbuild/linux-ppc64": 0.16.17 + "@esbuild/linux-riscv64": 0.16.17 + "@esbuild/linux-s390x": 0.16.17 + "@esbuild/linux-x64": 0.16.17 + "@esbuild/netbsd-x64": 0.16.17 + "@esbuild/openbsd-x64": 0.16.17 + "@esbuild/sunos-x64": 0.16.17 + "@esbuild/win32-arm64": 0.16.17 + "@esbuild/win32-ia32": 0.16.17 + "@esbuild/win32-x64": 0.16.17 dependenciesMeta: "@esbuild/android-arm": optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true "@esbuild/linux-loong64": optional: true - esbuild-android-64: + "@esbuild/linux-mips64el": optional: true - esbuild-android-arm64: + "@esbuild/linux-ppc64": optional: true - esbuild-darwin-64: + "@esbuild/linux-riscv64": optional: true - esbuild-darwin-arm64: + "@esbuild/linux-s390x": optional: true - esbuild-freebsd-64: + "@esbuild/linux-x64": optional: true - esbuild-freebsd-arm64: + "@esbuild/netbsd-x64": optional: true - esbuild-linux-32: + "@esbuild/openbsd-x64": optional: true - esbuild-linux-64: + "@esbuild/sunos-x64": optional: true - esbuild-linux-arm: + "@esbuild/win32-arm64": optional: true - esbuild-linux-arm64: + "@esbuild/win32-ia32": optional: true - esbuild-linux-mips64le: - optional: true - esbuild-linux-ppc64le: - optional: true - esbuild-linux-riscv64: - optional: true - esbuild-linux-s390x: - optional: true - esbuild-netbsd-64: - optional: true - esbuild-openbsd-64: - optional: true - esbuild-sunos-64: - optional: true - esbuild-windows-32: - optional: true - esbuild-windows-64: - optional: true - esbuild-windows-arm64: + "@esbuild/win32-x64": optional: true bin: esbuild: bin/esbuild - checksum: ec12682b2cb2d4f0669d0e555028b87a9284ca7f6a1b26e35e69a8697165b35cc682ad598abc70f0bbcfdc12ca84ef888caf5ceee389237862e8f8c17da85f89 + checksum: 4c2cc609ecfb426554bc3f75beb92d89eb2d0c515cfceebaa36c7599d7dcaab7056b70f6d6b51e72b45951ddf9021ee28e356cf205f8e42cc055d522312ea30c languageName: node linkType: hard @@ -21756,6 +21910,83 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:~0.15.10": + version: 0.15.18 + resolution: "esbuild@npm:0.15.18" + dependencies: + "@esbuild/android-arm": 0.15.18 + "@esbuild/linux-loong64": 0.15.18 + esbuild-android-64: 0.15.18 + esbuild-android-arm64: 0.15.18 + esbuild-darwin-64: 0.15.18 + esbuild-darwin-arm64: 0.15.18 + esbuild-freebsd-64: 0.15.18 + esbuild-freebsd-arm64: 0.15.18 + esbuild-linux-32: 0.15.18 + esbuild-linux-64: 0.15.18 + esbuild-linux-arm: 0.15.18 + esbuild-linux-arm64: 0.15.18 + esbuild-linux-mips64le: 0.15.18 + esbuild-linux-ppc64le: 0.15.18 + esbuild-linux-riscv64: 0.15.18 + esbuild-linux-s390x: 0.15.18 + esbuild-netbsd-64: 0.15.18 + esbuild-openbsd-64: 0.15.18 + esbuild-sunos-64: 0.15.18 + esbuild-windows-32: 0.15.18 + esbuild-windows-64: 0.15.18 + esbuild-windows-arm64: 0.15.18 + dependenciesMeta: + "@esbuild/android-arm": + optional: true + "@esbuild/linux-loong64": + optional: true + esbuild-android-64: + optional: true + esbuild-android-arm64: + optional: true + esbuild-darwin-64: + optional: true + esbuild-darwin-arm64: + optional: true + esbuild-freebsd-64: + optional: true + esbuild-freebsd-arm64: + optional: true + esbuild-linux-32: + optional: true + esbuild-linux-64: + optional: true + esbuild-linux-arm: + optional: true + esbuild-linux-arm64: + optional: true + esbuild-linux-mips64le: + optional: true + esbuild-linux-ppc64le: + optional: true + esbuild-linux-riscv64: + optional: true + esbuild-linux-s390x: + optional: true + esbuild-netbsd-64: + optional: true + esbuild-openbsd-64: + optional: true + esbuild-sunos-64: + optional: true + esbuild-windows-32: + optional: true + esbuild-windows-64: + optional: true + esbuild-windows-arm64: + optional: true + bin: + esbuild: bin/esbuild + checksum: ec12682b2cb2d4f0669d0e555028b87a9284ca7f6a1b26e35e69a8697165b35cc682ad598abc70f0bbcfdc12ca84ef888caf5ceee389237862e8f8c17da85f89 + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -35337,7 +35568,7 @@ __metadata: languageName: node linkType: hard -"source-list-map@npm:^2.0.1": +"source-list-map@npm:^2.0.0": version: 2.0.1 resolution: "source-list-map@npm:2.0.1" checksum: 806efc6f75e7cd31e4815e7a3aaf75a45c704871ea4075cb2eb49882c6fca28998f44fc5ac91adb6de03b2882ee6fb02f951fdc85e6a22b338c32bfe19557938 @@ -38329,13 +38560,13 @@ __metadata: languageName: node linkType: hard -"webpack-sources@npm:^2.2.0": - version: 2.3.1 - resolution: "webpack-sources@npm:2.3.1" +"webpack-sources@npm:^1.4.3": + version: 1.4.3 + resolution: "webpack-sources@npm:1.4.3" dependencies: - source-list-map: ^2.0.1 - source-map: ^0.6.1 - checksum: 6fd67f2274a84c5f51ad89767112ec8b47727134bf0f2ba0cff458c970f18966939a24128bdbddba621cd66eeb2bef0552642a9333cd8e54514f7b2a71776346 + source-list-map: ^2.0.0 + source-map: ~0.6.1 + checksum: 37463dad8d08114930f4bc4882a9602941f07c9f0efa9b6bc78738cd936275b990a596d801ef450d022bb005b109b9f451dd087db2f3c9baf53e8e22cf388f79 languageName: node linkType: hard From 71c0aee2598883a0fa0ec479a4d591ca6ab42a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 14 Feb 2023 14:07:07 +0100 Subject: [PATCH 153/417] update the alpha warning blurbs in backend docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- docs/backend-system/architecture/01-index.md | 2 +- docs/backend-system/architecture/02-backends.md | 2 +- docs/backend-system/architecture/03-services.md | 2 +- docs/backend-system/architecture/04-plugins.md | 2 +- docs/backend-system/architecture/05-extension-points.md | 2 +- docs/backend-system/architecture/06-modules.md | 2 +- docs/backend-system/architecture/07-naming-patterns.md | 2 +- docs/backend-system/building-backends/01-index.md | 2 +- docs/backend-system/building-backends/08-migrating.md | 2 +- docs/backend-system/building-plugins-and-modules/01-index.md | 2 +- .../backend-system/building-plugins-and-modules/02-testing.md | 2 +- .../building-plugins-and-modules/08-migrating.md | 2 +- docs/backend-system/core-services/01-index.md | 2 +- docs/backend-system/index.md | 4 ++-- docs/plugins/new-backend-system.md | 4 ++-- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index a9f08c7907..76953f7009 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -6,7 +6,7 @@ sidebar_label: System Architecture description: The structure and architecture of the new Backend System and its component parts --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## Building Blocks diff --git a/docs/backend-system/architecture/02-backends.md b/docs/backend-system/architecture/02-backends.md index 53670aba12..b6079d71b4 100644 --- a/docs/backend-system/architecture/02-backends.md +++ b/docs/backend-system/architecture/02-backends.md @@ -6,7 +6,7 @@ sidebar_label: Backend description: Backend instances --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## The Backend Instance diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index 875cb3aaea..8a86d90efb 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -6,7 +6,7 @@ sidebar_label: Services description: Services for backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Backend services provide shared functionality available to all backend plugins and modules. They are made available through service references that embed a type that represents the service interface, similar to how [Utility APIs](../../api/utility-apis.md) work in the Backstage frontend system. To use a service in your plugin or module you request an implementation of that service using the service reference. diff --git a/docs/backend-system/architecture/04-plugins.md b/docs/backend-system/architecture/04-plugins.md index e73f086c43..04271b17da 100644 --- a/docs/backend-system/architecture/04-plugins.md +++ b/docs/backend-system/architecture/04-plugins.md @@ -6,7 +6,7 @@ sidebar_label: Plugins description: Backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Plugins provide the actual base features of a Backstage backend. Each plugin operates completely independently of all other plugins and they only communicate with each other through network calls. This means that there is a strong degree of isolation between plugins, and that each plugin can be considered a separate microservice. While a default Backstage project has all plugins installed within a single backend, it is also possible to split this setup into multiple backends, with each backend housing one or more plugins. diff --git a/docs/backend-system/architecture/05-extension-points.md b/docs/backend-system/architecture/05-extension-points.md index 278c565472..6d320037ba 100644 --- a/docs/backend-system/architecture/05-extension-points.md +++ b/docs/backend-system/architecture/05-extension-points.md @@ -6,7 +6,7 @@ sidebar_label: Extension Points description: Extension points of backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** While plugins are able to accept options for lightweight forms of customization and extension, you quickly hit a limit where you need something more powerful to allow users to extend your plugin. For this purpose, the backend system provides a mechanism for plugins to provide extension points, which can be used to expose deeper customizations for your plugin. Extension points are used by modules, which are installed in the backend adjacent to plugins. Modules are covered more in-depth in the [next section](./06-modules.md). diff --git a/docs/backend-system/architecture/06-modules.md b/docs/backend-system/architecture/06-modules.md index 2f359eaa75..53aae9e38d 100644 --- a/docs/backend-system/architecture/06-modules.md +++ b/docs/backend-system/architecture/06-modules.md @@ -6,7 +6,7 @@ sidebar_label: Modules description: Modules for backend plugins --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Backend modules are used to extend [plugins](./04-plugins.md) with additional features or change existing behavior. They must always be installed in the same backend instance as the plugin that they extend, and may only extend a single plugin. Modules interact with their target plugin using the [extension points](./05-extension-points.md) registered by the plugin, while also being able to depend on the [services](./03-services.md) of that plugin. diff --git a/docs/backend-system/architecture/07-naming-patterns.md b/docs/backend-system/architecture/07-naming-patterns.md index b62e049f08..b541cc09ba 100644 --- a/docs/backend-system/architecture/07-naming-patterns.md +++ b/docs/backend-system/architecture/07-naming-patterns.md @@ -6,7 +6,7 @@ sidebar_label: Naming Patterns description: Naming patterns in the backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** These are the naming patterns to adhere to within the backend system. They help us keep exports consistent across packages and make it easier to understand the usage and intent of exports. diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index bda2aa7eaa..65c536afdd 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -6,7 +6,7 @@ sidebar_label: Overview description: Building backends using the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** > NOTE: If you have an existing backend that is not yet using the new backend > system, see [migrating](./08-migrating.md). diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index e503d627ef..567476532f 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -6,7 +6,7 @@ sidebar_label: Migration Guide description: How to migrate existing backends to the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. As such, it is not considered stable, and it is not recommended to migrate production backends to the new backend system until it has a stable release.** ## Overview diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index cae5052d04..18cbabfe5d 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -6,7 +6,7 @@ sidebar_label: Overview description: Building backend plugins and modules using the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** > NOTE: If you have an existing backend and/or backend plugins that are not yet > using the new backend system, see [migrating](./08-migrating.md). diff --git a/docs/backend-system/building-plugins-and-modules/02-testing.md b/docs/backend-system/building-plugins-and-modules/02-testing.md index 37c5698512..7f93fab45b 100644 --- a/docs/backend-system/building-plugins-and-modules/02-testing.md +++ b/docs/backend-system/building-plugins-and-modules/02-testing.md @@ -6,7 +6,7 @@ sidebar_label: Testing description: Learn how to test your backend plugins and modules --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Utilities for testing backend plugins and modules are available in `@backstage/backend-test-utils`. This section describes those facilities. diff --git a/docs/backend-system/building-plugins-and-modules/08-migrating.md b/docs/backend-system/building-plugins-and-modules/08-migrating.md index 687f4c1d5e..cf5aa8106f 100644 --- a/docs/backend-system/building-plugins-and-modules/08-migrating.md +++ b/docs/backend-system/building-plugins-and-modules/08-migrating.md @@ -6,7 +6,7 @@ sidebar_label: Migration Guide description: How to migrate existing backend plugins to the new backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** Migrating an existing backend plugin to the new backend system is fairly straightforward. The process is similar across the majority of plugins which just return a `Router` that is then wired up in the `index.ts` file of your backend. The primary thing that we need to do is to make sure that the dependencies that are required by the plugin are available, and then registering the router with the HTTP router service. diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index b6682c2708..6448943e3a 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -6,7 +6,7 @@ sidebar_label: Core Services description: Core backend service APIs --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** The default backend provides several [core services](https://github.com/backstage/backstage/blob/master/packages/backend-plugin-api/src/services/definitions/coreServices.ts) out of the box which includes access to configuration, logging, URL Readers, databases and more. diff --git a/docs/backend-system/index.md b/docs/backend-system/index.md index de598167ae..d2d7c8e69e 100644 --- a/docs/backend-system/index.md +++ b/docs/backend-system/index.md @@ -6,10 +6,10 @@ sidebar_label: Overview description: The Backend System --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## Status -The new backend system is under active development, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. +The new backend system is in alpha, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. You can find an example backend setup in [the `backend-next` package](https://github.com/backstage/backstage/tree/master/packages/backend-next). diff --git a/docs/plugins/new-backend-system.md b/docs/plugins/new-backend-system.md index 785d364ae2..2ff061a60b 100644 --- a/docs/plugins/new-backend-system.md +++ b/docs/plugins/new-backend-system.md @@ -4,11 +4,11 @@ title: New Backend System description: Details of the upcoming backend system --- -> **DISCLAIMER: The new backend system is under active development and is not considered stable** +> **DISCLAIMER: The new backend system is in alpha, and still under active development. While we have reviewed the interfaces carefully, they may still be iterated on before the stable release.** ## Status -The new backend system is under active development, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. +The new backend system is in alpha, and only a small number of plugins have been migrated so far. It is possible to try it out, but it is not recommended to use this new system in production yet. You can find an example backend setup in [the backend-next package](https://github.com/backstage/backstage/tree/master/packages/backend-next). From 7afcb6773b292d861e04afa0321afb81b8277218 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:30:39 +0000 Subject: [PATCH 154/417] fix(deps): update dependency @swc/core to v1.3.35 Signed-off-by: Renovate Bot --- storybook/yarn.lock | 86 ++++++++++++++++++++++----------------------- yarn.lock | 86 ++++++++++++++++++++++----------------------- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/storybook/yarn.lock b/storybook/yarn.lock index f2e0f1c96a..9bcd4ed45c 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2966,90 +2966,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-darwin-arm64@npm:1.3.34" +"@swc/core-darwin-arm64@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-darwin-arm64@npm:1.3.35" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-darwin-x64@npm:1.3.34" +"@swc/core-darwin-x64@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-darwin-x64@npm:1.3.35" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.34" +"@swc/core-linux-arm-gnueabihf@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.35" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.34" +"@swc/core-linux-arm64-gnu@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.35" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.34" +"@swc/core-linux-arm64-musl@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.35" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.34" +"@swc/core-linux-x64-gnu@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.35" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-x64-musl@npm:1.3.34" +"@swc/core-linux-x64-musl@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-x64-musl@npm:1.3.35" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.34" +"@swc/core-win32-arm64-msvc@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.35" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.34" +"@swc/core-win32-ia32-msvc@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.35" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.34" +"@swc/core-win32-x64-msvc@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.35" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.34 - resolution: "@swc/core@npm:1.3.34" + version: 1.3.35 + resolution: "@swc/core@npm:1.3.35" dependencies: - "@swc/core-darwin-arm64": 1.3.34 - "@swc/core-darwin-x64": 1.3.34 - "@swc/core-linux-arm-gnueabihf": 1.3.34 - "@swc/core-linux-arm64-gnu": 1.3.34 - "@swc/core-linux-arm64-musl": 1.3.34 - "@swc/core-linux-x64-gnu": 1.3.34 - "@swc/core-linux-x64-musl": 1.3.34 - "@swc/core-win32-arm64-msvc": 1.3.34 - "@swc/core-win32-ia32-msvc": 1.3.34 - "@swc/core-win32-x64-msvc": 1.3.34 + "@swc/core-darwin-arm64": 1.3.35 + "@swc/core-darwin-x64": 1.3.35 + "@swc/core-linux-arm-gnueabihf": 1.3.35 + "@swc/core-linux-arm64-gnu": 1.3.35 + "@swc/core-linux-arm64-musl": 1.3.35 + "@swc/core-linux-x64-gnu": 1.3.35 + "@swc/core-linux-x64-musl": 1.3.35 + "@swc/core-win32-arm64-msvc": 1.3.35 + "@swc/core-win32-ia32-msvc": 1.3.35 + "@swc/core-win32-x64-msvc": 1.3.35 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -3071,7 +3071,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: a77c286b6b34d40f634ae882aac66f882cf806c165453878c31311070c46f020c607925bd454f64959504f08852b204cc37feba93fc6a3c1a64b295a9b5007d6 + checksum: 263e01904fe4f4d6cbf6deef90439d6d93f28c04252d917fc290aadde131a1716820eb488a615b3c0dbe3f48d6d7ac0f1c886e2c2acd07a72e3d99e4a245b3de languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index af1a8fd1b0..d8e92c6e12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13521,90 +13521,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-darwin-arm64@npm:1.3.34" +"@swc/core-darwin-arm64@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-darwin-arm64@npm:1.3.35" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-darwin-x64@npm:1.3.34" +"@swc/core-darwin-x64@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-darwin-x64@npm:1.3.35" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.34" +"@swc/core-linux-arm-gnueabihf@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.35" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.34" +"@swc/core-linux-arm64-gnu@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.35" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.34" +"@swc/core-linux-arm64-musl@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.35" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.34" +"@swc/core-linux-x64-gnu@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.35" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-linux-x64-musl@npm:1.3.34" +"@swc/core-linux-x64-musl@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-linux-x64-musl@npm:1.3.35" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.34" +"@swc/core-win32-arm64-msvc@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.35" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.34" +"@swc/core-win32-ia32-msvc@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.35" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.34": - version: 1.3.34 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.34" +"@swc/core-win32-x64-msvc@npm:1.3.35": + version: 1.3.35 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.35" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.34 - resolution: "@swc/core@npm:1.3.34" + version: 1.3.35 + resolution: "@swc/core@npm:1.3.35" dependencies: - "@swc/core-darwin-arm64": 1.3.34 - "@swc/core-darwin-x64": 1.3.34 - "@swc/core-linux-arm-gnueabihf": 1.3.34 - "@swc/core-linux-arm64-gnu": 1.3.34 - "@swc/core-linux-arm64-musl": 1.3.34 - "@swc/core-linux-x64-gnu": 1.3.34 - "@swc/core-linux-x64-musl": 1.3.34 - "@swc/core-win32-arm64-msvc": 1.3.34 - "@swc/core-win32-ia32-msvc": 1.3.34 - "@swc/core-win32-x64-msvc": 1.3.34 + "@swc/core-darwin-arm64": 1.3.35 + "@swc/core-darwin-x64": 1.3.35 + "@swc/core-linux-arm-gnueabihf": 1.3.35 + "@swc/core-linux-arm64-gnu": 1.3.35 + "@swc/core-linux-arm64-musl": 1.3.35 + "@swc/core-linux-x64-gnu": 1.3.35 + "@swc/core-linux-x64-musl": 1.3.35 + "@swc/core-win32-arm64-msvc": 1.3.35 + "@swc/core-win32-ia32-msvc": 1.3.35 + "@swc/core-win32-x64-msvc": 1.3.35 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -13626,7 +13626,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: a77c286b6b34d40f634ae882aac66f882cf806c165453878c31311070c46f020c607925bd454f64959504f08852b204cc37feba93fc6a3c1a64b295a9b5007d6 + checksum: 263e01904fe4f4d6cbf6deef90439d6d93f28c04252d917fc290aadde131a1716820eb488a615b3c0dbe3f48d6d7ac0f1c886e2c2acd07a72e3d99e4a245b3de languageName: node linkType: hard From 25b57cc07f620aae4a2b7174133e347307de228e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 14 Feb 2023 13:41:52 +0000 Subject: [PATCH 155/417] Version Packages --- .changeset/afraid-foxes-provide.md | 5 - .changeset/afraid-planets-crash.md | 5 - .changeset/big-bags-glow.md | 5 - .changeset/brave-cougars-burn.md | 6 - .changeset/brave-lemons-chew.md | 6 - .changeset/breezy-ears-rule.md | 5 - .changeset/bright-eagles-love.md | 5 - .changeset/bright-plums-cough.md | 5 - .changeset/bright-teachers-compete.md | 5 - .changeset/brown-islands-own.md | 5 - .changeset/brown-kings-wait.md | 5 - .changeset/calm-avocados-exercise.md | 5 - .changeset/chatty-lemons-reply.md | 5 - .changeset/chatty-owls-care.md | 5 - .changeset/chilled-brooms-jog.md | 7 - .changeset/chilled-sheep-collect.md | 5 - .changeset/clean-queens-judge.md | 5 - .changeset/cold-cycles-switch.md | 5 - .changeset/cool-radios-hope.md | 6 - .changeset/cool-spoons-bathe.md | 5 - .changeset/create-app-1674561612.md | 5 - .changeset/cuddly-boxes-agree.md | 5 - .changeset/cyan-deers-walk.md | 5 - .changeset/dry-donkeys-cheer.md | 5 - .changeset/dull-fishes-suffer.md | 5 - .changeset/dull-gorillas-sing.md | 5 - .changeset/dull-pianos-shave.md | 5 - .changeset/eight-falcons-explode.md | 5 - .changeset/eight-hotels-sparkle.md | 5 - .changeset/eight-vans-drum.md | 5 - .changeset/eighty-knives-repeat.md | 6 - .changeset/eleven-shoes-crash.md | 6 - .changeset/empty-games-cheer.md | 22 - .changeset/famous-squids-wonder.md | 5 - .changeset/few-meals-buy.md | 5 - .changeset/few-moons-accept.md | 5 - .changeset/few-trees-cross.md | 5 - .changeset/flat-cups-itch.md | 6 - .changeset/flat-lizards-poke.md | 10 - .changeset/four-candles-add.md | 18 - .changeset/four-rivers-enjoy.md | 5 - .changeset/four-tables-fix.md | 5 - .changeset/friendly-chefs-rule.md | 5 - .changeset/friendly-scissors-shop.md | 12 - .changeset/gold-bulldogs-talk.md | 5 - .changeset/gold-lemons-eat.md | 5 - .changeset/gold-masks-sleep.md | 5 - .changeset/gorgeous-ligers-burn.md | 5 - .changeset/gorgeous-llamas-mate.md | 7 - .changeset/great-goats-talk.md | 5 - .changeset/green-adults-retire.md | 5 - .changeset/green-guests-flow.md | 8 - .changeset/grumpy-bottles-stare.md | 6 - .changeset/grumpy-fireants-drop.md | 5 - .changeset/happy-cows-moo.md | 5 - .changeset/heavy-comics-applaud.md | 5 - .changeset/hip-chairs-double.md | 19 - .changeset/hip-onions-tan.md | 5 - .changeset/hip-pugs-teach.md | 12 - .changeset/hip-tables-prove.md | 5 - .changeset/honest-timers-pull.md | 6 - .changeset/hot-lions-cover.md | 5 - .changeset/hot-wasps-cover.md | 5 - .changeset/hungry-news-fix.md | 5 - .changeset/hungry-stingrays-type.md | 5 - .changeset/itchy-chairs-punch.md | 5 - .changeset/itchy-goats-melt.md | 8 - .changeset/itchy-rings-rule.md | 5 - .changeset/khaki-toes-care.md | 5 - .changeset/late-rice-crash.md | 5 - .changeset/lazy-badgers-rule.md | 5 - .changeset/lazy-badgers-try.md | 5 - .changeset/lemon-tables-train.md | 5 - .changeset/light-crabs-drum.md | 6 - .changeset/little-jars-lay.md | 14 - .changeset/long-chefs-burn.md | 5 - .changeset/lovely-ladybugs-taste.md | 10 - .changeset/lucky-papayas-allow.md | 5 - .changeset/many-nails-joke.md | 5 - .changeset/many-pans-unite.md | 5 - .changeset/mean-squids-kneel.md | 5 - .changeset/modern-cats-worry.md | 5 - .changeset/nasty-beans-accept.md | 5 - .changeset/nasty-kids-deny.md | 5 - .changeset/neat-schools-raise.md | 5 - .changeset/neat-zebras-run.md | 5 - .changeset/nervous-apricots-whisper.md | 5 - .changeset/nervous-mangos-rhyme.md | 5 - .changeset/nervous-phones-shout.md | 6 - .changeset/new-pumpkins-sleep.md | 6 - .changeset/nine-glasses-invent.md | 5 - .changeset/nine-guests-compete.md | 5 - .changeset/nine-ravens-kiss.md | 5 - .changeset/ninety-hats-serve.md | 30 - .changeset/odd-kangaroos-itch.md | 5 - .changeset/old-knives-wonder.md | 5 - .changeset/old-ways-know.md | 5 - .changeset/olive-ads-peel.md | 5 - .changeset/perfect-cheetahs-serve.md | 5 - .changeset/perfect-pears-care.md | 7 - .changeset/pink-falcons-serve.md | 6 - .changeset/poor-moons-confess.md | 5 - .changeset/popular-dancers-join.md | 5 - .changeset/pre.json | 343 -- .changeset/pretty-icons-glow.md | 8 - .changeset/pretty-jars-peel.md | 9 - .changeset/pretty-ladybugs-taste.md | 5 - .changeset/proud-glasses-live.md | 5 - .changeset/purple-feet-smile.md | 5 - .changeset/purple-panthers-know.md | 5 - .changeset/quick-ladybugs-reply.md | 6 - .changeset/quick-mice-change.md | 6 - .changeset/quiet-pets-count.md | 6 - .changeset/rare-berries-give.md | 5 - .changeset/rare-melons-battle.md | 5 - .changeset/red-kiwis-compare.md | 5 - .changeset/red-pugs-tap.md | 5 - .changeset/red-toes-suffer.md | 9 - .changeset/renovate-0b349f9.md | 8 - .changeset/renovate-0c3644c.md | 6 - .changeset/renovate-53e8b07.md | 5 - .changeset/rich-bags-sleep.md | 5 - .changeset/rich-snakes-rest.md | 5 - .changeset/rotten-birds-build.md | 7 - .changeset/rotten-mayflies-love.md | 5 - .changeset/selfish-frogs-punch.md | 5 - .changeset/serious-grapes-brush.md | 5 - .changeset/serious-horses-juggle.md | 7 - .changeset/serious-pigs-watch.md | 10 - .changeset/sharp-lobsters-build.md | 10 - .changeset/shiny-years-tap.md | 5 - .changeset/short-apes-relate.md | 5 - .changeset/shy-buses-mix.md | 5 - .changeset/shy-steaks-invite.md | 16 - .changeset/silent-peas-fly.md | 5 - .changeset/silent-roses-join.md | 5 - .changeset/silly-buckets-joke.md | 5 - .changeset/silly-socks-lie.md | 5 - .changeset/silly-turkeys-hang.md | 6 - .changeset/silver-badgers-heal.md | 35 - .changeset/silver-wolves-breathe.md | 5 - .changeset/slow-carrots-sniff.md | 8 - .changeset/slow-moles-sin.md | 5 - .changeset/slow-sloths-do.md | 5 - .changeset/smart-dingos-raise.md | 5 - .changeset/soft-actors-worry.md | 5 - .changeset/soft-boxes-buy.md | 5 - .changeset/soft-snails-notice.md | 5 - .changeset/spotty-coats-clean.md | 5 - .changeset/spotty-spiders-love.md | 5 - .changeset/stale-dots-smile.md | 5 - .changeset/stale-experts-punch.md | 9 - .changeset/stale-houses-push.md | 5 - .changeset/stupid-ladybugs-brake.md | 6 - .changeset/sweet-yaks-taste.md | 5 - .changeset/swift-fishes-smash.md | 5 - .changeset/tall-falcons-teach.md | 5 - .changeset/tall-tables-hide.md | 5 - .changeset/tall-years-relate.md | 5 - .changeset/tasty-jobs-help.md | 7 - .changeset/thick-clocks-pump.md | 5 - .changeset/thick-tables-travel.md | 5 - .changeset/thin-donkeys-attack.md | 5 - .changeset/thin-scissors-press.md | 6 - .changeset/three-geckos-press.md | 5 - .changeset/tidy-kids-hide.md | 7 - .changeset/tidy-kings-cough.md | 5 - .changeset/tough-jeans-camp.md | 5 - .changeset/twenty-islands-wonder.md | 5 - .changeset/twenty-parents-relate.md | 5 - .changeset/twenty-pugs-explain.md | 5 - .changeset/two-melons-lie.md | 5 - .changeset/violet-tips-rhyme.md | 5 - .changeset/weak-radios-sing.md | 5 - .changeset/wicked-beers-walk.md | 5 - .changeset/wild-donkeys-rescue.md | 6 - .changeset/wild-melons-shout.md | 5 - .changeset/witty-moose-itch.md | 5 - .changeset/yellow-roses-tell.md | 5 - .changeset/young-beans-float.md | 24 - .changeset/young-points-drop.md | 5 - .changeset/young-singers-learn.md | 5 - docs/releases/v1.11.0-changelog.md | 2876 +++++++++++++++++ package.json | 2 +- packages/app-defaults/CHANGELOG.md | 15 + packages/app-defaults/package.json | 2 +- packages/app/CHANGELOG.md | 68 + packages/app/package.json | 2 +- packages/backend-app-api/CHANGELOG.md | 33 + packages/backend-app-api/package.json | 2 +- packages/backend-common/CHANGELOG.md | 25 + packages/backend-common/package.json | 2 +- packages/backend-defaults/CHANGELOG.md | 10 + packages/backend-defaults/package.json | 2 +- packages/backend-dev-utils/CHANGELOG.md | 10 + packages/backend-dev-utils/package.json | 2 +- packages/backend-next/CHANGELOG.md | 10 + packages/backend-next/package.json | 2 +- packages/backend-plugin-api/CHANGELOG.md | 29 + packages/backend-plugin-api/package.json | 2 +- packages/backend-tasks/CHANGELOG.md | 10 + packages/backend-tasks/package.json | 2 +- packages/backend-test-utils/CHANGELOG.md | 24 + packages/backend-test-utils/package.json | 2 +- packages/backend/CHANGELOG.md | 51 + packages/backend/package.json | 2 +- packages/catalog-client/CHANGELOG.md | 8 + packages/catalog-client/package.json | 2 +- packages/catalog-model/CHANGELOG.md | 15 + packages/catalog-model/package.json | 2 +- packages/cli/CHANGELOG.md | 20 + packages/cli/package.json | 2 +- packages/codemods/CHANGELOG.md | 8 + packages/codemods/package.json | 2 +- packages/core-app-api/CHANGELOG.md | 15 + packages/core-app-api/package.json | 2 +- packages/core-components/CHANGELOG.md | 18 + packages/core-components/package.json | 2 +- packages/core-plugin-api/CHANGELOG.md | 13 + packages/core-plugin-api/package.json | 2 +- packages/create-app/CHANGELOG.md | 11 + packages/create-app/package.json | 2 +- packages/dev-utils/CHANGELOG.md | 15 + packages/dev-utils/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 6 + packages/eslint-plugin/package.json | 2 +- packages/integration-react/CHANGELOG.md | 11 + packages/integration-react/package.json | 2 +- packages/repo-tools/CHANGELOG.md | 9 + packages/repo-tools/package.json | 2 +- .../techdocs-cli-embedded-app/CHANGELOG.md | 19 + .../techdocs-cli-embedded-app/package.json | 2 +- packages/techdocs-cli/CHANGELOG.md | 22 + packages/techdocs-cli/package.json | 2 +- packages/test-utils/CHANGELOG.md | 13 + packages/test-utils/package.json | 2 +- packages/theme/CHANGELOG.md | 6 + packages/theme/package.json | 2 +- plugins/adr-backend/CHANGELOG.md | 19 + plugins/adr-backend/package.json | 2 +- plugins/adr-common/CHANGELOG.md | 9 + plugins/adr-common/package.json | 2 +- plugins/adr/CHANGELOG.md | 22 + plugins/adr/package.json | 2 +- plugins/airbrake-backend/CHANGELOG.md | 8 + plugins/airbrake-backend/package.json | 2 +- plugins/airbrake/CHANGELOG.md | 14 + plugins/airbrake/package.json | 2 +- plugins/allure/CHANGELOG.md | 12 + plugins/allure/package.json | 2 +- plugins/analytics-module-ga/CHANGELOG.md | 11 + plugins/analytics-module-ga/package.json | 2 +- plugins/apache-airflow/CHANGELOG.md | 10 + plugins/apache-airflow/package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- plugins/api-docs/CHANGELOG.md | 18 + plugins/api-docs/package.json | 2 +- plugins/apollo-explorer/CHANGELOG.md | 10 + plugins/apollo-explorer/package.json | 2 +- plugins/app-backend/CHANGELOG.md | 12 + plugins/app-backend/package.json | 2 +- plugins/auth-backend/CHANGELOG.md | 17 + plugins/auth-backend/package.json | 2 +- plugins/auth-node/CHANGELOG.md | 9 + plugins/auth-node/package.json | 2 +- plugins/azure-devops-backend/CHANGELOG.md | 12 + plugins/azure-devops-backend/package.json | 2 +- plugins/azure-devops/CHANGELOG.md | 14 + plugins/azure-devops/package.json | 2 +- plugins/azure-sites-backend/CHANGELOG.md | 10 + plugins/azure-sites-backend/package.json | 2 +- plugins/azure-sites/CHANGELOG.md | 16 + plugins/azure-sites/package.json | 2 +- plugins/badges-backend/CHANGELOG.md | 11 + plugins/badges-backend/package.json | 2 +- plugins/badges/CHANGELOG.md | 12 + plugins/badges/package.json | 2 +- plugins/bazaar-backend/CHANGELOG.md | 14 + plugins/bazaar-backend/package.json | 2 +- plugins/bazaar/CHANGELOG.md | 15 + plugins/bazaar/package.json | 2 +- plugins/bitrise/CHANGELOG.md | 12 + plugins/bitrise/package.json | 2 +- .../catalog-backend-module-aws/CHANGELOG.md | 18 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 44 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 18 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 15 + .../package.json | 2 +- .../CHANGELOG.md | 22 + .../package.json | 2 +- .../CHANGELOG.md | 19 + .../package.json | 2 +- .../CHANGELOG.md | 25 + .../package.json | 2 +- .../catalog-backend-module-ldap/CHANGELOG.md | 12 + .../catalog-backend-module-ldap/package.json | 2 +- .../CHANGELOG.md | 24 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- plugins/catalog-backend/CHANGELOG.md | 29 + plugins/catalog-backend/package.json | 2 +- plugins/catalog-common/CHANGELOG.md | 9 + plugins/catalog-common/package.json | 2 +- plugins/catalog-customized/CHANGELOG.md | 8 + plugins/catalog-customized/package.json | 2 +- plugins/catalog-graph/CHANGELOG.md | 15 + plugins/catalog-graph/package.json | 2 +- plugins/catalog-graphql/CHANGELOG.md | 9 + plugins/catalog-graphql/package.json | 2 +- plugins/catalog-import/CHANGELOG.md | 16 + plugins/catalog-import/package.json | 2 +- plugins/catalog-node/CHANGELOG.md | 12 + plugins/catalog-node/package.json | 2 +- plugins/catalog-react/CHANGELOG.md | 23 + plugins/catalog-react/package.json | 2 +- plugins/catalog/CHANGELOG.md | 29 + plugins/catalog/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/cicd-statistics/CHANGELOG.md | 10 + plugins/cicd-statistics/package.json | 2 +- plugins/circleci/CHANGELOG.md | 13 + plugins/circleci/package.json | 2 +- plugins/cloudbuild/CHANGELOG.md | 11 + plugins/cloudbuild/package.json | 2 +- plugins/code-climate/CHANGELOG.md | 11 + plugins/code-climate/package.json | 2 +- plugins/code-coverage-backend/CHANGELOG.md | 13 + plugins/code-coverage-backend/package.json | 2 +- plugins/code-coverage/CHANGELOG.md | 14 + plugins/code-coverage/package.json | 2 +- plugins/codescene/CHANGELOG.md | 12 + plugins/codescene/package.json | 2 +- plugins/config-schema/CHANGELOG.md | 12 + plugins/config-schema/package.json | 2 +- plugins/cost-insights/CHANGELOG.md | 14 + plugins/cost-insights/package.json | 2 +- plugins/dynatrace/CHANGELOG.md | 12 + plugins/dynatrace/package.json | 2 +- plugins/entity-feedback-backend/CHANGELOG.md | 17 + plugins/entity-feedback-backend/package.json | 2 +- plugins/entity-feedback-common/CHANGELOG.md | 7 + plugins/entity-feedback-common/package.json | 2 +- plugins/entity-feedback/CHANGELOG.md | 18 + plugins/entity-feedback/package.json | 2 +- plugins/entity-validation/CHANGELOG.md | 18 + plugins/entity-validation/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- .../events-backend-module-azure/CHANGELOG.md | 8 + .../events-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../events-backend-module-gerrit/CHANGELOG.md | 8 + .../events-backend-module-gerrit/package.json | 2 +- .../events-backend-module-github/CHANGELOG.md | 9 + .../events-backend-module-github/package.json | 2 +- .../events-backend-module-gitlab/CHANGELOG.md | 9 + .../events-backend-module-gitlab/package.json | 2 +- .../events-backend-test-utils/CHANGELOG.md | 7 + .../events-backend-test-utils/package.json | 2 +- plugins/events-backend/CHANGELOG.md | 11 + plugins/events-backend/package.json | 2 +- plugins/events-node/CHANGELOG.md | 8 + plugins/events-node/package.json | 2 +- .../example-todo-list-backend/CHANGELOG.md | 11 + .../example-todo-list-backend/package.json | 2 +- plugins/example-todo-list/CHANGELOG.md | 9 + plugins/example-todo-list/package.json | 2 +- plugins/explore-backend/CHANGELOG.md | 10 + plugins/explore-backend/package.json | 2 +- plugins/explore-react/CHANGELOG.md | 8 + plugins/explore-react/package.json | 2 +- plugins/explore/CHANGELOG.md | 24 + plugins/explore/package.json | 2 +- plugins/firehydrant/CHANGELOG.md | 10 + plugins/firehydrant/package.json | 2 +- plugins/fossa/CHANGELOG.md | 12 + plugins/fossa/package.json | 2 +- plugins/gcalendar/CHANGELOG.md | 10 + plugins/gcalendar/package.json | 2 +- plugins/gcp-projects/CHANGELOG.md | 9 + plugins/gcp-projects/package.json | 2 +- plugins/git-release-manager/CHANGELOG.md | 11 + plugins/git-release-manager/package.json | 2 +- plugins/github-actions/CHANGELOG.md | 12 + plugins/github-actions/package.json | 2 +- plugins/github-deployments/CHANGELOG.md | 14 + plugins/github-deployments/package.json | 2 +- plugins/github-issues/CHANGELOG.md | 14 + plugins/github-issues/package.json | 2 +- .../github-pull-requests-board/CHANGELOG.md | 12 + .../github-pull-requests-board/package.json | 2 +- plugins/gitops-profiles/CHANGELOG.md | 9 + plugins/gitops-profiles/package.json | 2 +- plugins/gocd/CHANGELOG.md | 12 + plugins/gocd/package.json | 2 +- plugins/graphiql/CHANGELOG.md | 9 + plugins/graphiql/package.json | 2 +- plugins/graphql-backend/CHANGELOG.md | 9 + plugins/graphql-backend/package.json | 2 +- plugins/graphql-voyager/CHANGELOG.md | 15 + plugins/graphql-voyager/package.json | 2 +- plugins/home/CHANGELOG.md | 15 + plugins/home/package.json | 2 +- plugins/ilert/CHANGELOG.md | 13 + plugins/ilert/package.json | 2 +- plugins/jenkins-backend/CHANGELOG.md | 14 + plugins/jenkins-backend/package.json | 2 +- plugins/jenkins-common/CHANGELOG.md | 8 + plugins/jenkins-common/package.json | 2 +- plugins/jenkins/CHANGELOG.md | 13 + plugins/jenkins/package.json | 2 +- plugins/kafka-backend/CHANGELOG.md | 13 + plugins/kafka-backend/package.json | 2 +- plugins/kafka/CHANGELOG.md | 12 + plugins/kafka/package.json | 2 +- plugins/kubernetes-backend/CHANGELOG.md | 18 + plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes-common/CHANGELOG.md | 13 + plugins/kubernetes-common/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 15 + plugins/kubernetes/package.json | 2 +- plugins/lighthouse-backend/CHANGELOG.md | 17 + plugins/lighthouse-backend/package.json | 2 +- plugins/lighthouse-common/CHANGELOG.md | 11 + plugins/lighthouse-common/package.json | 2 +- plugins/lighthouse/CHANGELOG.md | 38 + plugins/lighthouse/package.json | 2 +- plugins/linguist-backend/CHANGELOG.md | 20 + plugins/linguist-backend/package.json | 2 +- plugins/linguist-common/CHANGELOG.md | 7 + plugins/linguist-common/package.json | 2 +- plugins/linguist/CHANGELOG.md | 18 + plugins/linguist/package.json | 2 +- plugins/microsoft-calendar/CHANGELOG.md | 18 + plugins/microsoft-calendar/package.json | 2 +- plugins/newrelic-dashboard/CHANGELOG.md | 11 + plugins/newrelic-dashboard/package.json | 2 +- plugins/newrelic/CHANGELOG.md | 9 + plugins/newrelic/package.json | 2 +- plugins/org-react/CHANGELOG.md | 13 + plugins/org-react/package.json | 2 +- plugins/org/CHANGELOG.md | 12 + plugins/org/package.json | 2 +- plugins/pagerduty/CHANGELOG.md | 13 + plugins/pagerduty/package.json | 2 +- plugins/periskop-backend/CHANGELOG.md | 11 + plugins/periskop-backend/package.json | 2 +- plugins/periskop/CHANGELOG.md | 12 + plugins/periskop/package.json | 2 +- plugins/permission-backend/CHANGELOG.md | 12 + plugins/permission-backend/package.json | 2 +- plugins/permission-node/CHANGELOG.md | 11 + plugins/permission-node/package.json | 2 +- plugins/permission-react/CHANGELOG.md | 9 + plugins/permission-react/package.json | 2 +- plugins/playlist-backend/CHANGELOG.md | 18 + plugins/playlist-backend/package.json | 2 +- plugins/playlist/CHANGELOG.md | 18 + plugins/playlist/package.json | 2 +- plugins/proxy-backend/CHANGELOG.md | 11 + plugins/proxy-backend/package.json | 2 +- plugins/rollbar-backend/CHANGELOG.md | 8 + plugins/rollbar-backend/package.json | 2 +- plugins/rollbar/CHANGELOG.md | 11 + plugins/rollbar/package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- plugins/scaffolder-backend/CHANGELOG.md | 35 + plugins/scaffolder-backend/package.json | 2 +- plugins/scaffolder-common/CHANGELOG.md | 8 + plugins/scaffolder-common/package.json | 2 +- plugins/scaffolder-node/CHANGELOG.md | 14 + plugins/scaffolder-node/package.json | 2 +- plugins/scaffolder-react/CHANGELOG.md | 29 + plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 44 + plugins/scaffolder/package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- plugins/search-backend-module-pg/CHANGELOG.md | 10 + plugins/search-backend-module-pg/package.json | 2 +- plugins/search-backend-node/CHANGELOG.md | 12 + plugins/search-backend-node/package.json | 2 +- plugins/search-backend/CHANGELOG.md | 16 + plugins/search-backend/package.json | 2 +- plugins/search-react/CHANGELOG.md | 21 + plugins/search-react/package.json | 2 +- plugins/search/CHANGELOG.md | 23 + plugins/search/package.json | 2 +- plugins/sentry/CHANGELOG.md | 16 + plugins/sentry/package.json | 2 +- plugins/shortcuts/CHANGELOG.md | 11 + plugins/shortcuts/package.json | 2 +- plugins/sonarqube-backend/CHANGELOG.md | 9 + plugins/sonarqube-backend/package.json | 2 +- plugins/sonarqube-react/CHANGELOG.md | 8 + plugins/sonarqube-react/package.json | 2 +- plugins/sonarqube/CHANGELOG.md | 13 + plugins/sonarqube/package.json | 2 +- plugins/splunk-on-call/CHANGELOG.md | 12 + plugins/splunk-on-call/package.json | 2 +- plugins/stack-overflow-backend/CHANGELOG.md | 9 + plugins/stack-overflow-backend/package.json | 2 +- plugins/stack-overflow/CHANGELOG.md | 13 + plugins/stack-overflow/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- plugins/tech-insights-backend/CHANGELOG.md | 27 + plugins/tech-insights-backend/package.json | 2 +- plugins/tech-insights-common/CHANGELOG.md | 19 + plugins/tech-insights-common/package.json | 2 +- plugins/tech-insights-node/CHANGELOG.md | 25 + plugins/tech-insights-node/package.json | 2 +- plugins/tech-insights/CHANGELOG.md | 26 + plugins/tech-insights/package.json | 2 +- plugins/tech-radar/CHANGELOG.md | 26 + plugins/tech-radar/package.json | 2 +- .../techdocs-addons-test-utils/CHANGELOG.md | 17 + .../techdocs-addons-test-utils/package.json | 2 +- plugins/techdocs-backend/CHANGELOG.md | 18 + plugins/techdocs-backend/package.json | 2 +- .../CHANGELOG.md | 44 + .../package.json | 2 +- plugins/techdocs-node/CHANGELOG.md | 19 + plugins/techdocs-node/package.json | 2 +- plugins/techdocs-react/CHANGELOG.md | 11 + plugins/techdocs-react/package.json | 2 +- plugins/techdocs/CHANGELOG.md | 60 + plugins/techdocs/package.json | 2 +- plugins/todo-backend/CHANGELOG.md | 12 + plugins/todo-backend/package.json | 2 +- plugins/todo/CHANGELOG.md | 12 + plugins/todo/package.json | 2 +- plugins/user-settings-backend/CHANGELOG.md | 14 + plugins/user-settings-backend/package.json | 2 +- plugins/user-settings/CHANGELOG.md | 18 + plugins/user-settings/package.json | 2 +- plugins/vault-backend/CHANGELOG.md | 11 + plugins/vault-backend/package.json | 2 +- plugins/vault/CHANGELOG.md | 13 + plugins/vault/package.json | 2 +- plugins/xcmetrics/CHANGELOG.md | 11 + plugins/xcmetrics/package.json | 2 +- yarn.lock | 242 +- 561 files changed, 5946 insertions(+), 1898 deletions(-) delete mode 100644 .changeset/afraid-foxes-provide.md delete mode 100644 .changeset/afraid-planets-crash.md delete mode 100644 .changeset/big-bags-glow.md delete mode 100644 .changeset/brave-cougars-burn.md delete mode 100644 .changeset/brave-lemons-chew.md delete mode 100644 .changeset/breezy-ears-rule.md delete mode 100644 .changeset/bright-eagles-love.md delete mode 100644 .changeset/bright-plums-cough.md delete mode 100644 .changeset/bright-teachers-compete.md delete mode 100644 .changeset/brown-islands-own.md delete mode 100644 .changeset/brown-kings-wait.md delete mode 100644 .changeset/calm-avocados-exercise.md delete mode 100644 .changeset/chatty-lemons-reply.md delete mode 100644 .changeset/chatty-owls-care.md delete mode 100644 .changeset/chilled-brooms-jog.md delete mode 100644 .changeset/chilled-sheep-collect.md delete mode 100644 .changeset/clean-queens-judge.md delete mode 100644 .changeset/cold-cycles-switch.md delete mode 100644 .changeset/cool-radios-hope.md delete mode 100644 .changeset/cool-spoons-bathe.md delete mode 100644 .changeset/create-app-1674561612.md delete mode 100644 .changeset/cuddly-boxes-agree.md delete mode 100644 .changeset/cyan-deers-walk.md delete mode 100644 .changeset/dry-donkeys-cheer.md delete mode 100644 .changeset/dull-fishes-suffer.md delete mode 100644 .changeset/dull-gorillas-sing.md delete mode 100644 .changeset/dull-pianos-shave.md delete mode 100644 .changeset/eight-falcons-explode.md delete mode 100644 .changeset/eight-hotels-sparkle.md delete mode 100644 .changeset/eight-vans-drum.md delete mode 100644 .changeset/eighty-knives-repeat.md delete mode 100644 .changeset/eleven-shoes-crash.md delete mode 100644 .changeset/empty-games-cheer.md delete mode 100644 .changeset/famous-squids-wonder.md delete mode 100644 .changeset/few-meals-buy.md delete mode 100644 .changeset/few-moons-accept.md delete mode 100644 .changeset/few-trees-cross.md delete mode 100644 .changeset/flat-cups-itch.md delete mode 100644 .changeset/flat-lizards-poke.md delete mode 100644 .changeset/four-candles-add.md delete mode 100644 .changeset/four-rivers-enjoy.md delete mode 100644 .changeset/four-tables-fix.md delete mode 100644 .changeset/friendly-chefs-rule.md delete mode 100644 .changeset/friendly-scissors-shop.md delete mode 100644 .changeset/gold-bulldogs-talk.md delete mode 100644 .changeset/gold-lemons-eat.md delete mode 100644 .changeset/gold-masks-sleep.md delete mode 100644 .changeset/gorgeous-ligers-burn.md delete mode 100644 .changeset/gorgeous-llamas-mate.md delete mode 100644 .changeset/great-goats-talk.md delete mode 100644 .changeset/green-adults-retire.md delete mode 100644 .changeset/green-guests-flow.md delete mode 100644 .changeset/grumpy-bottles-stare.md delete mode 100644 .changeset/grumpy-fireants-drop.md delete mode 100644 .changeset/happy-cows-moo.md delete mode 100644 .changeset/heavy-comics-applaud.md delete mode 100644 .changeset/hip-chairs-double.md delete mode 100644 .changeset/hip-onions-tan.md delete mode 100644 .changeset/hip-pugs-teach.md delete mode 100644 .changeset/hip-tables-prove.md delete mode 100644 .changeset/honest-timers-pull.md delete mode 100644 .changeset/hot-lions-cover.md delete mode 100644 .changeset/hot-wasps-cover.md delete mode 100644 .changeset/hungry-news-fix.md delete mode 100644 .changeset/hungry-stingrays-type.md delete mode 100644 .changeset/itchy-chairs-punch.md delete mode 100644 .changeset/itchy-goats-melt.md delete mode 100644 .changeset/itchy-rings-rule.md delete mode 100644 .changeset/khaki-toes-care.md delete mode 100644 .changeset/late-rice-crash.md delete mode 100644 .changeset/lazy-badgers-rule.md delete mode 100644 .changeset/lazy-badgers-try.md delete mode 100644 .changeset/lemon-tables-train.md delete mode 100644 .changeset/light-crabs-drum.md delete mode 100644 .changeset/little-jars-lay.md delete mode 100644 .changeset/long-chefs-burn.md delete mode 100644 .changeset/lovely-ladybugs-taste.md delete mode 100644 .changeset/lucky-papayas-allow.md delete mode 100644 .changeset/many-nails-joke.md delete mode 100644 .changeset/many-pans-unite.md delete mode 100644 .changeset/mean-squids-kneel.md delete mode 100644 .changeset/modern-cats-worry.md delete mode 100644 .changeset/nasty-beans-accept.md delete mode 100644 .changeset/nasty-kids-deny.md delete mode 100644 .changeset/neat-schools-raise.md delete mode 100644 .changeset/neat-zebras-run.md delete mode 100644 .changeset/nervous-apricots-whisper.md delete mode 100644 .changeset/nervous-mangos-rhyme.md delete mode 100644 .changeset/nervous-phones-shout.md delete mode 100644 .changeset/new-pumpkins-sleep.md delete mode 100644 .changeset/nine-glasses-invent.md delete mode 100644 .changeset/nine-guests-compete.md delete mode 100644 .changeset/nine-ravens-kiss.md delete mode 100644 .changeset/ninety-hats-serve.md delete mode 100644 .changeset/odd-kangaroos-itch.md delete mode 100644 .changeset/old-knives-wonder.md delete mode 100644 .changeset/old-ways-know.md delete mode 100644 .changeset/olive-ads-peel.md delete mode 100644 .changeset/perfect-cheetahs-serve.md delete mode 100644 .changeset/perfect-pears-care.md delete mode 100644 .changeset/pink-falcons-serve.md delete mode 100644 .changeset/poor-moons-confess.md delete mode 100644 .changeset/popular-dancers-join.md delete mode 100644 .changeset/pre.json delete mode 100644 .changeset/pretty-icons-glow.md delete mode 100644 .changeset/pretty-jars-peel.md delete mode 100644 .changeset/pretty-ladybugs-taste.md delete mode 100644 .changeset/proud-glasses-live.md delete mode 100644 .changeset/purple-feet-smile.md delete mode 100644 .changeset/purple-panthers-know.md delete mode 100644 .changeset/quick-ladybugs-reply.md delete mode 100644 .changeset/quick-mice-change.md delete mode 100644 .changeset/quiet-pets-count.md delete mode 100644 .changeset/rare-berries-give.md delete mode 100644 .changeset/rare-melons-battle.md delete mode 100644 .changeset/red-kiwis-compare.md delete mode 100644 .changeset/red-pugs-tap.md delete mode 100644 .changeset/red-toes-suffer.md delete mode 100644 .changeset/renovate-0b349f9.md delete mode 100644 .changeset/renovate-0c3644c.md delete mode 100644 .changeset/renovate-53e8b07.md delete mode 100644 .changeset/rich-bags-sleep.md delete mode 100644 .changeset/rich-snakes-rest.md delete mode 100644 .changeset/rotten-birds-build.md delete mode 100644 .changeset/rotten-mayflies-love.md delete mode 100644 .changeset/selfish-frogs-punch.md delete mode 100644 .changeset/serious-grapes-brush.md delete mode 100644 .changeset/serious-horses-juggle.md delete mode 100644 .changeset/serious-pigs-watch.md delete mode 100644 .changeset/sharp-lobsters-build.md delete mode 100644 .changeset/shiny-years-tap.md delete mode 100644 .changeset/short-apes-relate.md delete mode 100644 .changeset/shy-buses-mix.md delete mode 100644 .changeset/shy-steaks-invite.md delete mode 100644 .changeset/silent-peas-fly.md delete mode 100644 .changeset/silent-roses-join.md delete mode 100644 .changeset/silly-buckets-joke.md delete mode 100644 .changeset/silly-socks-lie.md delete mode 100644 .changeset/silly-turkeys-hang.md delete mode 100644 .changeset/silver-badgers-heal.md delete mode 100644 .changeset/silver-wolves-breathe.md delete mode 100644 .changeset/slow-carrots-sniff.md delete mode 100644 .changeset/slow-moles-sin.md delete mode 100644 .changeset/slow-sloths-do.md delete mode 100644 .changeset/smart-dingos-raise.md delete mode 100644 .changeset/soft-actors-worry.md delete mode 100644 .changeset/soft-boxes-buy.md delete mode 100644 .changeset/soft-snails-notice.md delete mode 100644 .changeset/spotty-coats-clean.md delete mode 100644 .changeset/spotty-spiders-love.md delete mode 100644 .changeset/stale-dots-smile.md delete mode 100644 .changeset/stale-experts-punch.md delete mode 100644 .changeset/stale-houses-push.md delete mode 100644 .changeset/stupid-ladybugs-brake.md delete mode 100644 .changeset/sweet-yaks-taste.md delete mode 100644 .changeset/swift-fishes-smash.md delete mode 100644 .changeset/tall-falcons-teach.md delete mode 100644 .changeset/tall-tables-hide.md delete mode 100644 .changeset/tall-years-relate.md delete mode 100644 .changeset/tasty-jobs-help.md delete mode 100644 .changeset/thick-clocks-pump.md delete mode 100644 .changeset/thick-tables-travel.md delete mode 100644 .changeset/thin-donkeys-attack.md delete mode 100644 .changeset/thin-scissors-press.md delete mode 100644 .changeset/three-geckos-press.md delete mode 100644 .changeset/tidy-kids-hide.md delete mode 100644 .changeset/tidy-kings-cough.md delete mode 100644 .changeset/tough-jeans-camp.md delete mode 100644 .changeset/twenty-islands-wonder.md delete mode 100644 .changeset/twenty-parents-relate.md delete mode 100644 .changeset/twenty-pugs-explain.md delete mode 100644 .changeset/two-melons-lie.md delete mode 100644 .changeset/violet-tips-rhyme.md delete mode 100644 .changeset/weak-radios-sing.md delete mode 100644 .changeset/wicked-beers-walk.md delete mode 100644 .changeset/wild-donkeys-rescue.md delete mode 100644 .changeset/wild-melons-shout.md delete mode 100644 .changeset/witty-moose-itch.md delete mode 100644 .changeset/yellow-roses-tell.md delete mode 100644 .changeset/young-beans-float.md delete mode 100644 .changeset/young-points-drop.md delete mode 100644 .changeset/young-singers-learn.md create mode 100644 docs/releases/v1.11.0-changelog.md create mode 100644 plugins/entity-feedback-backend/CHANGELOG.md create mode 100644 plugins/entity-feedback-common/CHANGELOG.md create mode 100644 plugins/entity-feedback/CHANGELOG.md create mode 100644 plugins/linguist-backend/CHANGELOG.md create mode 100644 plugins/linguist-common/CHANGELOG.md create mode 100644 plugins/linguist/CHANGELOG.md create mode 100644 plugins/microsoft-calendar/CHANGELOG.md diff --git a/.changeset/afraid-foxes-provide.md b/.changeset/afraid-foxes-provide.md deleted file mode 100644 index e02702b895..0000000000 --- a/.changeset/afraid-foxes-provide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sonarqube': patch ---- - -Additional export added in order to bind SonarQubeClient to its apiref diff --git a/.changeset/afraid-planets-crash.md b/.changeset/afraid-planets-crash.md deleted file mode 100644 index b31a492f3d..0000000000 --- a/.changeset/afraid-planets-crash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': minor ---- - -**BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. diff --git a/.changeset/big-bags-glow.md b/.changeset/big-bags-glow.md deleted file mode 100644 index eb606838fd..0000000000 --- a/.changeset/big-bags-glow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Add additional validation as security precations for output entities. diff --git a/.changeset/brave-cougars-burn.md b/.changeset/brave-cougars-burn.md deleted file mode 100644 index 419378d25d..0000000000 --- a/.changeset/brave-cougars-burn.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch ---- - -`scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` diff --git a/.changeset/brave-lemons-chew.md b/.changeset/brave-lemons-chew.md deleted file mode 100644 index 61bf7cc6af..0000000000 --- a/.changeset/brave-lemons-chew.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-playlist-backend': patch -'@backstage/plugin-catalog-backend': patch ---- - -Minor improvements to the descriptions provided with permission rules schemas diff --git a/.changeset/breezy-ears-rule.md b/.changeset/breezy-ears-rule.md deleted file mode 100644 index 753554187d..0000000000 --- a/.changeset/breezy-ears-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-gitlab': patch ---- - -The config now consistently uses the term 'instance' to refer to a single GitLab API host. diff --git a/.changeset/bright-eagles-love.md b/.changeset/bright-eagles-love.md deleted file mode 100644 index eade94f6f8..0000000000 --- a/.changeset/bright-eagles-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': minor ---- - -Added new mechanism to handle deltas in incremental providers diff --git a/.changeset/bright-plums-cough.md b/.changeset/bright-plums-cough.md deleted file mode 100644 index 9af30f002e..0000000000 --- a/.changeset/bright-plums-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': minor ---- - -**BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. diff --git a/.changeset/bright-teachers-compete.md b/.changeset/bright-teachers-compete.md deleted file mode 100644 index 3cc900d613..0000000000 --- a/.changeset/bright-teachers-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': minor ---- - -**BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. diff --git a/.changeset/brown-islands-own.md b/.changeset/brown-islands-own.md deleted file mode 100644 index d91ab89fd8..0000000000 --- a/.changeset/brown-islands-own.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-azure-devops': patch ---- - -Fixed `AssignedToCurrentUsersTeams` & `CreatedByCurrentUsersTeams` filter in `AzurePullRequestsPage` component. diff --git a/.changeset/brown-kings-wait.md b/.changeset/brown-kings-wait.md deleted file mode 100644 index db3fc0ee86..0000000000 --- a/.changeset/brown-kings-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -The list of entities takes into account the title when its different from the name to sort the entities. diff --git a/.changeset/calm-avocados-exercise.md b/.changeset/calm-avocados-exercise.md deleted file mode 100644 index c62ae4bd83..0000000000 --- a/.changeset/calm-avocados-exercise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-common': patch ---- - -New K8s catalog entity annotations added that will replace now deprecated k8s annotations in the catalog-model package. K8s annotation imports should now be made from plugin-kubernetes-common. diff --git a/.changeset/chatty-lemons-reply.md b/.changeset/chatty-lemons-reply.md deleted file mode 100644 index 118f832646..0000000000 --- a/.changeset/chatty-lemons-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend-module-elasticsearch': patch ---- - -Export `decodeElasticSearchPageCursor` utility function diff --git a/.changeset/chatty-owls-care.md b/.changeset/chatty-owls-care.md deleted file mode 100644 index 9f39f51bb5..0000000000 --- a/.changeset/chatty-owls-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -The `backstage-cli repo test` command now sets a default Jest `--workerIdleMemoryLimit` of 1GB. If needed to ensure that tests are not run in band, `--maxWorkers=2` is set as well. This is the recommended workaround for dealing with Jest workers leaking memory and eventually hitting the heap limit. diff --git a/.changeset/chilled-brooms-jog.md b/.changeset/chilled-brooms-jog.md deleted file mode 100644 index d848246b2b..0000000000 --- a/.changeset/chilled-brooms-jog.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -**BREAKING**: The `CacheClient` interface must now also implement the `withOptions` method. The `.get()` method has also received a type parameter that helps ensure that `undefined` in the event of a cache miss is handled. - -Added a `cacheToPluginCacheManager` helper that converts a `CacheService` into a legacy `PluginCacheManager` instance. diff --git a/.changeset/chilled-sheep-collect.md b/.changeset/chilled-sheep-collect.md deleted file mode 100644 index b944685e16..0000000000 --- a/.changeset/chilled-sheep-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Removed unnecessary `@backstage/cli` dependency. diff --git a/.changeset/clean-queens-judge.md b/.changeset/clean-queens-judge.md deleted file mode 100644 index a394bfa9a7..0000000000 --- a/.changeset/clean-queens-judge.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -The process of adding or modifying fields in the software-catalog search index has been simplified. For more details, see [how to customize fields in the Software Catalog index](https://backstage.io/docs/features/search/how-to-guides#how-to-customize-fields-in-the-software-catalog-index). diff --git a/.changeset/cold-cycles-switch.md b/.changeset/cold-cycles-switch.md deleted file mode 100644 index 0df71a82d3..0000000000 --- a/.changeset/cold-cycles-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch ---- - -Adding new Cluster detail fields to catalogClusterLocator. Replace deprecated imports with k8s annotations from plugin-kubernetes-common. diff --git a/.changeset/cool-radios-hope.md b/.changeset/cool-radios-hope.md deleted file mode 100644 index 4a66925d05..0000000000 --- a/.changeset/cool-radios-hope.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-techdocs-node': minor -'@techdocs/cli': patch ---- - -Deprecated getMkDocsYml in favor of getMkdocsYml (lowercase 'd') diff --git a/.changeset/cool-spoons-bathe.md b/.changeset/cool-spoons-bathe.md deleted file mode 100644 index b6bcaf89aa..0000000000 --- a/.changeset/cool-spoons-bathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-lighthouse-backend': minor ---- - -Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits diff --git a/.changeset/create-app-1674561612.md b/.changeset/create-app-1674561612.md deleted file mode 100644 index b50d431d4b..0000000000 --- a/.changeset/create-app-1674561612.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bumped create-app version. diff --git a/.changeset/cuddly-boxes-agree.md b/.changeset/cuddly-boxes-agree.md deleted file mode 100644 index 83f027ecb5..0000000000 --- a/.changeset/cuddly-boxes-agree.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': minor ---- - -Update DocsTable and EntityListDocsTable to accept overrides for Material Table options. diff --git a/.changeset/cyan-deers-walk.md b/.changeset/cyan-deers-walk.md deleted file mode 100644 index 236eb7935b..0000000000 --- a/.changeset/cyan-deers-walk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs-node': patch ---- - -Fixed bug caused by recent migration to AWS SDK V3 for techdocs-node. Instead of s3ForcePathStyle, forcePathStyle should be passed. diff --git a/.changeset/dry-donkeys-cheer.md b/.changeset/dry-donkeys-cheer.md deleted file mode 100644 index 70ed45fa74..0000000000 --- a/.changeset/dry-donkeys-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Added a check to ensure that Yarn v1 is used when creating new projects. diff --git a/.changeset/dull-fishes-suffer.md b/.changeset/dull-fishes-suffer.md deleted file mode 100644 index 54baae404e..0000000000 --- a/.changeset/dull-fishes-suffer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': patch ---- - -Removed the unused `TypesToServiceRef` type diff --git a/.changeset/dull-gorillas-sing.md b/.changeset/dull-gorillas-sing.md deleted file mode 100644 index 99246bea1c..0000000000 --- a/.changeset/dull-gorillas-sing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -The previous migration that adds the `search.original_value` column may leave some of the entities not updated. Add a migration script to trigger a reprocessing of the entities. diff --git a/.changeset/dull-pianos-shave.md b/.changeset/dull-pianos-shave.md deleted file mode 100644 index 8fae999bda..0000000000 --- a/.changeset/dull-pianos-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Added aria labels on the support button and sidebar diff --git a/.changeset/eight-falcons-explode.md b/.changeset/eight-falcons-explode.md deleted file mode 100644 index d9a1a2fe1f..0000000000 --- a/.changeset/eight-falcons-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -Fixed an issue were the log redaction didn't properly escape RegExp characters. diff --git a/.changeset/eight-hotels-sparkle.md b/.changeset/eight-hotels-sparkle.md deleted file mode 100644 index 6846630e02..0000000000 --- a/.changeset/eight-hotels-sparkle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Show module name causing error during build diff --git a/.changeset/eight-vans-drum.md b/.changeset/eight-vans-drum.md deleted file mode 100644 index 8e815a1701..0000000000 --- a/.changeset/eight-vans-drum.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-lighthouse-common': minor ---- - -Introduce @backstage/plugin-lighthouse-common with the API implementation diff --git a/.changeset/eighty-knives-repeat.md b/.changeset/eighty-knives-repeat.md deleted file mode 100644 index 3e32a3589d..0000000000 --- a/.changeset/eighty-knives-repeat.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-app-api': patch -'@backstage/backend-common': patch ---- - -Updated to match the new `CacheService` interface. diff --git a/.changeset/eleven-shoes-crash.md b/.changeset/eleven-shoes-crash.md deleted file mode 100644 index 8013f311d5..0000000000 --- a/.changeset/eleven-shoes-crash.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch ---- - -scaffolder/next: Implementing a simple `OngoingTask` page diff --git a/.changeset/empty-games-cheer.md b/.changeset/empty-games-cheer.md deleted file mode 100644 index d17e97f752..0000000000 --- a/.changeset/empty-games-cheer.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch -'@backstage/plugin-api-docs-module-protoc-gen-doc': patch -'@backstage/plugin-code-coverage-backend': patch -'@backstage/plugin-azure-devops-backend': patch -'@backstage/backend-test-utils': patch -'@backstage/plugin-analytics-module-ga': patch -'@backstage/plugin-azure-sites-backend': patch -'@backstage/plugin-microsoft-calendar': patch -'@backstage/plugin-catalog-graph': patch -'@backstage/plugin-code-coverage': patch -'@backstage/plugin-adr-backend': patch -'@backstage/plugin-azure-sites': patch -'@backstage/plugin-lighthouse': patch -'@backstage/plugin-shortcuts': patch -'@backstage/plugin-xcmetrics': patch -'@backstage/plugin-allure': patch -'@backstage/plugin-ilert': patch -'@backstage/plugin-home': patch ---- - -Update docs to always use `yarn add --cwd` for app & backend diff --git a/.changeset/famous-squids-wonder.md b/.changeset/famous-squids-wonder.md deleted file mode 100644 index 5b027e9a63..0000000000 --- a/.changeset/famous-squids-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Location rule target patterns now also match hidden files, i.e. path components with a leading dot. diff --git a/.changeset/few-meals-buy.md b/.changeset/few-meals-buy.md deleted file mode 100644 index c49eb8c7ac..0000000000 --- a/.changeset/few-meals-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-aws': patch ---- - -Update to import `LocationSpec` from the correct package. diff --git a/.changeset/few-moons-accept.md b/.changeset/few-moons-accept.md deleted file mode 100644 index c790e837c8..0000000000 --- a/.changeset/few-moons-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. diff --git a/.changeset/few-trees-cross.md b/.changeset/few-trees-cross.md deleted file mode 100644 index ed70c3bddb..0000000000 --- a/.changeset/few-trees-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed Webpack loader patterns so that they properly match the file suffix only. diff --git a/.changeset/flat-cups-itch.md b/.changeset/flat-cups-itch.md deleted file mode 100644 index 250393c21a..0000000000 --- a/.changeset/flat-cups-itch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch ---- - -lock versions of `@rjsf/*-beta` packages diff --git a/.changeset/flat-lizards-poke.md b/.changeset/flat-lizards-poke.md deleted file mode 100644 index bc180836fa..0000000000 --- a/.changeset/flat-lizards-poke.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Fix proxying to mkdocs - -The domain localhost may point to both 127.0.0.1 and ::1, ipv4 and ipv6 -and when node tries to lookup localhost it might prefer ipv6 while mkdocs -is only listening on ipv4. This tells node-proxy to target the ipv4 address -instead of relying on localhost hostname lookup. diff --git a/.changeset/four-candles-add.md b/.changeset/four-candles-add.md deleted file mode 100644 index fa975e0a58..0000000000 --- a/.changeset/four-candles-add.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -'@backstage/plugin-tech-insights-backend': patch -'@backstage/plugin-tech-insights-common': patch -'@backstage/plugin-tech-insights-node': minor -'@backstage/plugin-tech-insights': patch ---- - -TechInsightsApi interface now has getFactSchemas() method. -TechInsightsClient now implements method getFactSchemas(). - -**BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common - -These changes are **required** if you were importing this type directly. - -```diff -- import { FactSchema } from '@backstage/plugin-tech-insights-node'; -+ import { FactSchema } from '@backstage/plugin-tech-insights-common'; -``` diff --git a/.changeset/four-rivers-enjoy.md b/.changeset/four-rivers-enjoy.md deleted file mode 100644 index b38babd8bd..0000000000 --- a/.changeset/four-rivers-enjoy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-msgraph': patch ---- - -Fix MS Graph provider to use target URL for fetching access token diff --git a/.changeset/four-tables-fix.md b/.changeset/four-tables-fix.md deleted file mode 100644 index f17f57e253..0000000000 --- a/.changeset/four-tables-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Added explicit return type signature for `mockServices.config()`. diff --git a/.changeset/friendly-chefs-rule.md b/.changeset/friendly-chefs-rule.md deleted file mode 100644 index 872a36b5ae..0000000000 --- a/.changeset/friendly-chefs-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch ---- - -Removing extra imports for `run` script as `TestBackend` auto loads the default factories diff --git a/.changeset/friendly-scissors-shop.md b/.changeset/friendly-scissors-shop.md deleted file mode 100644 index 03c67ba491..0000000000 --- a/.changeset/friendly-scissors-shop.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-scaffolder': minor ---- - -- **Deprecation** - Deprecated the following exports, please import them directly from `@backstage/plugin-scaffolder-react` instead - - ``` - createScaffolderLayout - ScaffolderLayouts - LayoutOptions - LayoutTemplate - ``` diff --git a/.changeset/gold-bulldogs-talk.md b/.changeset/gold-bulldogs-talk.md deleted file mode 100644 index e5b6254ec5..0000000000 --- a/.changeset/gold-bulldogs-talk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': minor ---- - -Update `SearchModal` component to use `SearchResult` extensions. diff --git a/.changeset/gold-lemons-eat.md b/.changeset/gold-lemons-eat.md deleted file mode 100644 index 8d9c0118b1..0000000000 --- a/.changeset/gold-lemons-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Updating the readme with better `csp` instructions diff --git a/.changeset/gold-masks-sleep.md b/.changeset/gold-masks-sleep.md deleted file mode 100644 index 425a1abdc0..0000000000 --- a/.changeset/gold-masks-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Fixed bug in Techdocs reader where a techdocs page with a hash in the URL did not always jump to the document anchor. diff --git a/.changeset/gorgeous-ligers-burn.md b/.changeset/gorgeous-ligers-burn.md deleted file mode 100644 index f1d8f2cf5f..0000000000 --- a/.changeset/gorgeous-ligers-burn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Added a global override for `window.open` that helps prevent security vulnerabilities. diff --git a/.changeset/gorgeous-llamas-mate.md b/.changeset/gorgeous-llamas-mate.md deleted file mode 100644 index a2553875e9..0000000000 --- a/.changeset/gorgeous-llamas-mate.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-entity-feedback-backend': minor -'@backstage/plugin-entity-feedback-common': minor -'@backstage/plugin-entity-feedback': minor ---- - -Implement entity feedback plugin, check out the `README.md` for more details! diff --git a/.changeset/great-goats-talk.md b/.changeset/great-goats-talk.md deleted file mode 100644 index 92a1cd59ee..0000000000 --- a/.changeset/great-goats-talk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': minor ---- - -Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. diff --git a/.changeset/green-adults-retire.md b/.changeset/green-adults-retire.md deleted file mode 100644 index c13e8d664f..0000000000 --- a/.changeset/green-adults-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-dev-utils': minor ---- - -Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. diff --git a/.changeset/green-guests-flow.md b/.changeset/green-guests-flow.md deleted file mode 100644 index 688ff17dd9..0000000000 --- a/.changeset/green-guests-flow.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-test-utils': patch -'@backstage/backend-app-api': patch -'@backstage/backend-common': patch -'@backstage/plugin-catalog-backend': patch ---- - -Updated usage of the lifecycle service. diff --git a/.changeset/grumpy-bottles-stare.md b/.changeset/grumpy-bottles-stare.md deleted file mode 100644 index 1e6040f57f..0000000000 --- a/.changeset/grumpy-bottles-stare.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': patch -'@backstage/plugin-scaffolder': patch ---- - -Upgrade `@rjsf` version 5 dependencies to `beta.18` diff --git a/.changeset/grumpy-fireants-drop.md b/.changeset/grumpy-fireants-drop.md deleted file mode 100644 index 92b08663f4..0000000000 --- a/.changeset/grumpy-fireants-drop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/codemods': patch ---- - -Moved `commander` to being a regular dependency. diff --git a/.changeset/happy-cows-moo.md b/.changeset/happy-cows-moo.md deleted file mode 100644 index a5e425f5d2..0000000000 --- a/.changeset/happy-cows-moo.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-azure-devops-backend': patch ---- - -Fixed a bug where the azure devops host in URLs on the readme card was being URL encoded, breaking hosts with ports. diff --git a/.changeset/heavy-comics-applaud.md b/.changeset/heavy-comics-applaud.md deleted file mode 100644 index faa0aabb4c..0000000000 --- a/.changeset/heavy-comics-applaud.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': minor ---- - -Added `DescriptionField` field override to the `next/scaffolder` diff --git a/.changeset/hip-chairs-double.md b/.changeset/hip-chairs-double.md deleted file mode 100644 index e2b03f2e66..0000000000 --- a/.changeset/hip-chairs-double.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@backstage/plugin-tech-radar': patch ---- - -Deprecate `RadarEntry.url` - use `RadarEntry.links` instead - -```diff -- url: 'https://www.javascript.com/', - key: 'javascript', - id: 'javascript', - title: 'JavaScript', - quadrant: 'languages', - links: [ -+ { -+ url: 'https://www.javascript.com/', -+ title: 'Learn more', -+ }, - ], -``` diff --git a/.changeset/hip-onions-tan.md b/.changeset/hip-onions-tan.md deleted file mode 100644 index 01be0d4867..0000000000 --- a/.changeset/hip-onions-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-backend': patch ---- - -Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. diff --git a/.changeset/hip-pugs-teach.md b/.changeset/hip-pugs-teach.md deleted file mode 100644 index 4a3820cecc..0000000000 --- a/.changeset/hip-pugs-teach.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -'@backstage/plugin-techdocs-module-addons-contrib': patch -'@backstage/plugin-techdocs-addons-test-utils': patch -'@backstage/plugin-apollo-explorer': patch -'@backstage/plugin-cicd-statistics': patch -'@backstage/plugin-codescene': patch -'@backstage/plugin-dynatrace': patch -'@backstage/plugin-org-react': patch -'@backstage/plugin-playlist': patch ---- - -Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages diff --git a/.changeset/hip-tables-prove.md b/.changeset/hip-tables-prove.md deleted file mode 100644 index bc2c4e83d6..0000000000 --- a/.changeset/hip-tables-prove.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Updated the `mockServices.rootLogger` options to accept a single level option instead. diff --git a/.changeset/honest-timers-pull.md b/.changeset/honest-timers-pull.md deleted file mode 100644 index d11d260a22..0000000000 --- a/.changeset/honest-timers-pull.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': minor -'@backstage/plugin-scaffolder': minor ---- - -Migrating the `TemplateEditorPage` to work with the new components from `@backstage/plugin-scaffolder-react` diff --git a/.changeset/hot-lions-cover.md b/.changeset/hot-lions-cover.md deleted file mode 100644 index 62064188a4..0000000000 --- a/.changeset/hot-lions-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github': patch ---- - -Add support for filtering out forks diff --git a/.changeset/hot-wasps-cover.md b/.changeset/hot-wasps-cover.md deleted file mode 100644 index e142980b56..0000000000 --- a/.changeset/hot-wasps-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` diff --git a/.changeset/hungry-news-fix.md b/.changeset/hungry-news-fix.md deleted file mode 100644 index c59113d9f4..0000000000 --- a/.changeset/hungry-news-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-sentry': patch ---- - -Fix broken module exports and dependencies to match a backend module, rather than a frontend plugin. diff --git a/.changeset/hungry-stingrays-type.md b/.changeset/hungry-stingrays-type.md deleted file mode 100644 index 8cb11f67a5..0000000000 --- a/.changeset/hungry-stingrays-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': patch ---- - -Keep the tech docs sync event stream alive even if it is taking a while to build. diff --git a/.changeset/itchy-chairs-punch.md b/.changeset/itchy-chairs-punch.md deleted file mode 100644 index 034a9bbdae..0000000000 --- a/.changeset/itchy-chairs-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': patch ---- - -Aligned opaque type markers to all use a `$$type` property with namespacing. diff --git a/.changeset/itchy-goats-melt.md b/.changeset/itchy-goats-melt.md deleted file mode 100644 index d073dd4103..0000000000 --- a/.changeset/itchy-goats-melt.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch -'@backstage/plugin-scaffolder-backend-module-sentry': patch -'@backstage/plugin-scaffolder-backend-module-yeoman': patch -'@backstage/plugin-scaffolder-backend-module-rails': patch ---- - -Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality diff --git a/.changeset/itchy-rings-rule.md b/.changeset/itchy-rings-rule.md deleted file mode 100644 index 3e8b9e8b2b..0000000000 --- a/.changeset/itchy-rings-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Fixed an issue where entities sometimes were not properly deleted during a full mutation. diff --git a/.changeset/khaki-toes-care.md b/.changeset/khaki-toes-care.md deleted file mode 100644 index e119208335..0000000000 --- a/.changeset/khaki-toes-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-common': minor ---- - -**BREAKING**: Renamed misspelled `LimitRangeFetchReponse` to `LimitRangeFetchResponse`. diff --git a/.changeset/late-rice-crash.md b/.changeset/late-rice-crash.md deleted file mode 100644 index b692310c01..0000000000 --- a/.changeset/late-rice-crash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -Fixed regression that caused the `WelcomeTitle` to not be the right size when passed to the `title` property of the `

` component. A Storybook entry was also added for the `WelcomeTitle` diff --git a/.changeset/lazy-badgers-rule.md b/.changeset/lazy-badgers-rule.md deleted file mode 100644 index 748b9dbadc..0000000000 --- a/.changeset/lazy-badgers-rule.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-insights-backend-module-jsonfc': patch ---- - -Surface the cause of the json rules engine diff --git a/.changeset/lazy-badgers-try.md b/.changeset/lazy-badgers-try.md deleted file mode 100644 index 4ffb32304a..0000000000 --- a/.changeset/lazy-badgers-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-node': minor ---- - -New package that takes over some of the types and functionality from `@backstage/plugin-scaffolder-backend` that are shared with other modules diff --git a/.changeset/lemon-tables-train.md b/.changeset/lemon-tables-train.md deleted file mode 100644 index 80b64bfe53..0000000000 --- a/.changeset/lemon-tables-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-aws': patch ---- - -Added support for `externalId` when assuming role in `AwsS3EntityProvider` diff --git a/.changeset/light-crabs-drum.md b/.changeset/light-crabs-drum.md deleted file mode 100644 index ebc0b3fa5a..0000000000 --- a/.changeset/light-crabs-drum.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-adr-backend': minor -'@backstage/plugin-adr': minor ---- - -Display title, status and date in ADR navigation, sourced from ADR content and reverse order. diff --git a/.changeset/little-jars-lay.md b/.changeset/little-jars-lay.md deleted file mode 100644 index f8851f7adc..0000000000 --- a/.changeset/little-jars-lay.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@backstage/plugin-user-settings-backend': patch -'@backstage/plugin-scaffolder-backend': patch -'@backstage/plugin-periskop-backend': patch -'@backstage/backend-common': patch -'@backstage/plugin-catalog-backend': patch -'@backstage/plugin-bazaar-backend': patch -'@backstage/plugin-events-backend': patch -'@backstage/plugin-kafka-backend': patch -'@backstage/plugin-proxy-backend': patch -'@backstage/plugin-app-backend': patch ---- - -Updated usage of `createBackendPlugin`. diff --git a/.changeset/long-chefs-burn.md b/.changeset/long-chefs-burn.md deleted file mode 100644 index 03a7b76db9..0000000000 --- a/.changeset/long-chefs-burn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -Updated database factory to pass service deps required for restoring database state during development. diff --git a/.changeset/lovely-ladybugs-taste.md b/.changeset/lovely-ladybugs-taste.md deleted file mode 100644 index 24017e4dee..0000000000 --- a/.changeset/lovely-ladybugs-taste.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -**Deprecations**: The following are deprecated and should instead be imported from the new package `@backstage/plugin-scaffolder-node`: - -- `ActionContext` -- `createTemplateAction` -- `TaskSecrets` -- `TemplateAction` diff --git a/.changeset/lucky-papayas-allow.md b/.changeset/lucky-papayas-allow.md deleted file mode 100644 index 5a896efd0b..0000000000 --- a/.changeset/lucky-papayas-allow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': minor ---- - -Added a missing validator check for items in an array diff --git a/.changeset/many-nails-joke.md b/.changeset/many-nails-joke.md deleted file mode 100644 index 2ffd97dd0b..0000000000 --- a/.changeset/many-nails-joke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -Added Markdown support in the `AboutCard` description section diff --git a/.changeset/many-pans-unite.md b/.changeset/many-pans-unite.md deleted file mode 100644 index 59c068cec1..0000000000 --- a/.changeset/many-pans-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': minor ---- - -Adds the tRPC API type to the catalog. diff --git a/.changeset/mean-squids-kneel.md b/.changeset/mean-squids-kneel.md deleted file mode 100644 index 41a1bd4086..0000000000 --- a/.changeset/mean-squids-kneel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-vault': patch ---- - -Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. diff --git a/.changeset/modern-cats-worry.md b/.changeset/modern-cats-worry.md deleted file mode 100644 index b6698cb805..0000000000 --- a/.changeset/modern-cats-worry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Switched the order of reprocessing statements retroactively in migrations. This only improves the experience for those who at a later time perform a large upgrade of an old Backstage installation. diff --git a/.changeset/nasty-beans-accept.md b/.changeset/nasty-beans-accept.md deleted file mode 100644 index 51b3e88e49..0000000000 --- a/.changeset/nasty-beans-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Update `SearchPage` template to use `SearchResult` extensions. diff --git a/.changeset/nasty-kids-deny.md b/.changeset/nasty-kids-deny.md deleted file mode 100644 index 4a434eb1f6..0000000000 --- a/.changeset/nasty-kids-deny.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/theme': patch ---- - -Use same table header color as @backstage/core-components Table to meet accessibility color contrast requirements. This change affects material-ui tables. diff --git a/.changeset/neat-schools-raise.md b/.changeset/neat-schools-raise.md deleted file mode 100644 index b778ba8795..0000000000 --- a/.changeset/neat-schools-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch ---- - -Kubernetes proxy endpoint now accepts content types that are not json diff --git a/.changeset/neat-zebras-run.md b/.changeset/neat-zebras-run.md deleted file mode 100644 index 4ce5d5c393..0000000000 --- a/.changeset/neat-zebras-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Fixed an issue where an explicit port the frontend base URL could break the app. diff --git a/.changeset/nervous-apricots-whisper.md b/.changeset/nervous-apricots-whisper.md deleted file mode 100644 index ce71486364..0000000000 --- a/.changeset/nervous-apricots-whisper.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Improve view: remove footer overlay on large screen diff --git a/.changeset/nervous-mangos-rhyme.md b/.changeset/nervous-mangos-rhyme.md deleted file mode 100644 index 23e92c65a7..0000000000 --- a/.changeset/nervous-mangos-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-msgraph': patch ---- - -Extract default transformers to their own file diff --git a/.changeset/nervous-phones-shout.md b/.changeset/nervous-phones-shout.md deleted file mode 100644 index a4e46b3be9..0000000000 --- a/.changeset/nervous-phones-shout.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-test-utils': patch -'@backstage/backend-app-api': patch ---- - -Updates to match new `BackendFeature` type. diff --git a/.changeset/new-pumpkins-sleep.md b/.changeset/new-pumpkins-sleep.md deleted file mode 100644 index cc5b89806d..0000000000 --- a/.changeset/new-pumpkins-sleep.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-scaffolder-react': patch ---- - -bump `@rjsf` `v5` dependencies to 5.1.0 diff --git a/.changeset/nine-glasses-invent.md b/.changeset/nine-glasses-invent.md deleted file mode 100644 index beb69b3b90..0000000000 --- a/.changeset/nine-glasses-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes': patch ---- - -Condenses kubernetes ui plugin to fit more onscreen and increase visibility diff --git a/.changeset/nine-guests-compete.md b/.changeset/nine-guests-compete.md deleted file mode 100644 index 697236d0b7..0000000000 --- a/.changeset/nine-guests-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -remove unused plugin-stack-overflow dependency diff --git a/.changeset/nine-ravens-kiss.md b/.changeset/nine-ravens-kiss.md deleted file mode 100644 index a507db6b03..0000000000 --- a/.changeset/nine-ravens-kiss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-adr': minor ---- - -The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. diff --git a/.changeset/ninety-hats-serve.md b/.changeset/ninety-hats-serve.md deleted file mode 100644 index 762e53c242..0000000000 --- a/.changeset/ninety-hats-serve.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-azure': patch ---- - -This will add the ability to use Azure DevOps with multi project with a single value which is a new feature as previously this had to be done manually for each project that you wanted to add. - -Right now you would have to fill in multiple values in the config to use multiple projects: - -``` -yourFirstProviderId: # identifies your dataset / provider independent of config changes - organization: myorg - project: 'firstProject' # this will match the firstProject project - repository: '*' # this will match all repos - path: /catalog-info.yaml -yourSecondProviderId: # identifies your dataset / provider independent of config changes - organization: myorg - project: 'secondProject' # this will match the secondProject project - repository: '*' # this will match all repos - path: /catalog-info.yaml -``` - -With this change you can actually have all projects available where your PAT determines which you have access to, so that includes multiple projects: - -``` -yourFirstProviderId: # identifies your dataset / provider independent of config changes - organization: myorg - project: '*' # this will match all projects where your PAT has access to - repository: '*' # this will match all repos - path: /catalog-info.yaml -``` diff --git a/.changeset/odd-kangaroos-itch.md b/.changeset/odd-kangaroos-itch.md deleted file mode 100644 index 8529e5fe04..0000000000 --- a/.changeset/odd-kangaroos-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-graph': patch ---- - -Fix #16245: The CatalogGraphCard has parameter naming errors for CatalogGraphPage diff --git a/.changeset/old-knives-wonder.md b/.changeset/old-knives-wonder.md deleted file mode 100644 index 93d2be4871..0000000000 --- a/.changeset/old-knives-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -The `CatalogSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. diff --git a/.changeset/old-ways-know.md b/.changeset/old-ways-know.md deleted file mode 100644 index 60a1a923e8..0000000000 --- a/.changeset/old-ways-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. diff --git a/.changeset/olive-ads-peel.md b/.changeset/olive-ads-peel.md deleted file mode 100644 index 7a7c73ddb7..0000000000 --- a/.changeset/olive-ads-peel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': patch ---- - -Provide better error messaging when GitHub fails due to missing team definitions diff --git a/.changeset/perfect-cheetahs-serve.md b/.changeset/perfect-cheetahs-serve.md deleted file mode 100644 index 08f7c1da21..0000000000 --- a/.changeset/perfect-cheetahs-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Added the option to overwrite files in the `targetPath` of the `template:fetch` action diff --git a/.changeset/perfect-pears-care.md b/.changeset/perfect-pears-care.md deleted file mode 100644 index 2ea9f54a7f..0000000000 --- a/.changeset/perfect-pears-care.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': patch -'@backstage/plugin-techdocs-node': patch -'@techdocs/cli': patch ---- - -Added support for using a default `mkdocs.yml` configuration file when none is provided diff --git a/.changeset/pink-falcons-serve.md b/.changeset/pink-falcons-serve.md deleted file mode 100644 index 8cc6859c25..0000000000 --- a/.changeset/pink-falcons-serve.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder': minor -'@backstage/plugin-scaffolder-react': minor ---- - -Embed scaffolder workflow in other components diff --git a/.changeset/poor-moons-confess.md b/.changeset/poor-moons-confess.md deleted file mode 100644 index 7489a3c9f1..0000000000 --- a/.changeset/poor-moons-confess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch ---- - -Return `EventSubscriber` from `addIncrementalEntityProvider` to hook up to `EventsBackend` diff --git a/.changeset/popular-dancers-join.md b/.changeset/popular-dancers-join.md deleted file mode 100644 index e7f6ab524f..0000000000 --- a/.changeset/popular-dancers-join.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -The Button component has been deprecated in favor of the LinkButton component diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index 01c51bcc4b..0000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,343 +0,0 @@ -{ - "mode": "exit", - "tag": "next", - "initialVersions": { - "example-app": "0.2.79", - "@backstage/app-defaults": "1.1.0", - "example-backend": "0.2.79", - "@backstage/backend-app-api": "0.3.0", - "@backstage/backend-common": "0.18.0", - "@backstage/backend-defaults": "0.1.5", - "example-backend-next": "0.0.7", - "@backstage/backend-plugin-api": "0.3.0", - "@backstage/backend-tasks": "0.4.1", - "@backstage/backend-test-utils": "0.1.32", - "@backstage/catalog-client": "1.3.0", - "@backstage/catalog-model": "1.1.5", - "@backstage/cli": "0.22.1", - "@backstage/cli-common": "0.1.11", - "@backstage/codemods": "0.1.42", - "@backstage/config": "1.0.6", - "@backstage/config-loader": "1.1.8", - "@backstage/core-app-api": "1.4.0", - "@backstage/core-components": "0.12.3", - "@backstage/core-plugin-api": "1.3.0", - "@backstage/create-app": "0.4.36", - "@backstage/dev-utils": "1.0.11", - "e2e-test": "0.2.0", - "@backstage/errors": "1.1.4", - "@backstage/integration": "1.4.2", - "@backstage/integration-aws-node": "0.1.1", - "@backstage/integration-react": "1.1.9", - "@backstage/release-manifests": "0.0.8", - "@backstage/repo-tools": "0.1.1", - "@techdocs/cli": "1.3.0", - "techdocs-cli-embedded-app": "0.2.78", - "@backstage/test-utils": "1.2.4", - "@backstage/theme": "0.2.16", - "@backstage/types": "1.0.2", - "@backstage/version-bridge": "1.0.3", - "@backstage/plugin-adr": "0.3.0", - "@backstage/plugin-adr-backend": "0.2.5", - "@backstage/plugin-adr-common": "0.2.5", - "@backstage/plugin-airbrake": "0.3.14", - "@backstage/plugin-airbrake-backend": "0.2.13", - "@backstage/plugin-allure": "0.1.30", - "@backstage/plugin-analytics-module-ga": "0.1.25", - "@backstage/plugin-apache-airflow": "0.2.7", - "@backstage/plugin-api-docs": "0.8.14", - "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.0", - "@backstage/plugin-apollo-explorer": "0.1.7", - "@backstage/plugin-app-backend": "0.3.40", - "@backstage/plugin-auth-backend": "0.17.3", - "@backstage/plugin-auth-node": "0.2.9", - "@backstage/plugin-azure-devops": "0.2.5", - "@backstage/plugin-azure-devops-backend": "0.3.19", - "@backstage/plugin-azure-devops-common": "0.3.0", - "@backstage/plugin-azure-sites": "0.1.3", - "@backstage/plugin-azure-sites-backend": "0.1.2", - "@backstage/plugin-azure-sites-common": "0.1.0", - "@backstage/plugin-badges": "0.2.38", - "@backstage/plugin-badges-backend": "0.1.34", - "@backstage/plugin-bazaar": "0.2.3", - "@backstage/plugin-bazaar-backend": "0.2.3", - "@backstage/plugin-bitbucket-cloud-common": "0.2.3", - "@backstage/plugin-bitrise": "0.1.41", - "@backstage/plugin-catalog": "1.7.2", - "@backstage/plugin-catalog-backend": "1.7.0", - "@backstage/plugin-catalog-backend-module-aws": "0.1.13", - "@backstage/plugin-catalog-backend-module-azure": "0.1.11", - "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.7", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.7", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.5", - "@backstage/plugin-catalog-backend-module-gerrit": "0.1.8", - "@backstage/plugin-catalog-backend-module-github": "0.2.3", - "@backstage/plugin-catalog-backend-module-gitlab": "0.1.11", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.1.1", - "@backstage/plugin-catalog-backend-module-ldap": "0.5.7", - "@backstage/plugin-catalog-backend-module-msgraph": "0.4.6", - "@backstage/plugin-catalog-backend-module-openapi": "0.1.6", - "@backstage/plugin-catalog-common": "1.0.10", - "@internal/plugin-catalog-customized": "0.0.6", - "@backstage/plugin-catalog-graph": "0.2.26", - "@backstage/plugin-catalog-graphql": "0.3.17", - "@backstage/plugin-catalog-import": "0.9.4", - "@backstage/plugin-catalog-node": "1.3.1", - "@backstage/plugin-catalog-react": "1.2.4", - "@backstage/plugin-cicd-statistics": "0.1.16", - "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.10", - "@backstage/plugin-circleci": "0.3.14", - "@backstage/plugin-cloudbuild": "0.3.14", - "@backstage/plugin-code-climate": "0.1.14", - "@backstage/plugin-code-coverage": "0.2.7", - "@backstage/plugin-code-coverage-backend": "0.2.6", - "@backstage/plugin-codescene": "0.1.9", - "@backstage/plugin-config-schema": "0.1.37", - "@backstage/plugin-cost-insights": "0.12.3", - "@backstage/plugin-cost-insights-common": "0.1.1", - "@backstage/plugin-dynatrace": "1.0.4", - "@backstage/plugin-events-backend": "0.2.1", - "@backstage/plugin-events-backend-module-aws-sqs": "0.1.2", - "@backstage/plugin-events-backend-module-azure": "0.1.2", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.2", - "@backstage/plugin-events-backend-module-gerrit": "0.1.2", - "@backstage/plugin-events-backend-module-github": "0.1.2", - "@backstage/plugin-events-backend-module-gitlab": "0.1.2", - "@backstage/plugin-events-backend-test-utils": "0.1.2", - "@backstage/plugin-events-node": "0.2.1", - "@internal/plugin-todo-list": "1.0.9", - "@internal/plugin-todo-list-backend": "1.0.9", - "@internal/plugin-todo-list-common": "1.0.8", - "@backstage/plugin-explore": "0.3.45", - "@backstage/plugin-explore-backend": "0.0.2", - "@backstage/plugin-explore-common": "0.0.1", - "@backstage/plugin-explore-react": "0.0.25", - "@backstage/plugin-firehydrant": "0.1.31", - "@backstage/plugin-fossa": "0.2.46", - "@backstage/plugin-gcalendar": "0.3.10", - "@backstage/plugin-gcp-projects": "0.3.33", - "@backstage/plugin-git-release-manager": "0.3.27", - "@backstage/plugin-github-actions": "0.5.14", - "@backstage/plugin-github-deployments": "0.1.45", - "@backstage/plugin-github-issues": "0.2.3", - "@backstage/plugin-github-pull-requests-board": "0.1.8", - "@backstage/plugin-gitops-profiles": "0.3.32", - "@backstage/plugin-gocd": "0.1.20", - "@backstage/plugin-graphiql": "0.2.46", - "@backstage/plugin-graphql-backend": "0.1.30", - "@backstage/plugin-home": "0.4.30", - "@backstage/plugin-ilert": "0.2.3", - "@backstage/plugin-jenkins": "0.7.13", - "@backstage/plugin-jenkins-backend": "0.1.30", - "@backstage/plugin-jenkins-common": "0.1.12", - "@backstage/plugin-kafka": "0.3.14", - "@backstage/plugin-kafka-backend": "0.2.33", - "@backstage/plugin-kubernetes": "0.7.7", - "@backstage/plugin-kubernetes-backend": "0.9.1", - "@backstage/plugin-kubernetes-common": "0.5.1", - "@backstage/plugin-lighthouse": "0.3.14", - "@backstage/plugin-newrelic": "0.3.32", - "@backstage/plugin-newrelic-dashboard": "0.2.7", - "@backstage/plugin-org": "0.6.4", - "@backstage/plugin-org-react": "0.1.3", - "@backstage/plugin-pagerduty": "0.5.7", - "@backstage/plugin-periskop": "0.1.12", - "@backstage/plugin-periskop-backend": "0.1.11", - "@backstage/plugin-permission-backend": "0.5.15", - "@backstage/plugin-permission-common": "0.7.3", - "@backstage/plugin-permission-node": "0.7.3", - "@backstage/plugin-permission-react": "0.4.9", - "@backstage/plugin-playlist": "0.1.5", - "@backstage/plugin-playlist-backend": "0.2.3", - "@backstage/plugin-playlist-common": "0.1.4", - "@backstage/plugin-proxy-backend": "0.2.34", - "@backstage/plugin-rollbar": "0.4.14", - "@backstage/plugin-rollbar-backend": "0.1.37", - "@backstage/plugin-scaffolder": "1.10.0", - "@backstage/plugin-scaffolder-backend": "1.10.0", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.15", - "@backstage/plugin-scaffolder-backend-module-rails": "0.4.8", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.0", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.13", - "@backstage/plugin-scaffolder-common": "1.2.4", - "@backstage/plugin-scaffolder-react": "1.0.0", - "@backstage/plugin-search": "1.0.7", - "@backstage/plugin-search-backend": "1.2.1", - "@backstage/plugin-search-backend-module-elasticsearch": "1.1.1", - "@backstage/plugin-search-backend-module-pg": "0.5.1", - "@backstage/plugin-search-backend-node": "1.1.1", - "@backstage/plugin-search-common": "1.2.1", - "@backstage/plugin-search-react": "1.4.0", - "@backstage/plugin-sentry": "0.4.7", - "@backstage/plugin-shortcuts": "0.3.6", - "@backstage/plugin-sonarqube": "0.6.2", - "@backstage/plugin-sonarqube-backend": "0.1.5", - "@backstage/plugin-sonarqube-react": "0.1.1", - "@backstage/plugin-splunk-on-call": "0.4.3", - "@backstage/plugin-stack-overflow": "0.1.10", - "@backstage/plugin-stack-overflow-backend": "0.1.9", - "@backstage/plugin-tech-insights": "0.3.6", - "@backstage/plugin-tech-insights-backend": "0.5.6", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.24", - "@backstage/plugin-tech-insights-common": "0.2.9", - "@backstage/plugin-tech-insights-node": "0.3.8", - "@backstage/plugin-tech-radar": "0.6.0", - "@backstage/plugin-techdocs": "1.4.3", - "@backstage/plugin-techdocs-addons-test-utils": "1.0.9", - "@backstage/plugin-techdocs-backend": "1.5.1", - "@backstage/plugin-techdocs-module-addons-contrib": "1.0.9", - "@backstage/plugin-techdocs-node": "1.4.4", - "@backstage/plugin-techdocs-react": "1.1.2", - "@backstage/plugin-todo": "0.2.16", - "@backstage/plugin-todo-backend": "0.1.37", - "@backstage/plugin-user-settings": "0.6.2", - "@backstage/plugin-user-settings-backend": "0.1.4", - "@backstage/plugin-vault": "0.1.8", - "@backstage/plugin-vault-backend": "0.2.6", - "@backstage/plugin-xcmetrics": "0.2.34", - "@backstage/plugin-scaffolder-node": "0.0.0", - "@backstage/backend-dev-utils": "0.0.0", - "@backstage/eslint-plugin": "0.0.0", - "@backstage/plugin-entity-validation": "0.0.0", - "@backstage/plugin-graphql-voyager": "0.0.0", - "@backstage/plugin-lighthouse-backend": "0.0.0", - "@backstage/plugin-lighthouse-common": "0.0.0" - }, - "changesets": [ - "afraid-foxes-provide", - "afraid-planets-crash", - "brave-cougars-burn", - "breezy-ears-rule", - "bright-eagles-love", - "bright-plums-cough", - "bright-teachers-compete", - "brown-islands-own", - "calm-avocados-exercise", - "chatty-owls-care", - "chilled-sheep-collect", - "clean-queens-judge", - "cold-cycles-switch", - "cool-spoons-bathe", - "create-app-1674561612", - "cuddly-boxes-agree", - "cyan-deers-walk", - "dry-donkeys-cheer", - "dull-fishes-suffer", - "dull-gorillas-sing", - "eight-falcons-explode", - "eight-hotels-sparkle", - "eight-vans-drum", - "eleven-shoes-crash", - "few-moons-accept", - "flat-cups-itch", - "four-candles-add", - "four-rivers-enjoy", - "four-tables-fix", - "friendly-chefs-rule", - "friendly-scissors-shop", - "gold-bulldogs-talk", - "gold-lemons-eat", - "gold-masks-sleep", - "great-goats-talk", - "green-adults-retire", - "green-guests-flow", - "grumpy-bottles-stare", - "grumpy-fireants-drop", - "happy-cows-moo", - "hip-chairs-double", - "hip-onions-tan", - "hip-pugs-teach", - "hip-tables-prove", - "hot-lions-cover", - "hot-wasps-cover", - "hungry-news-fix", - "itchy-chairs-punch", - "itchy-goats-melt", - "khaki-toes-care", - "late-rice-crash", - "lazy-badgers-rule", - "lazy-badgers-try", - "lemon-tables-train", - "little-jars-lay", - "long-chefs-burn", - "lovely-ladybugs-taste", - "many-nails-joke", - "many-pans-unite", - "mean-squids-kneel", - "modern-cats-worry", - "nasty-beans-accept", - "neat-schools-raise", - "neat-zebras-run", - "nervous-apricots-whisper", - "nervous-mangos-rhyme", - "nervous-phones-shout", - "new-pumpkins-sleep", - "nine-glasses-invent", - "nine-guests-compete", - "nine-ravens-kiss", - "ninety-hats-serve", - "old-knives-wonder", - "old-ways-know", - "perfect-cheetahs-serve", - "pink-falcons-serve", - "poor-moons-confess", - "popular-dancers-join", - "pretty-ladybugs-taste", - "proud-glasses-live", - "purple-feet-smile", - "quick-ladybugs-reply", - "quick-mice-change", - "rare-berries-give", - "rare-melons-battle", - "red-kiwis-compare", - "renovate-0b349f9", - "renovate-0c3644c", - "renovate-53e8b07", - "rich-snakes-rest", - "rotten-mayflies-love", - "selfish-frogs-punch", - "serious-pigs-watch", - "sharp-lobsters-build", - "shiny-years-tap", - "short-apes-relate", - "shy-buses-mix", - "shy-steaks-invite", - "silent-peas-fly", - "silly-buckets-joke", - "silly-socks-lie", - "silly-turkeys-hang", - "silver-wolves-breathe", - "slow-carrots-sniff", - "slow-moles-sin", - "smart-dingos-raise", - "soft-actors-worry", - "soft-boxes-buy", - "soft-snails-notice", - "spotty-coats-clean", - "stale-dots-smile", - "stale-experts-punch", - "stupid-ladybugs-brake", - "swift-fishes-smash", - "tall-falcons-teach", - "tall-tables-hide", - "tall-years-relate", - "tasty-jobs-help", - "thick-clocks-pump", - "thick-tables-travel", - "thin-donkeys-attack", - "thin-scissors-press", - "tough-jeans-camp", - "twenty-islands-wonder", - "twenty-parents-relate", - "two-melons-lie", - "violet-tips-rhyme", - "weak-radios-sing", - "wicked-beers-walk", - "wild-donkeys-rescue", - "witty-moose-itch", - "yellow-roses-tell", - "young-beans-float", - "young-points-drop", - "young-singers-learn" - ] -} diff --git a/.changeset/pretty-icons-glow.md b/.changeset/pretty-icons-glow.md deleted file mode 100644 index 6023e47307..0000000000 --- a/.changeset/pretty-icons-glow.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-plugin-api': patch -'@backstage/backend-dev-utils': patch -'@backstage/backend-defaults': patch -'@backstage/backend-app-api': patch ---- - -Tweaked messaging in the README. diff --git a/.changeset/pretty-jars-peel.md b/.changeset/pretty-jars-peel.md deleted file mode 100644 index 639d4565ed..0000000000 --- a/.changeset/pretty-jars-peel.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/core-plugin-api': minor -'@backstage/app-defaults': minor -'@backstage/core-app-api': minor -'@backstage/plugin-user-settings': minor -'@backstage/plugin-auth-backend': minor ---- - -Added a Bitbucket Server Auth Provider and added its API to the app defaults diff --git a/.changeset/pretty-ladybugs-taste.md b/.changeset/pretty-ladybugs-taste.md deleted file mode 100644 index 5c87cde123..0000000000 --- a/.changeset/pretty-ladybugs-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Adds new type, TableOptions, extending Material Table Options. diff --git a/.changeset/proud-glasses-live.md b/.changeset/proud-glasses-live.md deleted file mode 100644 index ded7a53ce7..0000000000 --- a/.changeset/proud-glasses-live.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-adr': patch ---- - -Support displaying an icon on `AdrSearchResultListItem` diff --git a/.changeset/purple-feet-smile.md b/.changeset/purple-feet-smile.md deleted file mode 100644 index 0416284edf..0000000000 --- a/.changeset/purple-feet-smile.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-radar': patch ---- - -Allow to set additional links to the entry description. diff --git a/.changeset/purple-panthers-know.md b/.changeset/purple-panthers-know.md deleted file mode 100644 index c53c6d8890..0000000000 --- a/.changeset/purple-panthers-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Add additional validation for location references. diff --git a/.changeset/quick-ladybugs-reply.md b/.changeset/quick-ladybugs-reply.md deleted file mode 100644 index 971f6f635b..0000000000 --- a/.changeset/quick-ladybugs-reply.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Fixed publish command missing awsBucketRootPath option. -Fixed publish command having the gcsBucketRootPath option misconfigured, previously returning a boolean vs a string. diff --git a/.changeset/quick-mice-change.md b/.changeset/quick-mice-change.md deleted file mode 100644 index aeee24a021..0000000000 --- a/.changeset/quick-mice-change.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-test-utils': patch -'@backstage/backend-defaults': patch ---- - -Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` diff --git a/.changeset/quiet-pets-count.md b/.changeset/quiet-pets-count.md deleted file mode 100644 index bc7da8f3e7..0000000000 --- a/.changeset/quiet-pets-count.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-test-utils': patch -'@backstage/backend-app-api': patch ---- - -Updated usage of `ServiceFactory`. diff --git a/.changeset/rare-berries-give.md b/.changeset/rare-berries-give.md deleted file mode 100644 index 39e360bf48..0000000000 --- a/.changeset/rare-berries-give.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Packages without a declared `backstage.role` are now ignored. diff --git a/.changeset/rare-melons-battle.md b/.changeset/rare-melons-battle.md deleted file mode 100644 index 85fd72c763..0000000000 --- a/.changeset/rare-melons-battle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-react': minor ---- - -Add `initialFilter` prop to EntityLifecyclePicker. This allows you to set an initial lifecycle for the catalog. diff --git a/.changeset/red-kiwis-compare.md b/.changeset/red-kiwis-compare.md deleted file mode 100644 index 6045367105..0000000000 --- a/.changeset/red-kiwis-compare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. diff --git a/.changeset/red-pugs-tap.md b/.changeset/red-pugs-tap.md deleted file mode 100644 index 85da2b7990..0000000000 --- a/.changeset/red-pugs-tap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Updated Link URL validation to be more strict. diff --git a/.changeset/red-toes-suffer.md b/.changeset/red-toes-suffer.md deleted file mode 100644 index 3d819fb298..0000000000 --- a/.changeset/red-toes-suffer.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-playlist-backend': patch -'@backstage/plugin-bazaar-backend': patch -'@backstage/plugin-vault-backend': patch ---- - -Moving the backend-test-utils to devDependencies. diff --git a/.changeset/renovate-0b349f9.md b/.changeset/renovate-0b349f9.md deleted file mode 100644 index 810adfbc46..0000000000 --- a/.changeset/renovate-0b349f9.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-common': patch -'@backstage/plugin-kubernetes': patch ---- - -Updated dependency `@kubernetes/client-node` to `0.18.1`. diff --git a/.changeset/renovate-0c3644c.md b/.changeset/renovate-0c3644c.md deleted file mode 100644 index c32438b452..0000000000 --- a/.changeset/renovate-0c3644c.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/cli': patch -'@backstage/plugin-scaffolder-backend': patch ---- - -Updated dependency `esbuild` to `^0.17.0`. diff --git a/.changeset/renovate-53e8b07.md b/.changeset/renovate-53e8b07.md deleted file mode 100644 index cb19d8fe8b..0000000000 --- a/.changeset/renovate-53e8b07.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. diff --git a/.changeset/rich-bags-sleep.md b/.changeset/rich-bags-sleep.md deleted file mode 100644 index 14312ac7f4..0000000000 --- a/.changeset/rich-bags-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-pagerduty': patch ---- - -The PagerDutyCard now supports an optional `readOnly` property (``) for suppressing the rendering of the "Create Incident" button from the Backstage UI. diff --git a/.changeset/rich-snakes-rest.md b/.changeset/rich-snakes-rest.md deleted file mode 100644 index 7b42491ba1..0000000000 --- a/.changeset/rich-snakes-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-explore': minor ---- - -The `ToolSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md deleted file mode 100644 index e165129998..0000000000 --- a/.changeset/rotten-birds-build.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-microsoft-calendar': minor ---- - -Created a new plugin `@backstage/plugin-microsoft-calendar` to display events from a Microsoft Calendar. - -please refer to the [README.md](https://github.com/backstage/backstage/blob/master/plugins/microsoft-calendar/README.md) for step-by-step instructions to setup the plugin in your Backstage instance. diff --git a/.changeset/rotten-mayflies-love.md b/.changeset/rotten-mayflies-love.md deleted file mode 100644 index 24d4e4d1be..0000000000 --- a/.changeset/rotten-mayflies-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-user-settings': patch ---- - -Added a message to advise a page reload when toggling feature flags diff --git a/.changeset/selfish-frogs-punch.md b/.changeset/selfish-frogs-punch.md deleted file mode 100644 index 6484576af8..0000000000 --- a/.changeset/selfish-frogs-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': minor ---- - -**BREAKING**: Switched out `LogMeta` type for `JsonObject`. diff --git a/.changeset/serious-grapes-brush.md b/.changeset/serious-grapes-brush.md deleted file mode 100644 index 94eead7282..0000000000 --- a/.changeset/serious-grapes-brush.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github': patch ---- - -Use github team slug and login annotations rather than entity name to infer location annotations diff --git a/.changeset/serious-horses-juggle.md b/.changeset/serious-horses-juggle.md deleted file mode 100644 index 13be1d9715..0000000000 --- a/.changeset/serious-horses-juggle.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-linguist': minor -'@backstage/plugin-linguist-backend': minor -'@backstage/plugin-linguist-common': minor ---- - -Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! diff --git a/.changeset/serious-pigs-watch.md b/.changeset/serious-pigs-watch.md deleted file mode 100644 index 2efd8697f3..0000000000 --- a/.changeset/serious-pigs-watch.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-explore': patch -'@backstage/plugin-search-react': patch ---- - -`ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. - -Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. diff --git a/.changeset/sharp-lobsters-build.md b/.changeset/sharp-lobsters-build.md deleted file mode 100644 index d00333581b..0000000000 --- a/.changeset/sharp-lobsters-build.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/backend-plugin-api': patch ---- - -The `register` methods passed to `createBackendPlugin` and `createBackendModule` -now have dedicated `BackendPluginRegistrationPoints` and -`BackendModuleRegistrationPoints` arguments, respectively. This lets us make it -clear on a type level that it's not possible to pass in extension points as -dependencies to plugins (should only ever be done for modules). This has no -practical effect on code that was already well behaved. diff --git a/.changeset/shiny-years-tap.md b/.changeset/shiny-years-tap.md deleted file mode 100644 index d0d0c14c0a..0000000000 --- a/.changeset/shiny-years-tap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-github-issues': patch ---- - -Updated README.md examples to use correct components and fixed some syntax errors. diff --git a/.changeset/short-apes-relate.md b/.changeset/short-apes-relate.md deleted file mode 100644 index d93c046a4d..0000000000 --- a/.changeset/short-apes-relate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': minor ---- - -**BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. diff --git a/.changeset/shy-buses-mix.md b/.changeset/shy-buses-mix.md deleted file mode 100644 index b7db90d03c..0000000000 --- a/.changeset/shy-buses-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-react': minor ---- - -refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. diff --git a/.changeset/shy-steaks-invite.md b/.changeset/shy-steaks-invite.md deleted file mode 100644 index b4a70589f9..0000000000 --- a/.changeset/shy-steaks-invite.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-bitbucket': patch -'@backstage/plugin-catalog-backend-module-github': patch -'@backstage/plugin-catalog-backend-module-gitlab': patch -'@backstage/plugin-catalog-backend-module-azure': patch -'@backstage/plugin-azure-devops-backend': patch -'@backstage/plugin-git-release-manager': patch -'@backstage/core-components': patch -'@backstage/plugin-playlist-backend': patch -'@backstage/plugin-apache-airflow': patch -'@backstage/plugin-circleci': patch -'@backstage/plugin-bitrise': patch -'@backstage/plugin-sentry': patch ---- - -Internal refactor to not use deprecated `substr` diff --git a/.changeset/silent-peas-fly.md b/.changeset/silent-peas-fly.md deleted file mode 100644 index 8148cb5d12..0000000000 --- a/.changeset/silent-peas-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong diff --git a/.changeset/silent-roses-join.md b/.changeset/silent-roses-join.md deleted file mode 100644 index 5794c8701c..0000000000 --- a/.changeset/silent-roses-join.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -The new backend system testing utilities have now been marked as stable API. diff --git a/.changeset/silly-buckets-joke.md b/.changeset/silly-buckets-joke.md deleted file mode 100644 index 113272c965..0000000000 --- a/.changeset/silly-buckets-joke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-msgraph': patch ---- - -Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration diff --git a/.changeset/silly-socks-lie.md b/.changeset/silly-socks-lie.md deleted file mode 100644 index ae7e1c0b2a..0000000000 --- a/.changeset/silly-socks-lie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-entity-validation': minor ---- - -First implementation for the entity validation UI. For more information refer to its `README.md`. diff --git a/.changeset/silly-turkeys-hang.md b/.changeset/silly-turkeys-hang.md deleted file mode 100644 index 9f712a43c8..0000000000 --- a/.changeset/silly-turkeys-hang.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-scaffolder-react': patch ---- - -Add `ScaffolderLayouts` to `NextScaffolderPage` diff --git a/.changeset/silver-badgers-heal.md b/.changeset/silver-badgers-heal.md deleted file mode 100644 index b1f239c3dc..0000000000 --- a/.changeset/silver-badgers-heal.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -'@backstage/plugin-techdocs-module-addons-contrib': patch -'@backstage/plugin-techdocs': patch ---- - -Create a TechDocs `` addon that allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. - -Here's an example on how to use it in a Backstage app: - -```diff -import { - DefaultTechDocsHome, - TechDocsIndexPage, - TechDocsReaderPage, -} from '@backstage/plugin-techdocs'; -import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; -+import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; - -const AppRoutes = () => { - - // other plugin routes - }> - - - } - > - -+ - - - ; -}; -``` diff --git a/.changeset/silver-wolves-breathe.md b/.changeset/silver-wolves-breathe.md deleted file mode 100644 index 8c1529e142..0000000000 --- a/.changeset/silver-wolves-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sentry': minor ---- - -Add option to filter issues based on the time it was triggered diff --git a/.changeset/slow-carrots-sniff.md b/.changeset/slow-carrots-sniff.md deleted file mode 100644 index d32c2a281e..0000000000 --- a/.changeset/slow-carrots-sniff.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-msgraph': minor ---- - -Improve performance when loading users via group membership. -Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. - -Note, there are still additional per user calls made to load user avatars diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md deleted file mode 100644 index 02e1952312..0000000000 --- a/.changeset/slow-moles-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-circleci': patch ---- - -Making workflow a link diff --git a/.changeset/slow-sloths-do.md b/.changeset/slow-sloths-do.md deleted file mode 100644 index 2d86d477bf..0000000000 --- a/.changeset/slow-sloths-do.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-graph': patch ---- - -Expose additional props on the `CatalogGraphCard` to allow for custom node & label rendering or kind/relation filtering. diff --git a/.changeset/smart-dingos-raise.md b/.changeset/smart-dingos-raise.md deleted file mode 100644 index ea3b0ec82e..0000000000 --- a/.changeset/smart-dingos-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Renamed the export `scaffolderCatalogModule` to `catalogModuleTemplateKind` in order to follow the new recommended naming patterns of backend system items. This is technically a breaking change but in an alpha export, so take care to change your imports if you have already migrated to the new backend system. diff --git a/.changeset/soft-actors-worry.md b/.changeset/soft-actors-worry.md deleted file mode 100644 index 5186499292..0000000000 --- a/.changeset/soft-actors-worry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': minor ---- - -**BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` diff --git a/.changeset/soft-boxes-buy.md b/.changeset/soft-boxes-buy.md deleted file mode 100644 index 581f69cacd..0000000000 --- a/.changeset/soft-boxes-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-gitlab': patch ---- - -Implement Group and User Catalog Provider diff --git a/.changeset/soft-snails-notice.md b/.changeset/soft-snails-notice.md deleted file mode 100644 index ed39ee9591..0000000000 --- a/.changeset/soft-snails-notice.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Prefer schema ordering of template properties during review content generation. diff --git a/.changeset/spotty-coats-clean.md b/.changeset/spotty-coats-clean.md deleted file mode 100644 index 1a48da5688..0000000000 --- a/.changeset/spotty-coats-clean.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-adr': patch ---- - -Render the common `` component when the `backstage.io/adr-location` annotation is missing from the component diff --git a/.changeset/spotty-spiders-love.md b/.changeset/spotty-spiders-love.md deleted file mode 100644 index e0ac3b3cc7..0000000000 --- a/.changeset/spotty-spiders-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Make catalog search result list a bit more customizable diff --git a/.changeset/stale-dots-smile.md b/.changeset/stale-dots-smile.md deleted file mode 100644 index dc1abc926e..0000000000 --- a/.changeset/stale-dots-smile.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/catalog-model': patch ---- - -Add deprecation tag to kubernetes constants in catalog, constants are now defined in plugin-kubernetes-common diff --git a/.changeset/stale-experts-punch.md b/.changeset/stale-experts-punch.md deleted file mode 100644 index 85872bfffe..0000000000 --- a/.changeset/stale-experts-punch.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-user-settings-backend': patch -'@backstage/plugin-periskop-backend': patch -'@backstage/plugin-bazaar-backend': patch -'@backstage/plugin-kafka-backend': patch -'@backstage/plugin-proxy-backend': patch ---- - -Added a Backend System plugin feature diff --git a/.changeset/stale-houses-push.md b/.changeset/stale-houses-push.md deleted file mode 100644 index ef2213ed7b..0000000000 --- a/.changeset/stale-houses-push.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature with this off there is no difference between it and the `default` story. diff --git a/.changeset/stupid-ladybugs-brake.md b/.changeset/stupid-ladybugs-brake.md deleted file mode 100644 index 5a14b82937..0000000000 --- a/.changeset/stupid-ladybugs-brake.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-search-react': minor ---- - -- Create the search results extensions, for more details see the documentation [here](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions); -- Update the `SearchResult`, `SearchResultList` and `SearchResultGroup` components to use extensions and default their props to optionally accept a query, when the query is not passed, the component tries to get it from the search context. diff --git a/.changeset/sweet-yaks-taste.md b/.changeset/sweet-yaks-taste.md deleted file mode 100644 index cbbbaea497..0000000000 --- a/.changeset/sweet-yaks-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -Fix bug in EntityCostsCard if cost aggregation array is empty. Allow title override on the Cost Insights Page diff --git a/.changeset/swift-fishes-smash.md b/.changeset/swift-fishes-smash.md deleted file mode 100644 index cf3f00129c..0000000000 --- a/.changeset/swift-fishes-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -`HttpRouterFactoryOptions.getPath` is now optional as a default value is always provided in the factory. diff --git a/.changeset/tall-falcons-teach.md b/.changeset/tall-falcons-teach.md deleted file mode 100644 index d6608a6597..0000000000 --- a/.changeset/tall-falcons-teach.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Navigation items in mobile sidebar now have aria label. diff --git a/.changeset/tall-tables-hide.md b/.changeset/tall-tables-hide.md deleted file mode 100644 index 3e8011aff2..0000000000 --- a/.changeset/tall-tables-hide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch ---- - -Updated README to include newer API options for incremental entity providers diff --git a/.changeset/tall-years-relate.md b/.changeset/tall-years-relate.md deleted file mode 100644 index 73a0e875b0..0000000000 --- a/.changeset/tall-years-relate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-airbrake': patch ---- - -Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's `catalog-info.yaml` has an airbrake id set in the metadata diff --git a/.changeset/tasty-jobs-help.md b/.changeset/tasty-jobs-help.md deleted file mode 100644 index ad1df8fb8c..0000000000 --- a/.changeset/tasty-jobs-help.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-graphql-voyager': minor ---- - -Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. - -For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. diff --git a/.changeset/thick-clocks-pump.md b/.changeset/thick-clocks-pump.md deleted file mode 100644 index 6b3b6e86de..0000000000 --- a/.changeset/thick-clocks-pump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Fixed bug in review step refactor that caused schema-based display settings for individual property values to be discarded. diff --git a/.changeset/thick-tables-travel.md b/.changeset/thick-tables-travel.md deleted file mode 100644 index d74ed18b8a..0000000000 --- a/.changeset/thick-tables-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-events-node': patch ---- - -Make `EventParams` typed for implementing tidier event handling. diff --git a/.changeset/thin-donkeys-attack.md b/.changeset/thin-donkeys-attack.md deleted file mode 100644 index 2fd0aebb6a..0000000000 --- a/.changeset/thin-donkeys-attack.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Removed the `ref` from all `mockServices`. diff --git a/.changeset/thin-scissors-press.md b/.changeset/thin-scissors-press.md deleted file mode 100644 index 2891d4ca66..0000000000 --- a/.changeset/thin-scissors-press.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-azure-sites': patch ---- - -Fixed `AzureSites` plugin start and stop issue #15904 -Fixed `AzureSites` UI load issue #15907 diff --git a/.changeset/three-geckos-press.md b/.changeset/three-geckos-press.md deleted file mode 100644 index fc1af4fdc0..0000000000 --- a/.changeset/three-geckos-press.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Implement a `showCounts` option to display result counts per type in `SearchType.Accordion` diff --git a/.changeset/tidy-kids-hide.md b/.changeset/tidy-kids-hide.md deleted file mode 100644 index 194497d05c..0000000000 --- a/.changeset/tidy-kids-hide.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-apache-airflow': patch -'@backstage/plugin-azure-sites': patch -'@backstage/plugin-lighthouse': patch ---- - -Prefer Link over plain anchors diff --git a/.changeset/tidy-kings-cough.md b/.changeset/tidy-kings-cough.md deleted file mode 100644 index e908572c8b..0000000000 --- a/.changeset/tidy-kings-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch ---- - -The name of the header used to specify a cluster to the proxy endpoint is now visible in the API reference. diff --git a/.changeset/tough-jeans-camp.md b/.changeset/tough-jeans-camp.md deleted file mode 100644 index 8c7a53190f..0000000000 --- a/.changeset/tough-jeans-camp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/eslint-plugin': minor ---- - -Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. diff --git a/.changeset/twenty-islands-wonder.md b/.changeset/twenty-islands-wonder.md deleted file mode 100644 index fe3c5a05c8..0000000000 --- a/.changeset/twenty-islands-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-react': minor ---- - -Aligned buttons on "Unregister entity" dialog to keep them on the same line diff --git a/.changeset/twenty-parents-relate.md b/.changeset/twenty-parents-relate.md deleted file mode 100644 index a883873c16..0000000000 --- a/.changeset/twenty-parents-relate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -All mock service factories and mock service implementations are now available via the new experimental `mockServices` export. diff --git a/.changeset/twenty-pugs-explain.md b/.changeset/twenty-pugs-explain.md deleted file mode 100644 index 9ac77d2ffb..0000000000 --- a/.changeset/twenty-pugs-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': minor ---- - -**BREAKING**: The `CacheService` has been changed to remove the indirection of `getClient`, instead making the `CacheClient` methods directly available on the `CacheService`. In order to allow for the creation of clients with default options, there is now a new `.withOptions` method that must be implemented as part of the service interface. diff --git a/.changeset/two-melons-lie.md b/.changeset/two-melons-lie.md deleted file mode 100644 index f7abd749d5..0000000000 --- a/.changeset/two-melons-lie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Switch to inline source maps for test transpilation, simplifying editor setups. diff --git a/.changeset/violet-tips-rhyme.md b/.changeset/violet-tips-rhyme.md deleted file mode 100644 index c2d95cfbf9..0000000000 --- a/.changeset/violet-tips-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. diff --git a/.changeset/weak-radios-sing.md b/.changeset/weak-radios-sing.md deleted file mode 100644 index dff287b565..0000000000 --- a/.changeset/weak-radios-sing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. diff --git a/.changeset/wicked-beers-walk.md b/.changeset/wicked-beers-walk.md deleted file mode 100644 index 160a171eb1..0000000000 --- a/.changeset/wicked-beers-walk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. diff --git a/.changeset/wild-donkeys-rescue.md b/.changeset/wild-donkeys-rescue.md deleted file mode 100644 index 43dc3743bb..0000000000 --- a/.changeset/wild-donkeys-rescue.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/backend-test-utils': patch -'@backstage/backend-app-api': patch ---- - -Updated usages of `LogMeta`. diff --git a/.changeset/wild-melons-shout.md b/.changeset/wild-melons-shout.md deleted file mode 100644 index 5a79612f22..0000000000 --- a/.changeset/wild-melons-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': minor ---- - -Switch `ServiceFactory` to be an opaque type, keeping only the `service` field as public API, but also adding a type parameter for the service scope. diff --git a/.changeset/witty-moose-itch.md b/.changeset/witty-moose-itch.md deleted file mode 100644 index e2593bf7e7..0000000000 --- a/.changeset/witty-moose-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': minor ---- - -The `TechDocsSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. diff --git a/.changeset/yellow-roses-tell.md b/.changeset/yellow-roses-tell.md deleted file mode 100644 index ad645df294..0000000000 --- a/.changeset/yellow-roses-tell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-plugin-api': minor ---- - -Switched `BackendFeature` to be an opaque type. diff --git a/.changeset/young-beans-float.md b/.changeset/young-beans-float.md deleted file mode 100644 index ef52b2080a..0000000000 --- a/.changeset/young-beans-float.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -'@backstage/plugin-lighthouse': minor ---- - -Require @backstage/plugin-lighthouse-common package where API implementation moved to. - -**BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: - -- `Audit` -- `AuditBase` -- `AuditCompleted` -- `AuditFailed` -- `AuditRunning` -- `FetchError` -- `LASListRequest` -- `LASListResponse` -- `LighthouseApi` -- `LighthouseCategoryAbbr` -- `LighthouseCategoryId` -- `LighthouseConfigSettings` -- `LighthouseRestApi` -- `TriggerAuditPayload` -- `Website` -- `WebsiteListResponse` diff --git a/.changeset/young-points-drop.md b/.changeset/young-points-drop.md deleted file mode 100644 index 4309d54c2c..0000000000 --- a/.changeset/young-points-drop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-msgraph': patch ---- - -Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. diff --git a/.changeset/young-singers-learn.md b/.changeset/young-singers-learn.md deleted file mode 100644 index 9df5d91fe3..0000000000 --- a/.changeset/young-singers-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-splunk-on-call': patch ---- - -Refactor plugin Card component to not rerender contents unnecessarily. diff --git a/docs/releases/v1.11.0-changelog.md b/docs/releases/v1.11.0-changelog.md new file mode 100644 index 0000000000..42f9e9720b --- /dev/null +++ b/docs/releases/v1.11.0-changelog.md @@ -0,0 +1,2876 @@ +# Release v1.11.0 + +## @backstage/app-defaults@1.2.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-permission-react@0.4.10 + +## @backstage/backend-app-api@0.4.0 + +### Minor Changes + +- 01a075ec1d: **BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. +- 4ae71b7f2e: **BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. +- d31d8e00b3: **BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` + +### Patch Changes + +- a18da2f8b5: Fixed an issue were the log redaction didn't properly escape RegExp characters. +- 5febb216fe: Updated to match the new `CacheService` interface. +- e716946103: Updated usage of the lifecycle service. +- f60cca9da1: Updated database factory to pass service deps required for restoring database state during development. +- 610d65e143: Updates to match new `BackendFeature` type. +- 725383f69d: Tweaked messaging in the README. +- b86efa2d04: Updated usage of `ServiceFactory`. +- ab22515647: The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. +- b729f9f31f: Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong +- ed8b5967d7: `HttpRouterFactoryOptions.getPath` is now optional as a default value is always provided in the factory. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/backend-tasks@0.4.3 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-node@0.7.5 + +## @backstage/backend-dev-utils@0.1.0 + +### Minor Changes + +- 9d9cdea117: Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. + +### Patch Changes + +- 725383f69d: Tweaked messaging in the README. + +## @backstage/backend-plugin-api@0.4.0 + +### Minor Changes + +- e716946103: **BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. +- 0ff03319be: **BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. +- 71a5ec0f06: **BREAKING**: Switched out `LogMeta` type for `JsonObject`. +- 5febb216fe: **BREAKING**: The `CacheService` has been changed to remove the indirection of `getClient`, instead making the `CacheClient` methods directly available on the `CacheService`. In order to allow for the creation of clients with default options, there is now a new `.withOptions` method that must be implemented as part of the service interface. +- b86efa2d04: Switch `ServiceFactory` to be an opaque type, keeping only the `service` field as public API, but also adding a type parameter for the service scope. +- 610d65e143: Switched `BackendFeature` to be an opaque type. + +### Patch Changes + +- 9c9456fd33: Removed the unused `TypesToServiceRef` type +- 181c03edb5: Aligned opaque type markers to all use a `$type` property with namespacing. +- 725383f69d: Tweaked messaging in the README. +- ae88f61e00: The `register` methods passed to `createBackendPlugin` and `createBackendModule` + now have dedicated `BackendPluginRegistrationPoints` and + `BackendModuleRegistrationPoints` arguments, respectively. This lets us make it + clear on a type level that it's not possible to pass in extension points as + dependencies to plugins (should only ever be done for modules). This has no + practical effect on code that was already well behaved. +- Updated dependencies + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/catalog-model@1.2.0 + +### Minor Changes + +- d51668882d: Adds the tRPC API type to the catalog. + +### Patch Changes + +- aece6c57d2: Add additional validation for location references. +- 2518ef5b8a: Add deprecation tag to kubernetes constants in catalog, constants are now defined in plugin-kubernetes-common +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/core-app-api@1.5.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- dff4d8ddb1: Fixed an issue where an explicit port the frontend base URL could break the app. +- Updated dependencies + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + +## @backstage/core-plugin-api@1.4.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + +## @backstage/eslint-plugin@0.1.0 + +### Minor Changes + +- 179d301518: Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. + +## @backstage/plugin-adr@0.4.0 + +### Minor Changes + +- 0a32911d8a: Display title, status and date in ADR navigation, sourced from ADR content and reverse order. +- ec34b535c0: The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- ec34b535c0: Support displaying an icon on `AdrSearchResultListItem` +- 496cf6aff0: Render the common `` component when the `backstage.io/adr-location` annotation is missing from the component +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-adr-common@0.2.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-adr-backend@0.3.0 + +### Minor Changes + +- 0a32911d8a: Display title, status and date in ADR navigation, sourced from ADR content and reverse order. + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-api-docs@0.9.0 + +### Minor Changes + +- 9ed53218a5: Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. + +### Patch Changes + +- 60996f8aba: Updating the readme with better `csp` instructions +- 6856ab98f4: Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-auth-backend@0.18.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + +## @backstage/plugin-catalog@1.8.0 + +### Minor Changes + +- 0c1fc3986c: Added Markdown support in the `AboutCard` description section +- 0eaa579f89: The `CatalogSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- d7f55f6bd2: The list of entities takes into account the title when its different from the name to sort the entities. + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- 7d46ca2f68: Make catalog search result list a bit more customizable + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.2.0 + +### Minor Changes + +- 1ba120faa3: Added new mechanism to handle deltas in incremental providers + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 407dc01fc9: Removing extra imports for `run` script as `TestBackend` auto loads the default factories +- b7e36660d5: Return `EventSubscriber` from `addIncrementalEntityProvider` to hook up to `EventsBackend` +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 77c41b6924: Updated README to include newer API options for incremental entity providers +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.0 + +### Minor Changes + +- fb568e2683: Improve performance when loading users via group membership. + Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + + Note, there are still additional per user calls made to load user avatars + +### Patch Changes + +- 4c86436fdf: Fix MS Graph provider to use target URL for fetching access token +- 0daa328c3a: Extract default transformers to their own file +- 28f9883440: Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration +- c5b119ad9c: Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + +## @backstage/plugin-catalog-react@1.3.0 + +### Minor Changes + +- 929e1afe1b: Add `initialFilter` prop to EntityLifecyclePicker. This allows you to set an initial lifecycle for the catalog. +- fab93c2fe8: Aligned buttons on "Unregister entity" dialog to keep them on the same line + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.10 + +## @backstage/plugin-entity-feedback@0.1.0 + +### Minor Changes + +- a3c86a7ed2: Implement entity feedback plugin, check out the `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-entity-feedback-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-entity-feedback-backend@0.1.0 + +### Minor Changes + +- a3c86a7ed2: Implement entity feedback plugin, check out the `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-entity-feedback-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/plugin-auth-node@0.2.11 + +## @backstage/plugin-entity-feedback-common@0.1.0 + +### Minor Changes + +- a3c86a7ed2: Implement entity feedback plugin, check out the `README.md` for more details! + +## @backstage/plugin-entity-validation@0.1.0 + +### Minor Changes + +- d34b3267f9: First implementation for the entity validation UI. For more information refer to its `README.md`. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-common@1.0.11 + +## @backstage/plugin-explore@0.4.0 + +### Minor Changes + +- 0eaa579f89: The `ToolSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.26 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-graphql-voyager@0.1.0 + +### Minor Changes + +- d1fb4b7bf1: Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + + For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-kubernetes-common@0.6.0 + +### Minor Changes + +- 1728c1ef01: **BREAKING**: Renamed misspelled `LimitRangeFetchReponse` to `LimitRangeFetchResponse`. + +### Patch Changes + +- 2518ef5b8a: New K8s catalog entity annotations added that will replace now deprecated k8s annotations in the catalog-model package. K8s annotation imports should now be made from plugin-kubernetes-common. +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/catalog-model@1.2.0 + +## @backstage/plugin-lighthouse@0.4.0 + +### Minor Changes + +- eef62546ce: Require @backstage/plugin-lighthouse-common package where API implementation moved to. + + **BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: + + - `Audit` + - `AuditBase` + - `AuditCompleted` + - `AuditFailed` + - `AuditRunning` + - `FetchError` + - `LASListRequest` + - `LASListResponse` + - `LighthouseApi` + - `LighthouseCategoryAbbr` + - `LighthouseCategoryId` + - `LighthouseConfigSettings` + - `LighthouseRestApi` + - `TriggerAuditPayload` + - `Website` + - `WebsiteListResponse` + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 4bdd6bcb3c: Prefer Link over plain anchors +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-lighthouse-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-lighthouse-backend@0.1.0 + +### Minor Changes + +- eef62546ce: Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-lighthouse-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-lighthouse-common@0.1.0 + +### Minor Changes + +- eef62546ce: Introduce @backstage/plugin-lighthouse-common with the API implementation + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + +## @backstage/plugin-linguist@0.1.0 + +### Minor Changes + +- 75cfee5688: Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-linguist-backend@0.1.0 + +### Minor Changes + +- 75cfee5688: Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + +## @backstage/plugin-linguist-common@0.1.0 + +### Minor Changes + +- 75cfee5688: Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! + +## @backstage/plugin-microsoft-calendar@0.1.0 + +### Minor Changes + +- 44412375bb: Created a new plugin `@backstage/plugin-microsoft-calendar` to display events from a Microsoft Calendar. + + please refer to the [README.md](https://github.com/backstage/backstage/blob/master/plugins/microsoft-calendar/README.md) for step-by-step instructions to setup the plugin in your Backstage instance. + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-scaffolder@1.11.0 + +### Minor Changes + +- d6bb12a2e7: - **Deprecation** - Deprecated the following exports, please import them directly from `@backstage/plugin-scaffolder-react` instead + + createScaffolderLayout + ScaffolderLayouts + LayoutOptions + LayoutTemplate + +- a521379688: Migrating the `TemplateEditorPage` to work with the new components from `@backstage/plugin-scaffolder-react` + +- 074f7e81b5: Added a missing validator check for items in an array + +- 8c2966536b: Embed scaffolder workflow in other components + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- cbab8ac107: lock versions of `@rjsf/*-beta` packages +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- d2ddde2108: Add `ScaffolderLayouts` to `NextScaffolderPage` +- 0f0da2f256: Prefer schema ordering of template properties during review content generation. +- 38992bdbaf: Fixed bug in review step refactor that caused schema-based display settings for individual property values to be discarded. +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-react@0.4.10 + - @backstage/plugin-scaffolder-common@1.2.5 + +## @backstage/plugin-scaffolder-backend@1.11.0 + +### Minor Changes + +- 0b2952ee4b: Added the option to overwrite files in the `targetPath` of the `template:fetch` action +- 127154930f: Renamed the export `scaffolderCatalogModule` to `catalogModuleTemplateKind` in order to follow the new recommended naming patterns of backend system items. This is technically a breaking change but in an alpha export, so take care to change your imports if you have already migrated to the new backend system. + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. + +- ad3edc402d: **Deprecations**: The following are deprecated and should instead be imported from the new package `@backstage/plugin-scaffolder-node`: + + - `ActionContext` + - `createTemplateAction` + - `TaskSecrets` + - `TemplateAction` + +- 6c70919f1a: Provide better error messaging when GitHub fails due to missing team definitions + +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-scaffolder-common@1.2.5 + +## @backstage/plugin-scaffolder-node@0.1.0 + +### Minor Changes + +- d72866f0cc: New package that takes over some of the types and functionality from `@backstage/plugin-scaffolder-backend` that are shared with other modules + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/catalog-model@1.2.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5 + +## @backstage/plugin-scaffolder-react@1.1.0 + +### Minor Changes + +- a07750745b: Added `DescriptionField` field override to the `next/scaffolder` +- a521379688: Migrating the `TemplateEditorPage` to work with the new components from `@backstage/plugin-scaffolder-react` +- 8c2966536b: Embed scaffolder workflow in other components +- 5555e17313: refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- cbab8ac107: lock versions of `@rjsf/*-beta` packages +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- d2ddde2108: Add `ScaffolderLayouts` to `NextScaffolderPage` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-scaffolder-common@1.2.5 + +## @backstage/plugin-search@1.1.0 + +### Minor Changes + +- 0eaa579f89: Update `SearchModal` component to use `SearchResult` extensions. + +### Patch Changes + +- 26fb21aa8b: Implement a `showCounts` option to display result counts per type in `SearchType.Accordion` +- 66e2aab4c4: Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-react@1.5.0 + +### Minor Changes + +- 0eaa579f89: - Create the search results extensions, for more details see the documentation [here](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions); + - Update the `SearchResult`, `SearchResultList` and `SearchResultGroup` components to use extensions and default their props to optionally accept a query, when the query is not passed, the component tries to get it from the search context. + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-sentry@0.5.0 + +### Minor Changes + +- 6a8d6b9a0c: Add option to filter issues based on the time it was triggered + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-tech-insights-node@0.4.0 + +### Minor Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-techdocs@1.5.0 + +### Minor Changes + +- 20840b36b4: Update DocsTable and EntityListDocsTable to accept overrides for Material Table options. +- 0eaa579f89: The `TechDocsSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- c8e09cc383: Fixed bug in Techdocs reader where a techdocs page with a hash in the URL did not always jump to the document anchor. + +- cad5607411: Improve view: remove footer overlay on large screen + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- 4660b63947: Create a TechDocs `` addon that allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. + + Here's an example on how to use it in a Backstage app: + + ```diff + import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, + } from '@backstage/plugin-techdocs'; + import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + +import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + + const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + + + + + + ; + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3 + +## @backstage/plugin-techdocs-node@1.5.0 + +### Minor Changes + +- dd1e37649f: Deprecated getMkDocsYml in favor of getMkdocsYml (lowercase 'd') + +### Patch Changes + +- 87ab76e55c: Fixed bug caused by recent migration to AWS SDK V3 for techdocs-node. Instead of s3ForcePathStyle, forcePathStyle should be passed. +- 339d9a5b5c: Added support for using a default `mkdocs.yml` configuration file when none is provided +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-user-settings@0.7.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- c4940b6322: Added a message to advise a page reload when toggling feature flags +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-common@0.18.2 + +### Patch Changes + +- 5febb216fe: **BREAKING**: The `CacheClient` interface must now also implement the `withOptions` method. The `.get()` method has also received a type parameter that helps ensure that `undefined` in the event of a cache miss is handled. + + Added a `cacheToPluginCacheManager` helper that converts a `CacheService` into a legacy `PluginCacheManager` instance. + +- 5febb216fe: Updated to match the new `CacheService` interface. + +- e716946103: Updated usage of the lifecycle service. + +- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` + +- 0ff03319be: Updated usage of `createBackendPlugin`. + +- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. + +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. + +- Updated dependencies + - @backstage/backend-app-api@0.4.0 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-dev-utils@0.1.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/backend-defaults@0.1.7 + +### Patch Changes + +- 725383f69d: Tweaked messaging in the README. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- Updated dependencies + - @backstage/backend-app-api@0.4.0 + - @backstage/backend-plugin-api@0.4.0 + +## @backstage/backend-tasks@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-test-utils@0.1.34 + +### Patch Changes + +- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency. +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 1835311713: Added explicit return type signature for `mockServices.config()`. +- e716946103: Updated usage of the lifecycle service. +- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead. +- 610d65e143: Updates to match new `BackendFeature` type. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- b86efa2d04: Updated usage of `ServiceFactory`. +- 17b573e4be: The new backend system testing utilities have now been marked as stable API. +- f1adb2e36b: Removed the `ref` from all `mockServices`. +- d0901c9ba4: All mock service factories and mock service implementations are now available via the new experimental `mockServices` export. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-app-api@0.4.0 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + +## @backstage/catalog-client@1.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/errors@1.1.4 + +## @backstage/cli@0.22.2 + +### Patch Changes + +- 561df21ea3: The `backstage-cli repo test` command now sets a default Jest `--workerIdleMemoryLimit` of 1GB. If needed to ensure that tests are not run in band, `--maxWorkers=2` is set as well. This is the recommended workaround for dealing with Jest workers leaking memory and eventually hitting the heap limit. +- 2815981057: Show module name causing error during build +- dd8a9afe66: Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. +- a9c50af76b: Fixed Webpack loader patterns so that they properly match the file suffix only. +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. +- 6d3abfded1: Switch to inline source maps for test transpilation, simplifying editor setups. +- 90616df9a8: Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. +- Updated dependencies + - @backstage/eslint-plugin@0.1.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + +## @backstage/codemods@0.1.43 + +### Patch Changes + +- 02f1316e57: Moved `commander` to being a regular dependency. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/core-components@0.12.4 + +### Patch Changes + +- 68ce7d0417: Added aria labels on the support button and sidebar +- 5637ebed92: Added a global override for `window.open` that helps prevent security vulnerabilities. +- 910015f5b7: The Button component has been deprecated in favor of the LinkButton component +- 20840b36b4: Adds new type, TableOptions, extending Material Table Options. +- e81a6e0ab5: Updated Link URL validation to be more strict. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 66e2aab4c4: Navigation items in mobile sidebar now have aria label. +- Updated dependencies + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/version-bridge@1.0.3 + +## @backstage/create-app@0.4.37 + +### Patch Changes + +- 12a7b316ee: Bumped create-app version. +- 86a8dfd7b0: Added a check to ensure that Yarn v1 is used when creating new projects. +- 0eaa579f89: Update `SearchPage` template to use `SearchResult` extensions. +- 02f1316e57: Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/dev-utils@1.0.12 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/app-defaults@1.2.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/integration-react@1.1.10 + - @backstage/test-utils@1.2.5 + +## @backstage/integration-react@1.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + +## @backstage/repo-tools@0.1.2 + +### Patch Changes + +- ff63acf30a: Packages without a declared `backstage.role` are now ignored. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + +## @techdocs/cli@1.3.2 + +### Patch Changes + +- dd1e37649f: Deprecated getMkDocsYml in favor of getMkdocsYml (lowercase 'd') + +- dcacf94912: Fix proxying to mkdocs + + The domain localhost may point to both 127.0.0.1 and ::1, ipv4 and ipv6 + and when node tries to lookup localhost it might prefer ipv6 while mkdocs + is only listening on ipv4. This tells node-proxy to target the ipv4 address + instead of relying on localhost hostname lookup. + +- 339d9a5b5c: Added support for using a default `mkdocs.yml` configuration file when none is provided + +- 6e0b6a0d50: Fixed publish command missing awsBucketRootPath option. + Fixed publish command having the gcsBucketRootPath option misconfigured, previously returning a boolean vs a string. + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-techdocs-node@1.5.0 + - @backstage/catalog-model@1.2.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + +## @backstage/test-utils@1.2.5 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.10 + +## @backstage/theme@0.2.17 + +### Patch Changes + +- b7705e176c: Use same table header color as @backstage/core-components Table to meet accessibility color contrast requirements. This change affects material-ui tables. + +## @backstage/plugin-adr-common@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-airbrake@0.3.15 + +### Patch Changes + +- 41377156d0: Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's `catalog-info.yaml` has an airbrake id set in the metadata +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/dev-utils@1.0.12 + - @backstage/test-utils@1.2.5 + +## @backstage/plugin-airbrake-backend@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-allure@0.1.31 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-analytics-module-ga@0.1.26 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-apache-airflow@0.2.8 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 4bdd6bcb3c: Prefer Link over plain anchors +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-api-docs-module-protoc-gen-doc@0.1.1 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend + +## @backstage/plugin-apollo-explorer@0.1.8 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-app-backend@0.3.42 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-node@0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-azure-devops@0.2.6 + +### Patch Changes + +- 347b16ecea: Fixed `AssignedToCurrentUsersTeams` & `CreatedByCurrentUsersTeams` filter in `AzurePullRequestsPage` component. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-devops-backend@0.3.21 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- cc926a59bd: Fixed a bug where the azure devops host in URLs on the readme card was being URL encoded, breaking hosts with ports. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.4 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 98a00a09d5: Fixed `AzureSites` plugin start and stop issue #15904 + Fixed `AzureSites` UI load issue #15907 +- 4bdd6bcb3c: Prefer Link over plain anchors +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-azure-sites-backend@0.1.4 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.39 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-badges-backend@0.1.36 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bazaar@0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/cli@0.22.2 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bazaar-backend@0.2.5 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + +## @backstage/plugin-bitrise@0.1.42 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-catalog-backend@1.7.2 + +### Patch Changes + +- 071354eb7d: Add additional validation as security precations for output entities. +- b977c2e69f: Minor improvements to the descriptions provided with permission rules schemas +- 2380506364: The process of adding or modifying fields in the software-catalog search index has been simplified. For more details, see [how to customize fields in the Software Catalog index](https://backstage.io/docs/features/search/how-to-guides#how-to-customize-fields-in-the-software-catalog-index). +- 9573651919: The previous migration that adds the `search.original_value` column may leave some of the entities not updated. Add a migration script to trigger a reprocessing of the entities. +- 9f71a2fd20: Location rule target patterns now also match hidden files, i.e. path components with a leading dot. +- e716946103: Updated usage of the lifecycle service. +- 1aec041c34: Fixed an issue where entities sometimes were not properly deleted during a full mutation. +- 0ff03319be: Updated usage of `createBackendPlugin`. +- fc73f6aae5: Switched the order of reprocessing statements retroactively in migrations. This only improves the experience for those who at a later time perform a large upgrade of an old Backstage installation. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-scaffolder-common@1.2.5 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-backend-module-aws@0.1.15 + +### Patch Changes + +- 671c6af700: Update to import `LocationSpec` from the correct package. +- 8e025f1347: Added support for `externalId` when assuming role in `AwsS3EntityProvider` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-azure@0.1.13 + +### Patch Changes + +- 2890f47517: This will add the ability to use Azure DevOps with multi project with a single value which is a new feature as previously this had to be done manually for each project that you wanted to add. + + Right now you would have to fill in multiple values in the config to use multiple projects: + + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'firstProject' # this will match the firstProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + yourSecondProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'secondProject' # this will match the secondProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + + With this change you can actually have all projects available where your PAT determines which you have access to, so that includes multiple projects: + + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: '*' # this will match all projects where your PAT has access to + repository: '*' # this will match all repos + path: /catalog-info.yaml + +- 85b04f659a: Internal refactor to not use deprecated `substr` + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.9 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-github@0.2.5 + +### Patch Changes + +- 66158754b4: Add support for filtering out forks +- 80afd5ff8b: Use github team slug and login annotations rather than entity name to infer location annotations +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.13 + +### Patch Changes + +- 49948f644f: The config now consistently uses the term 'instance' to refer to a single GitLab API host. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 52c5685ceb: Implement Group and User Catalog Provider +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/catalog-model@1.2.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-common@1.0.11 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-graph@0.2.27 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- fe19058b74: Fix #16245: The CatalogGraphCard has parameter naming errors for CatalogGraphPage +- 1827710136: Expose additional props on the `CatalogGraphCard` to allow for custom node & label rendering or kind/relation filtering. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + +## @backstage/plugin-catalog-graphql@0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-import@0.9.5 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-catalog-common@1.0.11 + +## @backstage/plugin-catalog-node@1.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + +## @backstage/plugin-cicd-statistics@0.1.17 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.17 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-circleci@0.3.15 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 1616e06047: Making workflow a link +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-cloudbuild@0.3.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-code-climate@0.1.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-code-coverage@0.2.8 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-code-coverage-backend@0.2.8 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-codescene@0.1.10 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-config-schema@0.1.38 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-cost-insights@0.12.4 + +### Patch Changes + +- dfa0bb737e: Fix bug in EntityCostsCard if cost aggregation array is empty. Allow title override on the Cost Insights Page +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-dynatrace@2.0.0 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-events-backend@0.2.3 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-events-node@0.2.3 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-aws-sqs@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-events-node@0.2.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-events-backend-module-azure@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + +## @backstage/plugin-events-backend-module-gerrit@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + +## @backstage/plugin-events-backend-module-github@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-gitlab@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-test-utils@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3 + +## @backstage/plugin-events-node@0.2.3 + +### Patch Changes + +- 19d4abf72c: Make `EventParams` typed for implementing tidier event handling. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + +## @backstage/plugin-explore-backend@0.0.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-explore-react@0.0.26 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-explore-common@0.0.1 + +## @backstage/plugin-firehydrant@0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-fossa@0.2.47 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-gcalendar@0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-gcp-projects@0.3.34 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-git-release-manager@0.3.28 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/integration@1.4.2 + +## @backstage/plugin-github-actions@0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/integration@1.4.2 + +## @backstage/plugin-github-deployments@0.1.46 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + +## @backstage/plugin-github-issues@0.2.4 + +### Patch Changes + +- 3f88ae9d0a: Updated README.md examples to use correct components and fixed some syntax errors. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-github-pull-requests-board@0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/integration@1.4.2 + +## @backstage/plugin-gitops-profiles@0.3.33 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-gocd@0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-graphiql@0.2.47 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-graphql-backend@0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18 + +## @backstage/plugin-home@0.4.31 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 3d1d867d42: Fixed regression that caused the `WelcomeTitle` to not be the right size when passed to the `title` property of the `
    ` component. A Storybook entry was also added for the `WelcomeTitle` +- c553a625d2: remove unused plugin-stack-overflow dependency +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-ilert@0.2.4 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-jenkins@0.7.14 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-jenkins-common@0.1.13 + +## @backstage/plugin-jenkins-backend@0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-jenkins-common@0.1.13 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-jenkins-common@0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-kafka@0.3.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-kafka-backend@0.2.35 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-kubernetes@0.7.8 + +### Patch Changes + +- 145a79a15b: Condenses kubernetes ui plugin to fit more onscreen and increase visibility +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.6.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-kubernetes-backend@0.9.3 + +### Patch Changes + +- 2518ef5b8a: Adding new Cluster detail fields to catalogClusterLocator. Replace deprecated imports with k8s annotations from plugin-kubernetes-common. +- 7ff81f7692: Kubernetes proxy endpoint now accepts content types that are not json +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- a53d06afe5: The name of the header used to specify a cluster to the proxy endpoint is now visible in the API reference. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.6.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + +## @backstage/plugin-newrelic@0.3.33 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-newrelic-dashboard@0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-org@0.6.5 + +### Patch Changes + +- 5a4fa8859b: Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature with this off there is no difference between it and the `default` story. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-org-react@0.1.4 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + +## @backstage/plugin-pagerduty@0.5.8 + +### Patch Changes + +- 804746dd58: The PagerDutyCard now supports an optional `readOnly` property (``) for suppressing the rendering of the "Create Incident" button from the Backstage UI. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-periskop@0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-periskop-backend@0.1.13 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-permission-backend@0.5.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + +## @backstage/plugin-permission-node@0.7.5 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-permission-react@0.4.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-playlist@0.1.6 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.10 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-playlist-backend@0.2.5 + +### Patch Changes + +- b977c2e69f: Minor improvements to the descriptions provided with permission rules schemas +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-proxy-backend@0.2.36 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-rollbar@0.4.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-rollbar-backend@0.1.39 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.17 + +### Patch Changes + +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.10 + +### Patch Changes + +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.2 + +### Patch Changes + +- da418c89e4: Fix broken module exports and dependencies to match a backend module, rather than a frontend plugin. +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.15 + +### Patch Changes + +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-common@1.2.5 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/types@1.0.2 + +## @backstage/plugin-search-backend@1.2.3 + +### Patch Changes + +- 1b30c9a0f7: Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.1.3 + +### Patch Changes + +- 896566906b: Export `decodeElasticSearchPageCursor` utility function +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-pg@0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-node@1.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-shortcuts@0.3.7 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/types@1.0.2 + +## @backstage/plugin-sonarqube@0.6.3 + +### Patch Changes + +- 6310eacc11: Additional export added in order to bind SonarQubeClient to its apiref +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-sonarqube-react@0.1.2 + +## @backstage/plugin-sonarqube-backend@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-sonarqube-react@0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-splunk-on-call@0.4.4 + +### Patch Changes + +- 3598136ac7: Refactor plugin Card component to not rerender contents unnecessarily. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @backstage/plugin-stack-overflow@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-home@0.4.31 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-stack-overflow-backend@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-tech-insights@0.3.7 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-tech-insights-backend@0.5.8 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.0 + - @backstage/catalog-model@1.2.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26 + +### Patch Changes + +- d6b912f963: Surface the cause of the json rules engine +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-tech-insights-common@0.2.10 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/types@1.0.2 + +## @backstage/plugin-tech-radar@0.6.1 + +### Patch Changes + +- acf6c8c10b: Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + + ```diff + - url: 'https://www.javascript.com/', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ + + { + + url: 'https://www.javascript.com/', + + title: 'Learn more', + + }, + ], + ``` + +- 18024a231c: Allow to set additional links to the entry description. + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.10 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/plugin-techdocs@1.5.0 + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/integration-react@1.1.10 + - @backstage/test-utils@1.2.5 + - @backstage/plugin-techdocs-react@1.1.3 + +## @backstage/plugin-techdocs-backend@1.5.3 + +### Patch Changes + +- 6f097023fc: Keep the tech docs sync event stream alive even if it is taking a while to build. +- 339d9a5b5c: Added support for using a default `mkdocs.yml` configuration file when none is provided +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-techdocs-node@1.5.0 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.10 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages + +- 4660b63947: Create a TechDocs `` addon that allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. + + Here's an example on how to use it in a Backstage app: + + ```diff + import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, + } from '@backstage/plugin-techdocs'; + import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + +import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + + const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + + + + + + ; + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-techdocs-react@1.1.3 + +## @backstage/plugin-techdocs-react@1.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/version-bridge@1.0.3 + +## @backstage/plugin-todo@0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-todo-backend@0.1.39 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-user-settings-backend@0.1.6 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + +## @backstage/plugin-vault@0.1.9 + +### Patch Changes + +- fd7a77b9c4: Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-vault-backend@0.2.8 + +### Patch Changes + +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-xcmetrics@0.2.35 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/errors@1.1.4 + +## example-app@0.2.80 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0 + - @backstage/plugin-scaffolder@1.11.0 + - @backstage/plugin-azure-devops@0.2.6 + - @backstage/cli@0.22.2 + - @backstage/plugin-techdocs@1.5.0 + - @backstage/core-components@0.12.4 + - @backstage/plugin-microsoft-calendar@0.1.0 + - @backstage/plugin-catalog-graph@0.2.27 + - @backstage/plugin-code-coverage@0.2.8 + - @backstage/plugin-azure-sites@0.1.4 + - @backstage/plugin-lighthouse@0.4.0 + - @backstage/plugin-shortcuts@0.3.7 + - @backstage/plugin-home@0.4.31 + - @backstage/plugin-tech-insights@0.3.7 + - @backstage/plugin-search@1.1.0 + - @backstage/plugin-api-docs@0.9.0 + - @backstage/plugin-entity-feedback@0.1.0 + - @backstage/plugin-tech-radar@0.6.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10 + - @backstage/plugin-dynatrace@2.0.0 + - @backstage/plugin-playlist@0.1.6 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/plugin-kubernetes@0.7.8 + - @backstage/core-plugin-api@1.4.0 + - @backstage/app-defaults@1.2.0 + - @backstage/plugin-user-settings@0.7.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-pagerduty@0.5.8 + - @backstage/plugin-explore@0.4.0 + - @backstage/plugin-linguist@0.1.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/plugin-apache-airflow@0.2.8 + - @backstage/plugin-circleci@0.3.15 + - @backstage/plugin-sentry@0.5.0 + - @backstage/plugin-org@0.6.5 + - @backstage/plugin-cost-insights@0.12.4 + - @backstage/plugin-airbrake@0.3.15 + - @internal/plugin-catalog-customized@0.0.7 + - @backstage/config@1.0.6 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-badges@0.2.39 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-catalog-import@0.9.5 + - @backstage/plugin-cloudbuild@0.3.15 + - @backstage/plugin-gcalendar@0.3.11 + - @backstage/plugin-gcp-projects@0.3.34 + - @backstage/plugin-github-actions@0.5.15 + - @backstage/plugin-gocd@0.1.21 + - @backstage/plugin-graphiql@0.2.47 + - @backstage/plugin-jenkins@0.7.14 + - @backstage/plugin-kafka@0.3.15 + - @backstage/plugin-newrelic@0.3.33 + - @backstage/plugin-newrelic-dashboard@0.2.8 + - @backstage/plugin-permission-react@0.4.10 + - @backstage/plugin-rollbar@0.4.15 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-stack-overflow@0.1.11 + - @backstage/plugin-techdocs-react@1.1.3 + - @backstage/plugin-todo@0.2.17 + +## example-backend@0.2.80 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/plugin-playlist-backend@0.2.5 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-kubernetes-backend@0.9.3 + - @backstage/plugin-lighthouse-backend@0.1.0 + - @backstage/plugin-code-coverage-backend@0.2.8 + - @backstage/plugin-azure-devops-backend@0.3.21 + - @backstage/plugin-azure-sites-backend@0.1.4 + - @backstage/plugin-adr-backend@0.3.0 + - @backstage/plugin-tech-insights-backend@0.5.8 + - @backstage/plugin-tech-insights-node@0.4.0 + - @backstage/plugin-entity-feedback-backend@0.1.0 + - @backstage/plugin-search-backend@1.2.3 + - @backstage/plugin-techdocs-backend@1.5.3 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/plugin-events-backend@0.2.3 + - @backstage/plugin-kafka-backend@0.2.35 + - @backstage/plugin-proxy-backend@0.2.36 + - @backstage/plugin-app-backend@0.3.42 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-auth-backend@0.18.0 + - @backstage/plugin-linguist-backend@0.1.0 + - @backstage/plugin-events-node@0.2.3 + - example-app@0.2.80 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-badges-backend@0.1.36 + - @backstage/plugin-explore-backend@0.0.4 + - @backstage/plugin-graphql-backend@0.1.32 + - @backstage/plugin-jenkins-backend@0.1.32 + - @backstage/plugin-permission-backend@0.5.17 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-rollbar-backend@0.1.39 + - @backstage/plugin-search-backend-module-pg@0.5.3 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-todo-backend@0.1.39 + +## example-backend-next@0.0.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/plugin-app-backend@0.3.42 + - @backstage/backend-defaults@0.1.7 + +## techdocs-cli-embedded-app@0.2.79 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/cli@0.22.2 + - @backstage/plugin-techdocs@1.5.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/app-defaults@1.2.0 + - @backstage/config@1.0.6 + - @backstage/integration-react@1.1.10 + - @backstage/test-utils@1.2.5 + - @backstage/plugin-techdocs-react@1.1.3 + +## @internal/plugin-catalog-customized@0.0.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/plugin-catalog-react@1.3.0 + +## @internal/plugin-todo-list@1.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + +## @internal/plugin-todo-list-backend@1.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 diff --git a/package.json b/package.json index 286e750f29..5383ba3d51 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.11.0-next.2", + "version": "1.11.0", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index e785ffe05a..f22e4fce1a 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/app-defaults +## 1.2.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-permission-react@0.4.10 + ## 1.1.1-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 8ffdfd60bc..b1a30fdfc6 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.1.1-next.1", + "version": "1.2.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 818d21840d..aae6d02535 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,73 @@ # example-app +## 0.2.80 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0 + - @backstage/plugin-scaffolder@1.11.0 + - @backstage/plugin-azure-devops@0.2.6 + - @backstage/cli@0.22.2 + - @backstage/plugin-techdocs@1.5.0 + - @backstage/core-components@0.12.4 + - @backstage/plugin-microsoft-calendar@0.1.0 + - @backstage/plugin-catalog-graph@0.2.27 + - @backstage/plugin-code-coverage@0.2.8 + - @backstage/plugin-azure-sites@0.1.4 + - @backstage/plugin-lighthouse@0.4.0 + - @backstage/plugin-shortcuts@0.3.7 + - @backstage/plugin-home@0.4.31 + - @backstage/plugin-tech-insights@0.3.7 + - @backstage/plugin-search@1.1.0 + - @backstage/plugin-api-docs@0.9.0 + - @backstage/plugin-entity-feedback@0.1.0 + - @backstage/plugin-tech-radar@0.6.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10 + - @backstage/plugin-dynatrace@2.0.0 + - @backstage/plugin-playlist@0.1.6 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/plugin-kubernetes@0.7.8 + - @backstage/core-plugin-api@1.4.0 + - @backstage/app-defaults@1.2.0 + - @backstage/plugin-user-settings@0.7.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-pagerduty@0.5.8 + - @backstage/plugin-explore@0.4.0 + - @backstage/plugin-linguist@0.1.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/plugin-apache-airflow@0.2.8 + - @backstage/plugin-circleci@0.3.15 + - @backstage/plugin-sentry@0.5.0 + - @backstage/plugin-org@0.6.5 + - @backstage/plugin-cost-insights@0.12.4 + - @backstage/plugin-airbrake@0.3.15 + - @internal/plugin-catalog-customized@0.0.7 + - @backstage/config@1.0.6 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-badges@0.2.39 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-catalog-import@0.9.5 + - @backstage/plugin-cloudbuild@0.3.15 + - @backstage/plugin-gcalendar@0.3.11 + - @backstage/plugin-gcp-projects@0.3.34 + - @backstage/plugin-github-actions@0.5.15 + - @backstage/plugin-gocd@0.1.21 + - @backstage/plugin-graphiql@0.2.47 + - @backstage/plugin-jenkins@0.7.14 + - @backstage/plugin-kafka@0.3.15 + - @backstage/plugin-newrelic@0.3.33 + - @backstage/plugin-newrelic-dashboard@0.2.8 + - @backstage/plugin-permission-react@0.4.10 + - @backstage/plugin-rollbar@0.4.15 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-stack-overflow@0.1.11 + - @backstage/plugin-techdocs-react@1.1.3 + - @backstage/plugin-todo@0.2.17 + ## 0.2.80-next.2 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 226e48f548..793e497996 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.80-next.2", + "version": "0.2.80", "private": true, "backstage": { "role": "frontend" diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index daae24c717..2d5eb8251c 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/backend-app-api +## 0.4.0 + +### Minor Changes + +- 01a075ec1d: **BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. +- 4ae71b7f2e: **BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. +- d31d8e00b3: **BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` + +### Patch Changes + +- a18da2f8b5: Fixed an issue were the log redaction didn't properly escape RegExp characters. +- 5febb216fe: Updated to match the new `CacheService` interface. +- e716946103: Updated usage of the lifecycle service. +- f60cca9da1: Updated database factory to pass service deps required for restoring database state during development. +- 610d65e143: Updates to match new `BackendFeature` type. +- 725383f69d: Tweaked messaging in the README. +- b86efa2d04: Updated usage of `ServiceFactory`. +- ab22515647: The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. +- b729f9f31f: Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong +- ed8b5967d7: `HttpRouterFactoryOptions.getPath` is now optional as a default value is always provided in the factory. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/backend-tasks@0.4.3 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-node@0.7.5 + ## 0.4.0-next.2 ### Minor Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 3bbae1f7fe..f6672f1fbb 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.4.0-next.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 1a495ff771..14e9d60ba2 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/backend-common +## 0.18.2 + +### Patch Changes + +- 5febb216fe: **BREAKING**: The `CacheClient` interface must now also implement the `withOptions` method. The `.get()` method has also received a type parameter that helps ensure that `undefined` in the event of a cache miss is handled. + + Added a `cacheToPluginCacheManager` helper that converts a `CacheService` into a legacy `PluginCacheManager` instance. + +- 5febb216fe: Updated to match the new `CacheService` interface. +- e716946103: Updated usage of the lifecycle service. +- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` +- 0ff03319be: Updated usage of `createBackendPlugin`. +- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/backend-app-api@0.4.0 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-dev-utils@0.1.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.18.2-next.2 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 9619ef25f8..d356d67fab 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.18.2-next.2", + "version": "0.18.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 89f3ee25c6..d55ff77a24 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/backend-defaults +## 0.1.7 + +### Patch Changes + +- 725383f69d: Tweaked messaging in the README. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- Updated dependencies + - @backstage/backend-app-api@0.4.0 + - @backstage/backend-plugin-api@0.4.0 + ## 0.1.7-next.2 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 2d92d15ab8..1e700e2021 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.1.7-next.2", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-dev-utils/CHANGELOG.md b/packages/backend-dev-utils/CHANGELOG.md index 9acf8cf15f..44238676af 100644 --- a/packages/backend-dev-utils/CHANGELOG.md +++ b/packages/backend-dev-utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/backend-dev-utils +## 0.1.0 + +### Minor Changes + +- 9d9cdea117: Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. + +### Patch Changes + +- 725383f69d: Tweaked messaging in the README. + ## 0.1.0-next.0 ### Minor Changes diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json index 6e1cf7d3b0..cb1654d499 100644 --- a/packages/backend-dev-utils/package.json +++ b/packages/backend-dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dev-utils", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 9e8f7a2d83..69cfdac43e 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,15 @@ # example-backend-next +## 0.0.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/plugin-app-backend@0.3.42 + - @backstage/backend-defaults@0.1.7 + ## 0.0.8-next.2 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 8f007dc7ea..578cee8ad9 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.8-next.2", + "version": "0.0.8", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index f5aa2dd9fc..7afc24bb74 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/backend-plugin-api +## 0.4.0 + +### Minor Changes + +- e716946103: **BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. +- 0ff03319be: **BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. +- 71a5ec0f06: **BREAKING**: Switched out `LogMeta` type for `JsonObject`. +- 5febb216fe: **BREAKING**: The `CacheService` has been changed to remove the indirection of `getClient`, instead making the `CacheClient` methods directly available on the `CacheService`. In order to allow for the creation of clients with default options, there is now a new `.withOptions` method that must be implemented as part of the service interface. +- b86efa2d04: Switch `ServiceFactory` to be an opaque type, keeping only the `service` field as public API, but also adding a type parameter for the service scope. +- 610d65e143: Switched `BackendFeature` to be an opaque type. + +### Patch Changes + +- 9c9456fd33: Removed the unused `TypesToServiceRef` type +- 181c03edb5: Aligned opaque type markers to all use a `$type` property with namespacing. +- 725383f69d: Tweaked messaging in the README. +- ae88f61e00: The `register` methods passed to `createBackendPlugin` and `createBackendModule` + now have dedicated `BackendPluginRegistrationPoints` and + `BackendModuleRegistrationPoints` arguments, respectively. This lets us make it + clear on a type level that it's not possible to pass in extension points as + dependencies to plugins (should only ever be done for modules). This has no + practical effect on code that was already well behaved. +- Updated dependencies + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + ## 0.4.0-next.2 ### Minor Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 7243f3485c..f8af9e5bdc 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.4.0-next.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 1e32f34978..3b5a2473c8 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/backend-tasks +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.4.3-next.2 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index ee7d7d6e67..3c7c8ed452 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.4.3-next.2", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index bf7b6c6713..b4a81da494 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/backend-test-utils +## 0.1.34 + +### Patch Changes + +- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency. +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 1835311713: Added explicit return type signature for `mockServices.config()`. +- e716946103: Updated usage of the lifecycle service. +- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead. +- 610d65e143: Updates to match new `BackendFeature` type. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- b86efa2d04: Updated usage of `ServiceFactory`. +- 17b573e4be: The new backend system testing utilities have now been marked as stable API. +- f1adb2e36b: Removed the `ref` from all `mockServices`. +- d0901c9ba4: All mock service factories and mock service implementations are now available via the new experimental `mockServices` export. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-app-api@0.4.0 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + ## 0.1.34-next.2 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 08e00e1c5e..a6f02257d8 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.34-next.2", + "version": "0.1.34", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 7053244da9..dd77d99f65 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,56 @@ # example-backend +## 0.2.80 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/plugin-playlist-backend@0.2.5 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-kubernetes-backend@0.9.3 + - @backstage/plugin-lighthouse-backend@0.1.0 + - @backstage/plugin-code-coverage-backend@0.2.8 + - @backstage/plugin-azure-devops-backend@0.3.21 + - @backstage/plugin-azure-sites-backend@0.1.4 + - @backstage/plugin-adr-backend@0.3.0 + - @backstage/plugin-tech-insights-backend@0.5.8 + - @backstage/plugin-tech-insights-node@0.4.0 + - @backstage/plugin-entity-feedback-backend@0.1.0 + - @backstage/plugin-search-backend@1.2.3 + - @backstage/plugin-techdocs-backend@1.5.3 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/plugin-events-backend@0.2.3 + - @backstage/plugin-kafka-backend@0.2.35 + - @backstage/plugin-proxy-backend@0.2.36 + - @backstage/plugin-app-backend@0.3.42 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-auth-backend@0.18.0 + - @backstage/plugin-linguist-backend@0.1.0 + - @backstage/plugin-events-node@0.2.3 + - example-app@0.2.80 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-badges-backend@0.1.36 + - @backstage/plugin-explore-backend@0.0.4 + - @backstage/plugin-graphql-backend@0.1.32 + - @backstage/plugin-jenkins-backend@0.1.32 + - @backstage/plugin-permission-backend@0.5.17 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-rollbar-backend@0.1.39 + - @backstage/plugin-search-backend-module-pg@0.5.3 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-todo-backend@0.1.39 + ## 0.2.80-next.2 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 76c7e31fc5..87efe3c0c5 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.80-next.2", + "version": "0.2.80", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 1602dfbb79..557129f2f2 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 1.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/errors@1.1.4 + ## 1.3.1-next.1 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index ac233e293a..98257bc190 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.3.1-next.1", + "version": "1.3.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 1f14aba820..0eed8c8dbf 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/catalog-model +## 1.2.0 + +### Minor Changes + +- d51668882d: Adds the tRPC API type to the catalog. + +### Patch Changes + +- aece6c57d2: Add additional validation for location references. +- 2518ef5b8a: Add deprecation tag to kubernetes constants in catalog, constants are now defined in plugin-kubernetes-common +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 1.2.0-next.1 ### Minor Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 117035a82e..00f9543f52 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "1.2.0-next.1", + "version": "1.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 09e7f44eb4..08ffac4595 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/cli +## 0.22.2 + +### Patch Changes + +- 561df21ea3: The `backstage-cli repo test` command now sets a default Jest `--workerIdleMemoryLimit` of 1GB. If needed to ensure that tests are not run in band, `--maxWorkers=2` is set as well. This is the recommended workaround for dealing with Jest workers leaking memory and eventually hitting the heap limit. +- 2815981057: Show module name causing error during build +- dd8a9afe66: Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. +- a9c50af76b: Fixed Webpack loader patterns so that they properly match the file suffix only. +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. +- 6d3abfded1: Switch to inline source maps for test transpilation, simplifying editor setups. +- 90616df9a8: Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. +- Updated dependencies + - @backstage/eslint-plugin@0.1.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + ## 0.22.2-next.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index a3020de1da..9eaef81bec 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.22.2-next.1", + "version": "0.22.2", "publishConfig": { "access": "public" }, diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 5dc610d5c1..c3387fce64 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/codemods +## 0.1.43 + +### Patch Changes + +- 02f1316e57: Moved `commander` to being a regular dependency. +- Updated dependencies + - @backstage/cli-common@0.1.11 + ## 0.1.43-next.0 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 7c6af890b0..17649d49cf 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.43-next.0", + "version": "0.1.43", "publishConfig": { "access": "public", "main": "dist/index.cjs.js" diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 1d682dbc4a..df1cdc318e 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/core-app-api +## 1.5.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- dff4d8ddb1: Fixed an issue where an explicit port the frontend base URL could break the app. +- Updated dependencies + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + ## 1.4.1-next.0 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 391771bd5c..7233564efc 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.4.1-next.0", + "version": "1.5.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 30c4e92173..ee214290ea 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/core-components +## 0.12.4 + +### Patch Changes + +- 68ce7d0417: Added aria labels on the support button and sidebar +- 5637ebed92: Added a global override for `window.open` that helps prevent security vulnerabilities. +- 910015f5b7: The Button component has been deprecated in favor of the LinkButton component +- 20840b36b4: Adds new type, TableOptions, extending Material Table Options. +- e81a6e0ab5: Updated Link URL validation to be more strict. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 66e2aab4c4: Navigation items in mobile sidebar now have aria label. +- Updated dependencies + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/version-bridge@1.0.3 + ## 0.12.4-next.1 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 7eedac93ac..e10ab0ba69 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.12.4-next.1", + "version": "0.12.4", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index 88208e4430..464915bf18 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/core-plugin-api +## 1.4.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + ## 1.3.0 ### Minor Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 490ef25fbe..f1f023eedb 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "1.3.0", + "version": "1.4.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 198d4d92a9..3bdda403aa 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/create-app +## 0.4.37 + +### Patch Changes + +- 12a7b316ee: Bumped create-app version. +- 86a8dfd7b0: Added a check to ensure that Yarn v1 is used when creating new projects. +- 0eaa579f89: Update `SearchPage` template to use `SearchResult` extensions. +- 02f1316e57: Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. +- Updated dependencies + - @backstage/cli-common@0.1.11 + ## 0.4.37-next.2 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index cfdccc5a2b..52c7dcb3fe 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.4.37-next.2", + "version": "0.4.37", "publishConfig": { "access": "public" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 6996180db5..80550d82ca 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/dev-utils +## 1.0.12 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/app-defaults@1.2.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/integration-react@1.1.10 + - @backstage/test-utils@1.2.5 + ## 1.0.12-next.2 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 773dc3cac0..d179aa3c8c 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.12-next.2", + "version": "1.0.12", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 35e3c8f0ea..bc8c2742da 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/eslint-plugin +## 0.1.0 + +### Minor Changes + +- 179d301518: Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. + ## 0.1.0-next.0 ### Minor Changes diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 0aea11d370..8dedd24b1a 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/eslint-plugin", "description": "Backstage ESLint plugin", - "version": "0.1.0-next.0", + "version": "0.1.0", "publishConfig": { "access": "public" }, diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 8813458f86..45f6f0a543 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/integration-react +## 1.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + ## 1.1.10-next.1 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index b287f88f87..d8aabc9f92 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "1.1.10-next.1", + "version": "1.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 2875d54fef..9cf5780cbe 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/repo-tools +## 0.1.2 + +### Patch Changes + +- ff63acf30a: Packages without a declared `backstage.role` are now ignored. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + ## 0.1.2-next.0 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 5ea26060c4..5a5683dff9 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.1.2-next.0", + "version": "0.1.2", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 55d39a6ee5..fe2d1f6b4a 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,24 @@ # techdocs-cli-embedded-app +## 0.2.79 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/cli@0.22.2 + - @backstage/plugin-techdocs@1.5.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/app-defaults@1.2.0 + - @backstage/config@1.0.6 + - @backstage/integration-react@1.1.10 + - @backstage/test-utils@1.2.5 + - @backstage/plugin-techdocs-react@1.1.3 + ## 0.2.79-next.2 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index acee2e8cb3..fe7d6a427c 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.79-next.2", + "version": "0.2.79", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 54bf7d2e8c..a2da4ff5fa 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,27 @@ # @techdocs/cli +## 1.3.2 + +### Patch Changes + +- dd1e37649f: Deprecated getMkDocsYml in favor of getMkdocsYml (lowercase 'd') +- dcacf94912: Fix proxying to mkdocs + + The domain localhost may point to both 127.0.0.1 and ::1, ipv4 and ipv6 + and when node tries to lookup localhost it might prefer ipv6 while mkdocs + is only listening on ipv4. This tells node-proxy to target the ipv4 address + instead of relying on localhost hostname lookup. + +- 339d9a5b5c: Added support for using a default `mkdocs.yml` configuration file when none is provided +- 6e0b6a0d50: Fixed publish command missing awsBucketRootPath option. + Fixed publish command having the gcsBucketRootPath option misconfigured, previously returning a boolean vs a string. +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-techdocs-node@1.5.0 + - @backstage/catalog-model@1.2.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + ## 1.3.2-next.2 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 092bd687bc..016404b12f 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.3.2-next.2", + "version": "1.3.2", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 72ef042554..9a8cf6f264 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/test-utils +## 1.2.5 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.10 + ## 1.2.5-next.0 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 396bbcc4ed..9e82ccc1d7 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.2.5-next.0", + "version": "1.2.5", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index dcdcf2a6ae..a0ad669076 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/theme +## 0.2.17 + +### Patch Changes + +- b7705e176c: Use same table header color as @backstage/core-components Table to meet accessibility color contrast requirements. This change affects material-ui tables. + ## 0.2.16 ### Patch Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index f311aa7c1f..70f7cb2277 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.2.16", + "version": "0.2.17", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index 11f11a19b9..e52d3f91e7 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-adr-backend +## 0.3.0 + +### Minor Changes + +- 0a32911d8a: Display title, status and date in ADR navigation, sourced from ADR content and reverse order. + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6 + - @backstage/plugin-search-common@1.2.1 + ## 0.2.7-next.2 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 33679a00dc..2c16cca144 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.2.7-next.2", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 7ed77717a1..e19d73fe73 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + ## 0.2.6-next.1 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index 7bae7294bb..d7a57fc7d1 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.6-next.1", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index cea1b59deb..72c3625a4d 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-adr +## 0.4.0 + +### Minor Changes + +- 0a32911d8a: Display title, status and date in ADR navigation, sourced from ADR content and reverse order. +- ec34b535c0: The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- ec34b535c0: Support displaying an icon on `AdrSearchResultListItem` +- 496cf6aff0: Render the common `` component when the `backstage.io/adr-location` annotation is missing from the component +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-adr-common@0.2.6 + - @backstage/plugin-search-common@1.2.1 + ## 0.4.0-next.2 ### Minor Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 085729f86f..2ed701baf4 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.4.0-next.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index 16ad4db685..70e2e16713 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-airbrake-backend +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + ## 0.2.15-next.2 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 4d8cde9678..7a6248c391 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.2.15-next.2", + "version": "0.2.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index 0d7ccc3e7e..f5c5d98f35 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-airbrake +## 0.3.15 + +### Patch Changes + +- 41377156d0: Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's `catalog-info.yaml` has an airbrake id set in the metadata +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/dev-utils@1.0.12 + - @backstage/test-utils@1.2.5 + ## 0.3.15-next.2 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index c16cccd171..86713347c0 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.15-next.2", + "version": "0.3.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 02c249120e..f1e5663dea 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-allure +## 0.1.31 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.1.31-next.2 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index cdd0b6c71f..3eae30212a 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.31-next.2", + "version": "0.1.31", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 61cd39fcb8..3527c8ab4b 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-analytics-module-ga +## 0.1.26 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + ## 0.1.26-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index e98aa30b4b..0db33867a4 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.26-next.1", + "version": "0.1.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 1434589d01..f40885d51b 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-apache-airflow +## 0.2.8 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 4bdd6bcb3c: Prefer Link over plain anchors +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/core-plugin-api@1.4.0 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 45116f3171..504f3d5478 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.8-next.1", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md b/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md index 4e030b2264..f1c0b0499b 100644 --- a/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md +++ b/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-api-docs-module-protoc-gen-doc +## 0.1.1 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend + ## 0.1.0 ### Minor Changes diff --git a/plugins/api-docs-module-protoc-gen-doc/package.json b/plugins/api-docs-module-protoc-gen-doc/package.json index 072304d2cf..0fa001ff0e 100644 --- a/plugins/api-docs-module-protoc-gen-doc/package.json +++ b/plugins/api-docs-module-protoc-gen-doc/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs-module-protoc-gen-doc", "description": "Additional functionalities for the api-docs plugin that renders the output of the protoc-gen-doc", - "version": "0.1.0", + "version": "0.1.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 39796b3231..64af7b93e5 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-api-docs +## 0.9.0 + +### Minor Changes + +- 9ed53218a5: Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. + +### Patch Changes + +- 60996f8aba: Updating the readme with better `csp` instructions +- 6856ab98f4: Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.9.0-next.2 ### Minor Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index ee3e88fe11..1d2902117c 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.9.0-next.2", + "version": "0.9.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index 8903d504a9..1e84c3361a 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-apollo-explorer +## 0.1.8 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 7917f5a417..7e53f25627 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.8-next.1", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 617d74217b..9c0438f33a 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-app-backend +## 0.3.42 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + ## 0.3.42-next.2 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index ff9cd8fe5f..4b8f4ece73 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.42-next.2", + "version": "0.3.42", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index f76848cb94..6525ae6e92 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-auth-backend +## 0.18.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + ## 0.17.5-next.2 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 7a855e62a8..3481ae2714 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.17.5-next.2", + "version": "0.18.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 7f9e0f8a33..585358669f 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-node +## 0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.11-next.2 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index fe7adb300d..df1f8e52d5 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.2.11-next.2", + "version": "0.2.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 7488628b80..632fcc078c 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-azure-devops-backend +## 0.3.21 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- cc926a59bd: Fixed a bug where the azure devops host in URLs on the readme card was being URL encoded, breaking hosts with ports. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.3.21-next.2 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 2103acf8fc..5880e8ac2c 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.21-next.2", + "version": "0.3.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index cb4be6f908..e5a43b7104 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-azure-devops +## 0.2.6 + +### Patch Changes + +- 347b16ecea: Fixed `AssignedToCurrentUsersTeams` & `CreatedByCurrentUsersTeams` filter in `AzurePullRequestsPage` component. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.2.6-next.2 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index bfb09aff1d..0000ab8584 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.2.6-next.2", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index e3680abddb..9faccb8d31 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-azure-sites-backend +## 0.1.4 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index c053435161..2d87d3c4b5 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 8c44d24ff3..6f2417817e 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-azure-sites +## 0.1.4 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 98a00a09d5: Fixed `AzureSites` plugin start and stop issue #15904 + Fixed `AzureSites` UI load issue #15907 +- 4bdd6bcb3c: Prefer Link over plain anchors +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 3cfe1ea9c3..47d56fc062 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index ca5bbb859d..4e19efafc0 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-badges-backend +## 0.1.36 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.36-next.2 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 25beed0238..6c30cbf210 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.1.36-next.2", + "version": "0.1.36", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index cefd2f8ccd..16e60ca6df 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-badges +## 0.2.39 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.2.39-next.2 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 4c8edbd09f..85812681ab 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.39-next.2", + "version": "0.2.39", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index 5a7107312e..f007563f54 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-bazaar-backend +## 0.2.5 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + ## 0.2.5-next.2 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 5fba3fcbb3..d0c0fce53d 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.2.5-next.2", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index d3b9cc6a71..8518052168 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-bazaar +## 0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/cli@0.22.2 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + ## 0.2.4-next.2 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 7558aaf2ec..9164bd3824 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.4-next.2", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 65cef85765..8aaea19613 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-bitrise +## 0.1.42 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.1.42-next.2 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 13cc29fd06..1bf2252d3e 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.42-next.2", + "version": "0.1.42", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index d0eeb5702c..c70a80f693 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.1.15 + +### Patch Changes + +- 671c6af700: Update to import `LocationSpec` from the correct package. +- 8e025f1347: Added support for `externalId` when assuming role in `AwsS3EntityProvider` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.15-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 0c9d9af8bb..4082a4f83b 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.1.15-next.2", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 05e48690d7..88b1d869fa 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.13 + +### Patch Changes + +- 2890f47517: This will add the ability to use Azure DevOps with multi project with a single value which is a new feature as previously this had to be done manually for each project that you wanted to add. + + Right now you would have to fill in multiple values in the config to use multiple projects: + + ``` + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'firstProject' # this will match the firstProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + yourSecondProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'secondProject' # this will match the secondProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + ``` + + With this change you can actually have all projects available where your PAT determines which you have access to, so that includes multiple projects: + + ``` + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: '*' # this will match all projects where your PAT has access to + repository: '*' # this will match all repos + path: /catalog-info.yaml + ``` + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.13-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 9552fe1e98..518d7b89ad 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.13-next.2", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 261a192dfa..909153d497 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11 + ## 0.1.9-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 78e1e15653..d9b1c6613f 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.9-next.2", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index b3b825bbc6..cdf0373e0f 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.7-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index edd1fbf0e6..fdfc5649a5 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.7-next.2", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index b07c7a92bb..f0d584f5bc 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.9 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 7df64bbc87..596a87f5b9 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.9-next.2", + "version": "0.2.9", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 9efd73aac5..5e6e186e1c 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.10-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 4e8d389c9c..d945fed9fd 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.10-next.2", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 089cd237e2..ba092566b1 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-backend-module-github +## 0.2.5 + +### Patch Changes + +- 66158754b4: Add support for filtering out forks +- 80afd5ff8b: Use github team slug and login annotations rather than entity name to infer location annotations +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + ## 0.2.5-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 36cd96274a..5d8c5f3659 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.2.5-next.2", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 1f5fc26f38..b444742f89 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.1.13 + +### Patch Changes + +- 49948f644f: The config now consistently uses the term 'instance' to refer to a single GitLab API host. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 52c5685ceb: Implement Group and User Catalog Provider +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.13-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 6668e2f45d..4fb26eeb7e 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.1.13-next.2", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 1953885783..11d2015a02 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.2.0 + +### Minor Changes + +- 1ba120faa3: Added new mechanism to handle deltas in incremental providers + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 407dc01fc9: Removing extra imports for `run` script as `TestBackend` auto loads the default factories +- b7e36660d5: Return `EventSubscriber` from `addIncrementalEntityProvider` to hook up to `EventsBackend` +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 77c41b6924: Updated README to include newer API options for incremental entity providers +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + ## 0.2.0-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index f6ea81996e..9a09ea6ca2 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.2.0-next.2", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 50245d20ae..007cb3b219 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/catalog-model@1.2.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.5.9-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 6a5e1426f7..bf436978a9 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.9-next.2", + "version": "0.5.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 0ee67c7a3c..41dd527462 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.0 + +### Minor Changes + +- fb568e2683: Improve performance when loading users via group membership. + Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + + Note, there are still additional per user calls made to load user avatars + +### Patch Changes + +- 4c86436fdf: Fix MS Graph provider to use target URL for fetching access token +- 0daa328c3a: Extract default transformers to their own file +- 28f9883440: Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration +- c5b119ad9c: Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + ## 0.5.0-next.2 ### Minor Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 7ae0af0bea..65a58e2620 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.5.0-next.2", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 496221964e..5e488c7f56 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.8 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.8-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 8f08f4b183..b9d9332257 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.8-next.2", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 329f641c78..1b9eb1c703 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-catalog-backend +## 1.7.2 + +### Patch Changes + +- 071354eb7d: Add additional validation as security precations for output entities. +- b977c2e69f: Minor improvements to the descriptions provided with permission rules schemas +- 2380506364: The process of adding or modifying fields in the software-catalog search index has been simplified. For more details, see [how to customize fields in the Software Catalog index](https://backstage.io/docs/features/search/how-to-guides#how-to-customize-fields-in-the-software-catalog-index). +- 9573651919: The previous migration that adds the `search.original_value` column may leave some of the entities not updated. Add a migration script to trigger a reprocessing of the entities. +- 9f71a2fd20: Location rule target patterns now also match hidden files, i.e. path components with a leading dot. +- e716946103: Updated usage of the lifecycle service. +- 1aec041c34: Fixed an issue where entities sometimes were not properly deleted during a full mutation. +- 0ff03319be: Updated usage of `createBackendPlugin`. +- fc73f6aae5: Switched the order of reprocessing statements retroactively in migrations. This only improves the experience for those who at a later time perform a large upgrade of an old Backstage installation. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-scaffolder-common@1.2.5 + - @backstage/plugin-search-common@1.2.1 + ## 1.7.2-next.2 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index cebd91932b..297242d6e8 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "1.7.2-next.2", + "version": "1.7.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index b5dc4e29e8..eb6ba1149a 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-common +## 1.0.11 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.0.11-next.1 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 2ba16c3d2a..0ffaf3cff7 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "1.0.11-next.1", + "version": "1.0.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index f8ff5a85b8..ec7502f51f 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-catalog-customized +## 0.0.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.0.7-next.2 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index 9f1e310508..01921d1255 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.7-next.2", + "version": "0.0.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index d45fa8f234..791d8118b3 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-graph +## 0.2.27 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- fe19058b74: Fix #16245: The CatalogGraphCard has parameter naming errors for CatalogGraphPage +- 1827710136: Expose additional props on the `CatalogGraphCard` to allow for custom node & label rendering or kind/relation filtering. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + ## 0.2.27-next.2 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index aee919241c..fb37af29ed 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.27-next.2", + "version": "0.2.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index ee49cb0c3e..5483c379e0 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-graphql +## 0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.3.18-next.1 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index e66e0e0db2..4cfa1dbcc9 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-graphql", "description": "An experimental Backstage catalog GraphQL module", - "version": "0.3.18-next.1", + "version": "0.3.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 9c74c13c88..1e5c09567f 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-import +## 0.9.5 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-catalog-common@1.0.11 + ## 0.9.5-next.2 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index a128aedfd8..b185ce799e 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.9.5-next.2", + "version": "0.9.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 8d5667e4a6..47e3e2a519 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-node +## 1.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + ## 1.3.3-next.2 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 70071dcaea..248b808645 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.3.3-next.2", + "version": "1.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 662b57550a..aed8750ede 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog-react +## 1.3.0 + +### Minor Changes + +- 929e1afe1b: Add `initialFilter` prop to EntityLifecyclePicker. This allows you to set an initial lifecycle for the catalog. +- fab93c2fe8: Aligned buttons on "Unregister entity" dialog to keep them on the same line + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.10 + ## 1.3.0-next.2 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index c3e6cdda46..e66c2b4bb1 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "1.3.0-next.2", + "version": "1.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 204df92577..58ef9dcce9 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-catalog +## 1.8.0 + +### Minor Changes + +- 0c1fc3986c: Added Markdown support in the `AboutCard` description section +- 0eaa579f89: The `CatalogSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- d7f55f6bd2: The list of entities takes into account the title when its different from the name to sort the entities. +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- 7d46ca2f68: Make catalog search result list a bit more customizable +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-search-common@1.2.1 + ## 1.8.0-next.2 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index c5e2c675c9..01ce6dadf0 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "1.8.0-next.2", + "version": "1.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 6516506197..77305d54cb 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.17 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + ## 0.1.11-next.2 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 2c79050e98..ee39fa0b39 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.11-next.2", + "version": "0.1.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 5dcd054002..d80c9b2f7a 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-cicd-statistics +## 0.1.17 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.1.17-next.2 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 795d8a6c8f..55495ee940 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", - "version": "0.1.17-next.2", + "version": "0.1.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 701b6f5a86..7de7dae49a 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-circleci +## 0.3.15 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 1616e06047: Making workflow a link +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.3.15-next.2 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index b72b344eeb..64785a896d 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.3.15-next.2", + "version": "0.3.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index 2b2c262778..e7e9c99da1 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cloudbuild +## 0.3.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.3.15-next.2 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index c1ac873f30..4e519c5274 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.3.15-next.2", + "version": "0.3.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 5264e35a96..f3efbc42de 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-code-climate +## 0.1.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.1.15-next.2 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 9146f3e118..ef1b5f5e76 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.15-next.2", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index a5e6acae94..7bdf96fd44 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-code-coverage-backend +## 0.2.8 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.2.8-next.2 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index f9bcefbd5d..18603858e4 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.2.8-next.2", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 5064067470..9973cabe3e 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-code-coverage +## 0.2.8 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.8-next.2 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index fd15272e38..3d94e6314b 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.2.8-next.2", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index d07630cadf..8129121f2f 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-codescene +## 0.1.10 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 4249e11064..062f01c9c5 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.10-next.1", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 21f079f591..73875b4087 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-config-schema +## 0.1.38 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.1.38-next.1 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 95221632e6..1602caee2d 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.38-next.1", + "version": "0.1.38", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 05d55f3bfe..ba24253414 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-cost-insights +## 0.12.4 + +### Patch Changes + +- dfa0bb737e: Fix bug in EntityCostsCard if cost aggregation array is empty. Allow title override on the Cost Insights Page +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + - @backstage/plugin-cost-insights-common@0.1.1 + ## 0.12.4-next.2 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 02a86793b0..d443637dc5 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.12.4-next.2", + "version": "0.12.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index e403cf500c..c84b3b7355 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-dynatrace +## 2.0.0 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 2.0.0-next.2 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 4cf4a84c33..bca0d276e3 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "2.0.0-next.2", + "version": "2.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-backend/CHANGELOG.md b/plugins/entity-feedback-backend/CHANGELOG.md new file mode 100644 index 0000000000..58e66fb696 --- /dev/null +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -0,0 +1,17 @@ +# @backstage/plugin-entity-feedback-backend + +## 0.1.0 + +### Minor Changes + +- a3c86a7ed2: Implement entity feedback plugin, check out the `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-entity-feedback-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/plugin-auth-node@0.2.11 diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 7fbc7b9f7e..487d5f5d5e 100644 --- a/plugins/entity-feedback-backend/package.json +++ b/plugins/entity-feedback-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback-backend", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-common/CHANGELOG.md b/plugins/entity-feedback-common/CHANGELOG.md new file mode 100644 index 0000000000..e646a4322d --- /dev/null +++ b/plugins/entity-feedback-common/CHANGELOG.md @@ -0,0 +1,7 @@ +# @backstage/plugin-entity-feedback-common + +## 0.1.0 + +### Minor Changes + +- a3c86a7ed2: Implement entity feedback plugin, check out the `README.md` for more details! diff --git a/plugins/entity-feedback-common/package.json b/plugins/entity-feedback-common/package.json index 6316b72943..45a5a2b131 100644 --- a/plugins/entity-feedback-common/package.json +++ b/plugins/entity-feedback-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-entity-feedback-common", "description": "Common functionalities for the entity-feedback plugin", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback/CHANGELOG.md b/plugins/entity-feedback/CHANGELOG.md new file mode 100644 index 0000000000..795156f019 --- /dev/null +++ b/plugins/entity-feedback/CHANGELOG.md @@ -0,0 +1,18 @@ +# @backstage/plugin-entity-feedback + +## 0.1.0 + +### Minor Changes + +- a3c86a7ed2: Implement entity feedback plugin, check out the `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-entity-feedback-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index f8560a9237..6d71b04cc2 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md index aa1e41a299..95fe6c8436 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-entity-validation +## 0.1.0 + +### Minor Changes + +- d34b3267f9: First implementation for the entity validation UI. For more information refer to its `README.md`. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-common@1.0.11 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 6a00e4ad16..e9a47cc1e2 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-validation", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 31596ba402..60c67be93f 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-events-node@0.2.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index bf06d46648..a4ec624c91 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index 83fadeba7b..7a2d2c5b0f 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 12420646ae..88c2dcc795 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 6808429921..545df05bdc 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 04e6248a5f..9fc879cfec 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index e05890268c..c900e0e68f 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 59cded8497..85e9ac92dc 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index 88fe36262b..0505662c26 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-github +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/config@1.0.6 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 6d1fb5b412..1d266ea562 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index 4265fa2c71..e12e1d1130 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/plugin-events-node@0.2.3 + - @backstage/config@1.0.6 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index ad0b497421..7e195bc447 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index 713df91935..7591176488 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 9df1f423e1..e1c86062c6 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-backend-test-utils", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 1d3ae288b4..891d8eff1b 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-events-backend +## 0.2.3 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-events-node@0.2.3 + - @backstage/config@1.0.6 + ## 0.2.3-next.2 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 1154fc0633..fce00f668c 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.2.3-next.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index 99423d1f4a..ef59fc29ed 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-node +## 0.2.3 + +### Patch Changes + +- 19d4abf72c: Make `EventParams` typed for implementing tidier event handling. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + ## 0.2.3-next.2 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index e1b784c6c4..9dffabcaac 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-node", "description": "The plugin-events-node module for @backstage/plugin-events-backend", - "version": "0.2.3-next.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index d2212665fd..b517b8a64f 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @internal/plugin-todo-list-backend +## 1.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + ## 1.0.10-next.2 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 5cda8b5f52..3821e36e7d 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.10-next.2", + "version": "1.0.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index 6b0da992bc..602844625c 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,14 @@ # @internal/plugin-todo-list +## 1.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 1.0.10-next.1 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 7d4378b51f..8839346812 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.10-next.1", + "version": "1.0.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index 80503f396a..db9365c6a7 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-explore-backend +## 0.0.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + ## 0.0.4-next.2 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 77b6b05374..ec26467a8e 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-backend", - "version": "0.0.4-next.2", + "version": "0.0.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index 2dc2181597..08181713f0 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-explore-react +## 0.0.26 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-explore-common@0.0.1 + ## 0.0.25 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index e5a47a4ab7..afc01aca33 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore-react", "description": "A frontend library for Backstage plugins that want to interact with the explore plugin", - "version": "0.0.25", + "version": "0.0.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 58f14ca14d..ad2e9aa19e 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-explore +## 0.4.0 + +### Minor Changes + +- 0eaa579f89: The `ToolSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.26 + - @backstage/plugin-search-common@1.2.1 + ## 0.4.0-next.2 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 888040e1cb..f114076d3c 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.4.0-next.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index c4660e5479..05a126ab2c 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-firehydrant +## 0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.1.32-next.2 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 8edcade92b..b847ddcd43 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.1.32-next.2", + "version": "0.1.32", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 1e906085e4..92779b8525 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-fossa +## 0.2.47 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.2.47-next.2 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index a93d3b3922..90fcdd92fc 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.47-next.2", + "version": "0.2.47", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 5134ae8c3f..17b06fbf57 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-gcalendar +## 0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/errors@1.1.4 + ## 0.3.11-next.1 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 5c84ebe6cb..42c9e11b43 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.11-next.1", + "version": "0.3.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 405a344b28..4bacbec2e5 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gcp-projects +## 0.3.34 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 0.3.34-next.1 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 54bfc85dd2..65af5ae819 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.34-next.1", + "version": "0.3.34", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 3fee0c167b..b12495e3ca 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-git-release-manager +## 0.3.28 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/integration@1.4.2 + ## 0.3.28-next.1 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 171a909b74..2d0fc51bc6 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.28-next.1", + "version": "0.3.28", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 5ae3bafb5d..95776f2b02 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-actions +## 0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/integration@1.4.2 + ## 0.5.15-next.2 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 5165820d62..9aabcbeda5 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.5.15-next.2", + "version": "0.5.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 9c3d9c85e4..c941fe04cd 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-deployments +## 0.1.46 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + ## 0.1.46-next.2 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 17d6239b90..25bb21df67 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.46-next.2", + "version": "0.1.46", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index 35aa080016..df2886dac7 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-issues +## 0.2.4 + +### Patch Changes + +- 3f88ae9d0a: Updated README.md examples to use correct components and fixed some syntax errors. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.2.4-next.2 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 574968d61a..adfb395d5f 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.2.4-next.2", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 8dd45cd956..66fc1300c8 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/integration@1.4.2 + ## 0.1.9-next.2 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 163b7a1967..6d00f621ac 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.9-next.2", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 4ade8515ff..4fb6dec523 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gitops-profiles +## 0.3.33 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 0.3.33-next.1 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index f43e7bb14b..cda5452d9a 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.33-next.1", + "version": "0.3.33", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 01037953b0..b06622a53e 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gocd +## 0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.1.21-next.2 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index f89a11047d..0e2f78e8d2 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.21-next.2", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 68d6fa8e25..d0f32d2729 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphiql +## 0.2.47 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 0.2.47-next.1 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 15d15a38ca..33e9605aa6 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.47-next.1", + "version": "0.2.47", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 28efff9546..9ef3ca16c6 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-backend +## 0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18 + ## 0.1.32-next.2 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 0f44248997..ba1388a790 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-backend", "description": "An experimental Backstage backend plugin for GraphQL", - "version": "0.1.32-next.2", + "version": "0.1.32", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md index 3712169ea1..3eccc7f27b 100644 --- a/plugins/graphql-voyager/CHANGELOG.md +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-graphql-voyager +## 0.1.0 + +### Minor Changes + +- d1fb4b7bf1: Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + + For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index b20d045640..f4e36f3046 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 400ca51ae9..5ac8a7912e 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-home +## 0.4.31 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 3d1d867d42: Fixed regression that caused the `WelcomeTitle` to not be the right size when passed to the `title` property of the `
    ` component. A Storybook entry was also added for the `WelcomeTitle` +- c553a625d2: remove unused plugin-stack-overflow dependency +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + ## 0.4.31-next.2 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 6923b87c83..f3f545c1fd 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.31-next.2", + "version": "0.4.31", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index a12bd0a010..f74dc502ea 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-ilert +## 0.2.4 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.2.4-next.2 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 757b91f78e..7572a5725a 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.2.4-next.2", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index 00f1cdfe1b..9d8732ef50 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-jenkins-backend +## 0.1.32 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-jenkins-common@0.1.13 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.32-next.2 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index d3107cba77..314ef28b0b 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.1.32-next.2", + "version": "0.1.32", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index 75a1470ed0..ec4a80c12c 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-jenkins-common +## 0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index b37d1cfb8d..003a2e84b4 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.13-next.1", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 291f175013..2e38c955cf 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-jenkins +## 0.7.14 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-jenkins-common@0.1.13 + ## 0.7.14-next.2 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index d2c629136b..aa7a7114f7 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.7.14-next.2", + "version": "0.7.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 262cca0397..e7b1512157 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kafka-backend +## 0.2.35 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.35-next.2 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index f0c8d10bde..4bef8db597 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.35-next.2", + "version": "0.2.35", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 74d5b82c97..d0544308b5 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kafka +## 0.3.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + ## 0.3.15-next.2 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 546cf976d5..22790c3510 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.3.15-next.2", + "version": "0.3.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index a8726b238a..da155ef28e 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-kubernetes-backend +## 0.9.3 + +### Patch Changes + +- 2518ef5b8a: Adding new Cluster detail fields to catalogClusterLocator. Replace deprecated imports with k8s annotations from plugin-kubernetes-common. +- 7ff81f7692: Kubernetes proxy endpoint now accepts content types that are not json +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- a53d06afe5: The name of the header used to specify a cluster to the proxy endpoint is now visible in the API reference. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.6.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + ## 0.9.3-next.2 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 002a5e2651..09736e9e8e 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.9.3-next.2", + "version": "0.9.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index cd4df4d54a..a6212ee381 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes-common +## 0.6.0 + +### Minor Changes + +- 1728c1ef01: **BREAKING**: Renamed misspelled `LimitRangeFetchReponse` to `LimitRangeFetchResponse`. + +### Patch Changes + +- 2518ef5b8a: New K8s catalog entity annotations added that will replace now deprecated k8s annotations in the catalog-model package. K8s annotation imports should now be made from plugin-kubernetes-common. +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/catalog-model@1.2.0 + ## 0.6.0-next.2 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 4a4e2a30bf..c6da37cf2e 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-common", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", - "version": "0.6.0-next.2", + "version": "0.6.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index e30b168693..f6588349d3 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-kubernetes +## 0.7.8 + +### Patch Changes + +- 145a79a15b: Condenses kubernetes ui plugin to fit more onscreen and increase visibility +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.6.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + ## 0.7.8-next.2 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index e51726b296..8f8ccfd8e3 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.7.8-next.2", + "version": "0.7.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md index d64d035fa3..30b8acba19 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-lighthouse-backend +## 0.1.0 + +### Minor Changes + +- eef62546ce: Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-lighthouse-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index 60b8570481..df787e1bfe 100644 --- a/plugins/lighthouse-backend/package.json +++ b/plugins/lighthouse-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-backend", "description": "Backend functionalities for lighthouse", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-common/CHANGELOG.md b/plugins/lighthouse-common/CHANGELOG.md index 189507371a..6fb22efc9f 100644 --- a/plugins/lighthouse-common/CHANGELOG.md +++ b/plugins/lighthouse-common/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-lighthouse-common +## 0.1.0 + +### Minor Changes + +- eef62546ce: Introduce @backstage/plugin-lighthouse-common with the API implementation + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/lighthouse-common/package.json b/plugins/lighthouse-common/package.json index 50281e17ba..07061fae69 100644 --- a/plugins/lighthouse-common/package.json +++ b/plugins/lighthouse-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-common", "description": "Common functionalities for lighthouse, to be shared between lighthouse and lighthouse-backend plugin", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index a79e4795e2..040009bc2d 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-lighthouse +## 0.4.0 + +### Minor Changes + +- eef62546ce: Require @backstage/plugin-lighthouse-common package where API implementation moved to. + + **BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: + + - `Audit` + - `AuditBase` + - `AuditCompleted` + - `AuditFailed` + - `AuditRunning` + - `FetchError` + - `LASListRequest` + - `LASListResponse` + - `LighthouseApi` + - `LighthouseCategoryAbbr` + - `LighthouseCategoryId` + - `LighthouseConfigSettings` + - `LighthouseRestApi` + - `TriggerAuditPayload` + - `Website` + - `WebsiteListResponse` + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- 4bdd6bcb3c: Prefer Link over plain anchors +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-lighthouse-common@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/config@1.0.6 + ## 0.4.0-next.2 ### Minor Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index c52858b666..8887a54bb2 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.4.0-next.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist-backend/CHANGELOG.md b/plugins/linguist-backend/CHANGELOG.md new file mode 100644 index 0000000000..d703944d89 --- /dev/null +++ b/plugins/linguist-backend/CHANGELOG.md @@ -0,0 +1,20 @@ +# @backstage/plugin-linguist-backend + +## 0.1.0 + +### Minor Changes + +- 75cfee5688: Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index b1bf7be071..f5035d0f90 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist-backend", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist-common/CHANGELOG.md b/plugins/linguist-common/CHANGELOG.md new file mode 100644 index 0000000000..f2b34faa84 --- /dev/null +++ b/plugins/linguist-common/CHANGELOG.md @@ -0,0 +1,7 @@ +# @backstage/plugin-linguist-common + +## 0.1.0 + +### Minor Changes + +- 75cfee5688: Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! diff --git a/plugins/linguist-common/package.json b/plugins/linguist-common/package.json index 116f785216..c13f40dee2 100644 --- a/plugins/linguist-common/package.json +++ b/plugins/linguist-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-linguist-common", "description": "Common functionalities for the linguist plugin", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist/CHANGELOG.md b/plugins/linguist/CHANGELOG.md new file mode 100644 index 0000000000..13771bd259 --- /dev/null +++ b/plugins/linguist/CHANGELOG.md @@ -0,0 +1,18 @@ +# @backstage/plugin-linguist + +## 0.1.0 + +### Minor Changes + +- 75cfee5688: Introduced the Linguist plugin, checkout the plugin's `README.md` for more details! + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/errors@1.1.4 diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index 18a9ca0ac5..1d33f5260d 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/microsoft-calendar/CHANGELOG.md b/plugins/microsoft-calendar/CHANGELOG.md new file mode 100644 index 0000000000..c8437bc2fb --- /dev/null +++ b/plugins/microsoft-calendar/CHANGELOG.md @@ -0,0 +1,18 @@ +# @backstage/plugin-microsoft-calendar + +## 0.1.0 + +### Minor Changes + +- 44412375bb: Created a new plugin `@backstage/plugin-microsoft-calendar` to display events from a Microsoft Calendar. + + please refer to the [README.md](https://github.com/backstage/backstage/blob/master/plugins/microsoft-calendar/README.md) for step-by-step instructions to setup the plugin in your Backstage instance. + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/errors@1.1.4 diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 2a2e0ca013..848169c527 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-microsoft-calendar", - "version": "0.0.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 78aadfc390..6963241558 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-newrelic-dashboard +## 0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.2.8-next.2 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index 5fe39fd8a3..a93eb0ff59 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.2.8-next.2", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 8858555c7c..bac9a51946 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-newrelic +## 0.3.33 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 0.3.33-next.1 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index e02c690eff..2d4c48966a 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.33-next.1", + "version": "0.3.33", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 6af5e01b9b..59137d4ce7 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-org-react +## 0.1.4 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 6e939b1954..19a8ea024f 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.4-next.2", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 31c7843fa4..3190de3335 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-org +## 0.6.5 + +### Patch Changes + +- 5a4fa8859b: Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature with this off there is no difference between it and the `default` story. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.6.5-next.2 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 240e473b88..4d63db8ea5 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.6.5-next.2", + "version": "0.6.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index f9424baaea..6a64484355 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-pagerduty +## 0.5.8 + +### Patch Changes + +- 804746dd58: The PagerDutyCard now supports an optional `readOnly` property (``) for suppressing the rendering of the "Create Incident" button from the Backstage UI. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.5.8-next.2 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index df20b498ed..44a9dc384c 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.5.8-next.2", + "version": "0.5.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index 1e6ff6f307..68847c839e 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-periskop-backend +## 0.1.13 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + ## 0.1.13-next.2 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index 419d430fac..f66a630185 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.1.13-next.2", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index eeabe21052..76c75f9dae 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-periskop +## 0.1.13 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.1.13-next.2 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 08d875e51f..4445623ff4 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.13-next.2", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index f8cb24795b..53189129b0 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-backend +## 0.5.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + ## 0.5.17-next.2 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index b0b54f6b6e..06006dcbe6 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.17-next.2", + "version": "0.5.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 51c27671db..b9c1d0f5d1 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-node +## 0.7.5 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + ## 0.7.5-next.2 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index c43904fd00..fbe7a8a41f 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-node", "description": "Common permission and authorization utilities for backend plugins", - "version": "0.7.5-next.2", + "version": "0.7.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index 4093b6a430..cd3421bc44 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-permission-react +## 0.4.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/plugin-permission-common@0.7.3 + ## 0.4.9 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index beef8e093d..eeb98df610 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.9", + "version": "0.4.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index c634e3c2e0..fe1154b081 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-playlist-backend +## 0.2.5 + +### Patch Changes + +- b977c2e69f: Minor improvements to the descriptions provided with permission rules schemas +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-playlist-common@0.1.4 + ## 0.2.5-next.2 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index cc3e62eb5a..408629dffa 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.2.5-next.2", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index ea27ee40f3..368d66ee8d 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-playlist +## 0.1.6 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.10 + - @backstage/plugin-playlist-common@0.1.4 + ## 0.1.6-next.2 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 624fdbcd75..9b2ad57646 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.6-next.2", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index ad235f36e8..96f2e16120 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-proxy-backend +## 0.2.36 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + ## 0.2.36-next.2 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 76440ce0a9..21435d5e9c 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.36-next.2", + "version": "0.2.36", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index 9e6955c033..dcb0805ac1 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar-backend +## 0.1.39 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + ## 0.1.39-next.2 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 876c797a78..a574100983 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.39-next.2", + "version": "0.1.39", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 1fe3b3d6ba..be98587ec1 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-rollbar +## 0.4.15 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.4.15-next.2 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 2d65565015..e74c9a63ba 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.4.15-next.2", + "version": "0.4.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 65121ebda8..5537c72931 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.17 + +### Patch Changes + +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.2.17-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 669f498c1e..84d43e0441 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.2.17-next.2", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 51a6a9b796..78d709b904 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.10 + +### Patch Changes + +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/plugin-scaffolder-backend@1.11.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.4.10-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 1e4d881ef0..3183508f92 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.4.10-next.2", + "version": "0.4.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 9a7df7e14b..f017eaf9e2 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.2 + +### Patch Changes + +- da418c89e4: Fix broken module exports and dependencies to match a backend module, rather than a frontend plugin. +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.2-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 903ad54dc1..35be906c44 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.1.2-next.2", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index 5c4acbd85c..e0d4e39c8b 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.15 + +### Patch Changes + +- d72866f0cc: Internal refactor to use the new `@backstage/plugin-scaffolder-node` package for some functionality +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.2.15-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 7ae88b60e6..b4ed76f0a3 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.2.15-next.2", + "version": "0.2.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index d6db10f4ae..f68c91e237 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-scaffolder-backend +## 1.11.0 + +### Minor Changes + +- 0b2952ee4b: Added the option to overwrite files in the `targetPath` of the `template:fetch` action +- 127154930f: Renamed the export `scaffolderCatalogModule` to `catalogModuleTemplateKind` in order to follow the new recommended naming patterns of backend system items. This is technically a breaking change but in an alpha export, so take care to change your imports if you have already migrated to the new backend system. + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- ad3edc402d: **Deprecations**: The following are deprecated and should instead be imported from the new package `@backstage/plugin-scaffolder-node`: + + - `ActionContext` + - `createTemplateAction` + - `TaskSecrets` + - `TemplateAction` + +- 6c70919f1a: Provide better error messaging when GitHub fails due to missing team definitions +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2 + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/plugin-scaffolder-node@0.1.0 + - @backstage/catalog-model@1.2.0 + - @backstage/plugin-catalog-node@1.3.3 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-scaffolder-common@1.2.5 + ## 1.11.0-next.2 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index ccc586f55b..e9c21deeb2 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "1.11.0-next.2", + "version": "1.11.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index e1936292f9..b37be62f2e 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-scaffolder-common +## 1.2.5 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/types@1.0.2 + ## 1.2.5-next.1 ### Patch Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 3ec3528427..cce88a450d 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "1.2.5-next.1", + "version": "1.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index cd2ef0259e..8d9d666ac1 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-scaffolder-node +## 0.1.0 + +### Minor Changes + +- d72866f0cc: New package that takes over some of the types and functionality from `@backstage/plugin-scaffolder-backend` that are shared with other modules + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/catalog-model@1.2.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5 + ## 0.1.0-next.2 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index ce82f57f5f..d4741a009b 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-node", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", - "version": "0.1.0-next.2", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 51fa1abc63..dada3d4353 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-scaffolder-react +## 1.1.0 + +### Minor Changes + +- a07750745b: Added `DescriptionField` field override to the `next/scaffolder` +- a521379688: Migrating the `TemplateEditorPage` to work with the new components from `@backstage/plugin-scaffolder-react` +- 8c2966536b: Embed scaffolder workflow in other components +- 5555e17313: refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- cbab8ac107: lock versions of `@rjsf/*-beta` packages +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- d2ddde2108: Add `ScaffolderLayouts` to `NextScaffolderPage` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-scaffolder-common@1.2.5 + ## 1.1.0-next.2 ### Minor Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index e26bd973d5..043c9d5ee2 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.1.0-next.2", + "version": "1.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 37da3b63e1..d4aaf89ddc 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-scaffolder +## 1.11.0 + +### Minor Changes + +- d6bb12a2e7: - **Deprecation** - Deprecated the following exports, please import them directly from `@backstage/plugin-scaffolder-react` instead + + ``` + createScaffolderLayout + ScaffolderLayouts + LayoutOptions + LayoutTemplate + ``` + +- a521379688: Migrating the `TemplateEditorPage` to work with the new components from `@backstage/plugin-scaffolder-react` +- 074f7e81b5: Added a missing validator check for items in an array +- 8c2966536b: Embed scaffolder workflow in other components + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- cbab8ac107: lock versions of `@rjsf/*-beta` packages +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- d2ddde2108: Add `ScaffolderLayouts` to `NextScaffolderPage` +- 0f0da2f256: Prefer schema ordering of template properties during review content generation. +- 38992bdbaf: Fixed bug in review step refactor that caused schema-based display settings for individual property values to be discarded. +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0 + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-react@0.4.10 + - @backstage/plugin-scaffolder-common@1.2.5 + ## 1.11.0-next.2 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 08381732c2..5eac3c7a0d 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "1.11.0-next.2", + "version": "1.11.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 71dccfef4f..bda1843d96 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.1.3 + +### Patch Changes + +- 896566906b: Export `decodeElasticSearchPageCursor` utility function +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 2eb85f5f2c..714bfa3096 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "1.1.3-next.2", + "version": "1.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 1d17c6707c..90ea0c1a62 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + ## 0.5.3-next.2 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 7883475f34..f1eef09082 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.5.3-next.2", + "version": "0.5.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index bf9306cb1d..a434f2a8b1 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search-backend-node +## 1.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3-next.2 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 1bf73971d1..addca1b93c 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "1.1.3-next.2", + "version": "1.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index c31930c867..48df127d2d 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-backend +## 1.2.3 + +### Patch Changes + +- 1b30c9a0f7: Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5 + - @backstage/plugin-search-backend-node@1.1.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.2.3-next.2 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 31594bc8af..c4c85253e5 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend", "description": "The Backstage backend plugin that provides your backstage app with search", - "version": "1.2.3-next.2", + "version": "1.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index fa58979796..8b75fde4db 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-search-react +## 1.5.0 + +### Minor Changes + +- 0eaa579f89: - Create the search results extensions, for more details see the documentation [here](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions); + - Update the `SearchResult`, `SearchResultList` and `SearchResultGroup` components to use extensions and default their props to optionally accept a query, when the query is not passed, the component tries to get it from the search context. + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.5.0-next.1 ### Patch Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index d353189add..589e28db79 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.5.0-next.1", + "version": "1.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 7853a44abb..cc0d10f5a5 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-search +## 1.1.0 + +### Minor Changes + +- 0eaa579f89: Update `SearchModal` component to use `SearchResult` extensions. + +### Patch Changes + +- 26fb21aa8b: Implement a `showCounts` option to display result counts per type in `SearchType.Accordion` +- 66e2aab4c4: Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.0-next.2 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index c2f635f762..ddec50d70e 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "1.1.0-next.2", + "version": "1.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 922b06c8d8..0a9e0a031a 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-sentry +## 0.5.0 + +### Minor Changes + +- 6a8d6b9a0c: Add option to filter issues based on the time it was triggered + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.5.0-next.2 ### Minor Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index e757ff25a4..5a9d3e5965 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.5.0-next.2", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 94baec18aa..601d12293a 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-shortcuts +## 0.3.7 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/types@1.0.2 + ## 0.3.7-next.1 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 61b48b1c55..31b984907a 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.3.7-next.1", + "version": "0.3.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index 6fb7414acb..7c5b8cfa86 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-sonarqube-backend +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.7-next.2 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 99c0a8b486..80a85d955b 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.1.7-next.2", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-react/CHANGELOG.md b/plugins/sonarqube-react/CHANGELOG.md index b938ce8b37..87257ccda8 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-sonarqube-react +## 0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 53837a47cf..9006d77e84 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-react", - "version": "0.1.2-next.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index e51e0a65ac..04dec88ca9 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-sonarqube +## 0.6.3 + +### Patch Changes + +- 6310eacc11: Additional export added in order to bind SonarQubeClient to its apiref +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-sonarqube-react@0.1.2 + ## 0.6.3-next.2 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 80dd578523..ce0a288d59 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.6.3-next.2", + "version": "0.6.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index c5de65a3d3..e731d7fa24 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-splunk-on-call +## 0.4.4 + +### Patch Changes + +- 3598136ac7: Refactor plugin Card component to not rerender contents unnecessarily. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + ## 0.4.4-next.2 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 097cc1c6fd..4403d0a640 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.4.4-next.2", + "version": "0.4.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index aac07808c9..70a15d0417 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-stack-overflow-backend +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + ## 0.1.11-next.2 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index e40e3e846a..f4845de7a4 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.1.11-next.2", + "version": "0.1.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index f80e350a03..f24e998a58 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-stack-overflow +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-home@0.4.31 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + ## 0.1.11-next.2 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index c9fbe7e7a3..777e128aaa 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.11-next.2", + "version": "0.1.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 28a8ae4e05..f529b48646 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.26 + +### Patch Changes + +- d6b912f963: Surface the cause of the json rules engine +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.26-next.2 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index d3a3260f87..6f43c730cf 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend-module-jsonfc", - "version": "0.1.26-next.2", + "version": "0.1.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index bef4e4c472..115b6f505e 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-tech-insights-backend +## 0.5.8 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.0 + - @backstage/catalog-model@1.2.0 + - @backstage/backend-tasks@0.4.3 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.5.8-next.2 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 2b32f72763..d260229957 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend", - "version": "0.5.8-next.2", + "version": "0.5.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-common/CHANGELOG.md b/plugins/tech-insights-common/CHANGELOG.md index 347a4387d0..bf0f8f62ba 100644 --- a/plugins/tech-insights-common/CHANGELOG.md +++ b/plugins/tech-insights-common/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-tech-insights-common +## 0.2.10 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/types@1.0.2 + ## 0.2.10-next.0 ### Patch Changes diff --git a/plugins/tech-insights-common/package.json b/plugins/tech-insights-common/package.json index d7534b2834..bb6b6e9a57 100644 --- a/plugins/tech-insights-common/package.json +++ b/plugins/tech-insights-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-common", - "version": "0.2.10-next.0", + "version": "0.2.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index aa058fdc3b..953ee74dbc 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-tech-insights-node +## 0.4.0 + +### Minor Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.4.0-next.2 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 7f49679030..08aedf87b3 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-node", - "version": "0.4.0-next.2", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 37e46a4b5a..b013b06868 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-tech-insights +## 0.3.7 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.3.7-next.2 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index e874d2ba30..7e4d8d9ab1 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.3.7-next.2", + "version": "0.3.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index 37aa1e8336..946583c945 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-tech-radar +## 0.6.1 + +### Patch Changes + +- acf6c8c10b: Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + + ```diff + - url: 'https://www.javascript.com/', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ + + { + + url: 'https://www.javascript.com/', + + title: 'Learn more', + + }, + ], + ``` + +- 18024a231c: Allow to set additional links to the entry description. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + ## 0.6.1-next.1 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 2aad00f224..f69657776f 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.6.1-next.1", + "version": "0.6.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index 9afcf3aace..c4e4dc0571 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.10 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/plugin-catalog@1.8.0 + - @backstage/plugin-techdocs@1.5.0 + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/integration-react@1.1.10 + - @backstage/test-utils@1.2.5 + - @backstage/plugin-techdocs-react@1.1.3 + ## 1.0.10-next.2 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 1ad762a09d..c783fb53d7 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.10-next.2", + "version": "1.0.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index dbad0b17b1..3f846de942 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-techdocs-backend +## 1.5.3 + +### Patch Changes + +- 6f097023fc: Keep the tech docs sync event stream alive even if it is taking a while to build. +- 339d9a5b5c: Added support for using a default `mkdocs.yml` configuration file when none is provided +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/plugin-techdocs-node@1.5.0 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.5.3-next.2 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 9c8ce22bef..caf751423d 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "1.5.3-next.2", + "version": "1.5.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 22630158f1..7147a35221 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.0.10 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- 4660b63947: Create a TechDocs `` addon that allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. + + Here's an example on how to use it in a Backstage app: + + ```diff + import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, + } from '@backstage/plugin-techdocs'; + import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + +import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + + const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + + + + + + ; + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-techdocs-react@1.1.3 + ## 1.0.10-next.2 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index c077ccdd6c..8b682095b9 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.0.10-next.2", + "version": "1.0.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index a6d32d8d9f..1d57db1599 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-techdocs-node +## 1.5.0 + +### Minor Changes + +- dd1e37649f: Deprecated getMkDocsYml in favor of getMkdocsYml (lowercase 'd') + +### Patch Changes + +- 87ab76e55c: Fixed bug caused by recent migration to AWS SDK V3 for techdocs-node. Instead of s3ForcePathStyle, forcePathStyle should be passed. +- 339d9a5b5c: Added support for using a default `mkdocs.yml` configuration file when none is provided +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + ## 1.4.6-next.2 ### Patch Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 0a6ffd721b..8e2d1998c8 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.4.6-next.2", + "version": "1.5.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 34617eb3f5..287693865f 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-react +## 1.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/config@1.0.6 + - @backstage/version-bridge@1.0.3 + ## 1.1.3-next.2 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 29587c3e1e..34f78f9d84 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.1.3-next.2", + "version": "1.1.3", "publishConfig": { "access": "public", "alphaTypes": "dist/index.alpha.d.ts", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 352114d77d..2ed0c4fa79 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,65 @@ # @backstage/plugin-techdocs +## 1.5.0 + +### Minor Changes + +- 20840b36b4: Update DocsTable and EntityListDocsTable to accept overrides for Material Table options. +- 0eaa579f89: The `TechDocsSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- c8e09cc383: Fixed bug in Techdocs reader where a techdocs page with a hash in the URL did not always jump to the document anchor. +- cad5607411: Improve view: remove footer overlay on large screen +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- 4660b63947: Create a TechDocs `` addon that allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. + + Here's an example on how to use it in a Backstage app: + + ```diff + import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, + } from '@backstage/plugin-techdocs'; + import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + +import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + + const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + + + + + + ; + }; + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/plugin-search-react@1.5.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3 + ## 1.5.0-next.2 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 5e113f3e7f..42f6103b04 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "1.5.0-next.2", + "version": "1.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 9f44d33d18..42b6b6f37e 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo-backend +## 0.1.39 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/catalog-client@1.3.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.39-next.2 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 6120e76a5e..6a3b22aab4 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.1.39-next.2", + "version": "0.1.39", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 49a8241e30..558e0ca6bc 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo +## 0.2.17 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.2.17-next.2 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index d337834872..3a0dd54fa8 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.2.17-next.2", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 20a7f0c6e5..64becea637 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-user-settings-backend +## 0.1.6 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0 + - @backstage/backend-common@0.18.2 + - @backstage/catalog-model@1.2.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11 + ## 0.1.6-next.2 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index b77050a5af..4461bfea8c 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings-backend", "description": "The Backstage backend plugin to manage user settings", - "version": "0.1.6-next.2", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 478b60b6da..66cd543061 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-user-settings +## 0.7.0 + +### Minor Changes + +- db10b6ef65: Added a Bitbucket Server Auth Provider and added its API to the app defaults + +### Patch Changes + +- c4940b6322: Added a message to advise a page reload when toggling feature flags +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-app-api@1.5.0 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.6.3-next.2 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 319ce98fee..4c5780257e 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.6.3-next.2", + "version": "0.7.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 2c7715cd73..946e776371 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-vault-backend +## 0.2.8 + +### Patch Changes + +- 5b7cd5580d: Moving the backend-test-utils to devDependencies. +- Updated dependencies + - @backstage/backend-common@0.18.2 + - @backstage/backend-tasks@0.4.3 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.8-next.2 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index ae7c89a61c..08e6553e6a 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.2.8-next.2", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index 60fe5c4c8b..2bc324e0a5 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-vault +## 0.1.9 + +### Patch Changes + +- fd7a77b9c4: Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/catalog-model@1.2.0 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/plugin-catalog-react@1.3.0 + - @backstage/errors@1.1.4 + ## 0.1.9-next.2 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 15bae8c3ad..934333f21b 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.9-next.2", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index af4665e980..df67db6b94 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-xcmetrics +## 0.2.35 + +### Patch Changes + +- c51efce2a0: Update docs to always use `yarn add --cwd` for app & backend +- Updated dependencies + - @backstage/core-components@0.12.4 + - @backstage/theme@0.2.17 + - @backstage/core-plugin-api@1.4.0 + - @backstage/errors@1.1.4 + ## 0.2.35-next.1 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 775e884f4b..a2e8c226b3 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.35-next.1", + "version": "0.2.35", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/yarn.lock b/yarn.lock index ac66cab7ca..751f9accd6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3591,17 +3591,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-client@npm:^1.3.0": - version: 1.3.0 - resolution: "@backstage/catalog-client@npm:1.3.0" - dependencies: - "@backstage/catalog-model": ^1.1.5 - "@backstage/errors": ^1.1.4 - cross-fetch: ^3.1.5 - checksum: 7062e9796b5b26cc1b39690af47eacfef90f61241b1f6e775687671e15aaf9b5d3357e670e59b7ca0786fe1b08a3e76d0a00cbfd7328de79acef0f8970659021 - languageName: node - linkType: hard - "@backstage/catalog-client@workspace:^, @backstage/catalog-client@workspace:packages/catalog-client": version: 0.0.0-use.local resolution: "@backstage/catalog-client@workspace:packages/catalog-client" @@ -3614,22 +3603,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@npm:^1.1.3, @backstage/catalog-model@npm:^1.1.5": - version: 1.1.5 - resolution: "@backstage/catalog-model@npm:1.1.5" - dependencies: - "@backstage/config": ^1.0.6 - "@backstage/errors": ^1.1.4 - "@backstage/types": ^1.0.2 - ajv: ^8.10.0 - json-schema: ^0.4.0 - lodash: ^4.17.21 - uuid: ^8.0.0 - checksum: 4a3418994047b616ae154202ef062b7b76bcbc00665998269a0f2242cb7b84e4200e3c3c3df57e10448479c70139ba09484795571f489edf1dd98ade85cc039a - languageName: node - linkType: hard - -"@backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.3, @backstage/catalog-model@^1.1.5, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": version: 0.0.0-use.local resolution: "@backstage/catalog-model@workspace:packages/catalog-model" dependencies: @@ -3844,7 +3818,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config@^1.0.4, @backstage/config@^1.0.6, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": +"@backstage/config@^1.0.4, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": version: 0.0.0-use.local resolution: "@backstage/config@workspace:packages/config" dependencies: @@ -3890,57 +3864,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-components@npm:^0.12.0, @backstage/core-components@npm:^0.12.3": - version: 0.12.3 - resolution: "@backstage/core-components@npm:0.12.3" - dependencies: - "@backstage/config": ^1.0.6 - "@backstage/core-plugin-api": ^1.3.0 - "@backstage/errors": ^1.1.4 - "@backstage/theme": ^0.2.16 - "@backstage/version-bridge": ^1.0.3 - "@material-table/core": ^3.1.0 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.57 - "@react-hookz/web": ^20.0.0 - "@types/react-sparklines": ^1.7.0 - "@types/react-text-truncate": ^0.14.0 - ansi-regex: ^6.0.1 - classnames: ^2.2.6 - d3-selection: ^3.0.0 - d3-shape: ^3.0.0 - d3-zoom: ^3.0.0 - dagre: ^0.8.5 - history: ^5.0.0 - immer: ^9.0.1 - lodash: ^4.17.21 - pluralize: ^8.0.0 - prop-types: ^15.7.2 - qs: ^6.9.4 - rc-progress: 3.4.1 - react-helmet: 6.1.0 - react-hook-form: ^7.12.2 - react-markdown: ^8.0.0 - react-sparklines: ^1.7.0 - react-syntax-highlighter: ^15.4.5 - react-text-truncate: ^0.19.0 - react-use: ^17.3.2 - react-virtualized-auto-sizer: ^1.0.6 - react-window: ^1.8.6 - remark-gfm: ^3.0.1 - zen-observable: ^0.10.0 - zod: ~3.18.0 - peerDependencies: - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: f9c242af07b500f0de738591848776ad3864fb52e30f1979e547d6d607a0eb96df5c1464c8dadb4f5c1d7dd6c10ae74e4c2f60eba5380b704f4b01ac6711131c - languageName: node - linkType: hard - -"@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": +"@backstage/core-components@^0.12.0, @backstage/core-components@^0.12.3, @backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" dependencies: @@ -4096,7 +4020,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/errors@^1.1.4, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": +"@backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": version: 0.0.0-use.local resolution: "@backstage/errors@workspace:packages/errors" dependencies: @@ -4137,26 +4061,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@npm:^1.1.9": - version: 1.1.9 - resolution: "@backstage/integration-react@npm:1.1.9" - dependencies: - "@backstage/config": ^1.0.6 - "@backstage/core-components": ^0.12.3 - "@backstage/core-plugin-api": ^1.3.0 - "@backstage/integration": ^1.4.2 - "@backstage/theme": ^0.2.16 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.57 - react-use: ^17.2.4 - peerDependencies: - react: ^16.13.1 || ^17.0.0 - checksum: 28d94f05e65944308ac6b0709e22336e6e745fe6143f7c3851ccf200725066fc73f53d238e559599d003818c764a86645e3d3f3178e2e5fd0d7cc968d7cc6375 - languageName: node - linkType: hard - -"@backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/integration-react@^1.1.9, @backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": version: 0.0.0-use.local resolution: "@backstage/integration-react@workspace:packages/integration-react" dependencies: @@ -4183,7 +4088,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration@^1.4.2, @backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": +"@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" dependencies: @@ -5238,18 +5143,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@npm:^1.0.10, @backstage/plugin-catalog-common@npm:^1.0.8": - version: 1.0.10 - resolution: "@backstage/plugin-catalog-common@npm:1.0.10" - dependencies: - "@backstage/catalog-model": ^1.1.5 - "@backstage/plugin-permission-common": ^0.7.3 - "@backstage/plugin-search-common": ^1.2.1 - checksum: 3e09f8546aa3c58b4c6dd84beb8ca98378984463e6f05c3a73c9021a26bcf180f76607b735e00cb5af47b10122054781c7d1c7faa385e0708ba3e42e50676acf - languageName: node - linkType: hard - -"@backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": +"@backstage/plugin-catalog-common@^1.0.8, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-common@workspace:plugins/catalog-common" dependencies: @@ -5377,42 +5271,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.1, @backstage/plugin-catalog-react@npm:^1.2.4": - version: 1.2.4 - resolution: "@backstage/plugin-catalog-react@npm:1.2.4" - dependencies: - "@backstage/catalog-client": ^1.3.0 - "@backstage/catalog-model": ^1.1.5 - "@backstage/core-components": ^0.12.3 - "@backstage/core-plugin-api": ^1.3.0 - "@backstage/errors": ^1.1.4 - "@backstage/integration": ^1.4.2 - "@backstage/plugin-catalog-common": ^1.0.10 - "@backstage/plugin-permission-common": ^0.7.3 - "@backstage/plugin-permission-react": ^0.4.9 - "@backstage/theme": ^0.2.16 - "@backstage/types": ^1.0.2 - "@backstage/version-bridge": ^1.0.3 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.57 - classnames: ^2.2.6 - jwt-decode: ^3.1.0 - lodash: ^4.17.21 - material-ui-popup-state: ^1.9.3 - qs: ^6.9.4 - react-use: ^17.2.4 - yaml: ^2.0.0 - zen-observable: ^0.10.0 - peerDependencies: - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 2cbc65f713d2b04af21536e08756d49303030d8ae2e3450d228f81e44d59f9a1f52f3d3961d23169de4213f31414618d4dad7307e4e242b87899487eb118932c - languageName: node - linkType: hard - -"@backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": +"@backstage/plugin-catalog-react@^1.2.1, @backstage/plugin-catalog-react@^1.2.4, @backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-react@workspace:plugins/catalog-react" dependencies: @@ -6598,31 +6457,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-home@npm:^0.4.30": - version: 0.4.30 - resolution: "@backstage/plugin-home@npm:0.4.30" - dependencies: - "@backstage/catalog-model": ^1.1.5 - "@backstage/config": ^1.0.6 - "@backstage/core-components": ^0.12.3 - "@backstage/core-plugin-api": ^1.3.0 - "@backstage/plugin-catalog-react": ^1.2.4 - "@backstage/plugin-stack-overflow": ^0.1.10 - "@backstage/theme": ^0.2.16 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.57 - lodash: ^4.17.21 - react-use: ^17.2.4 - peerDependencies: - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 68420c7b2f94eec976bfeb9c8f704ef37554370e9c646e51de5582bc6fe7184b3021b08f85fbfca92a92b2efbe22261ac866799db4a75c9d10e9f14508cdcfb4 - languageName: node - linkType: hard - -"@backstage/plugin-home@workspace:^, @backstage/plugin-home@workspace:plugins/home": +"@backstage/plugin-home@^0.4.30, @backstage/plugin-home@workspace:^, @backstage/plugin-home@workspace:plugins/home": version: 0.0.0-use.local resolution: "@backstage/plugin-home@workspace:plugins/home" dependencies: @@ -7288,7 +7123,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-common@^0.7.3, @backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": +"@backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-common@workspace:plugins/permission-common" dependencies: @@ -7325,7 +7160,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-react@^0.4.9, @backstage/plugin-permission-react@workspace:^, @backstage/plugin-permission-react@workspace:plugins/permission-react": +"@backstage/plugin-permission-react@workspace:^, @backstage/plugin-permission-react@workspace:plugins/permission-react": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-react@workspace:plugins/permission-react" dependencies: @@ -7880,7 +7715,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-common@^1.2.1, @backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": +"@backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": version: 0.0.0-use.local resolution: "@backstage/plugin-search-common@workspace:plugins/search-common" dependencies: @@ -7890,30 +7725,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-react@npm:^1.4.0": - version: 1.4.0 - resolution: "@backstage/plugin-search-react@npm:1.4.0" - dependencies: - "@backstage/core-components": ^0.12.3 - "@backstage/core-plugin-api": ^1.3.0 - "@backstage/plugin-search-common": ^1.2.1 - "@backstage/theme": ^0.2.16 - "@backstage/types": ^1.0.2 - "@backstage/version-bridge": ^1.0.3 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.57 - lodash: ^4.17.21 - qs: ^6.9.4 - react-use: ^17.3.2 - peerDependencies: - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 0fe18ee991bea12ba4b525b1ed4934f53a2cb2172851762c67d844405206ef8ed335ce8ad6412b4c4f133ae2b1f654b5086cf9997521e2e2cb2ef9cad6891e0a - languageName: node - linkType: hard - "@backstage/plugin-search-react@workspace:^, @backstage/plugin-search-react@workspace:plugins/search-react": version: 0.0.0-use.local resolution: "@backstage/plugin-search-react@workspace:plugins/search-react" @@ -8161,31 +7972,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-stack-overflow@npm:^0.1.10": - version: 0.1.10 - resolution: "@backstage/plugin-stack-overflow@npm:0.1.10" - dependencies: - "@backstage/config": ^1.0.6 - "@backstage/core-components": ^0.12.3 - "@backstage/core-plugin-api": ^1.3.0 - "@backstage/plugin-home": ^0.4.30 - "@backstage/plugin-search-common": ^1.2.1 - "@backstage/plugin-search-react": ^1.4.0 - "@backstage/theme": ^0.2.16 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@testing-library/jest-dom": ^5.10.1 - cross-fetch: ^3.1.5 - lodash: ^4.17.21 - qs: ^6.9.4 - react-use: ^17.2.4 - peerDependencies: - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - checksum: 118f98739a69e3baea4bd72cc165ef3a38166983c6ac3b94668c8dd6709ffedaeec186f21cc871af291a2243565305e4ccea030837020d2b32765ff565cbd2c1 - languageName: node - linkType: hard - "@backstage/plugin-stack-overflow@workspace:^, @backstage/plugin-stack-overflow@workspace:plugins/stack-overflow": version: 0.0.0-use.local resolution: "@backstage/plugin-stack-overflow@workspace:plugins/stack-overflow" @@ -8864,7 +8650,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/types@^1.0.1, @backstage/types@^1.0.2, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": +"@backstage/types@^1.0.1, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@backstage/types@workspace:packages/types" dependencies: @@ -8875,7 +8661,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/version-bridge@^1.0.2, @backstage/version-bridge@^1.0.3, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": +"@backstage/version-bridge@^1.0.2, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": version: 0.0.0-use.local resolution: "@backstage/version-bridge@workspace:packages/version-bridge" dependencies: From 609adb61f2e066ec6de445775192f171a91ecff8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:42:40 +0000 Subject: [PATCH 156/417] fix(deps): update dependency @tanstack/react-query to v4.24.6 Signed-off-by: Renovate Bot --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index ac66cab7ca..40664beaee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13660,18 +13660,18 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:4.24.4": - version: 4.24.4 - resolution: "@tanstack/query-core@npm:4.24.4" - checksum: b357e950a41e5769878a3bfe9dd56a66828ccebb2f9396e568e8835bed71eb37926770a461e3aa5bafb7e1121c5141cee86aedf3ced88a2eacf754d545b107cd +"@tanstack/query-core@npm:4.24.6": + version: 4.24.6 + resolution: "@tanstack/query-core@npm:4.24.6" + checksum: 495dff04f27d72174051f97676fce0fbe322bca966edb7f174f0005a3363ac0300c31eb06255dafa7ee519a430840542379f5ec9f6846903b6bb878e46c33656 languageName: node linkType: hard "@tanstack/react-query@npm:^4.1.3": - version: 4.24.4 - resolution: "@tanstack/react-query@npm:4.24.4" + version: 4.24.6 + resolution: "@tanstack/react-query@npm:4.24.6" dependencies: - "@tanstack/query-core": 4.24.4 + "@tanstack/query-core": 4.24.6 use-sync-external-store: ^1.2.0 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -13682,7 +13682,7 @@ __metadata: optional: true react-native: optional: true - checksum: 8cf008d690fc5d336f6471ea2bc0751189f03874dcc7930cf8944fb57fa34e3b5347823775dbd36629d53a7aacb9ce87482b1adb3ad80d277a3a6c73b797f6a2 + checksum: 250bc2cba8dd7da61680a8e360fac87ee057d079ee3be950c76dbc063f941119817634857c1cb0d9b12042dd5d4fbe847c02af5dfb89ae8daa0f9339f87ad605 languageName: node linkType: hard From b84349e2f643769be1d542f0cfe54d14073e2fc1 Mon Sep 17 00:00:00 2001 From: Alex Crome Date: Tue, 14 Feb 2023 14:50:37 +0000 Subject: [PATCH 157/417] PR Feedback Signed-off-by: Alex Crome --- .changeset/twenty-jeans-speak.md | 2 +- docs/auth/microsoft/azure-easyauth.md | 6 +++--- .../providers/azure-easyauth/provider.test.ts | 2 +- .../src/providers/azure-easyauth/provider.ts | 18 ++++-------------- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/.changeset/twenty-jeans-speak.md b/.changeset/twenty-jeans-speak.md index c7385031e6..fddcc2eedd 100644 --- a/.changeset/twenty-jeans-speak.md +++ b/.changeset/twenty-jeans-speak.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-auth-backend': minor +'@backstage/plugin-auth-backend': patch --- Added authentication provider for Azure Easy Authentication. diff --git a/docs/auth/microsoft/azure-easyauth.md b/docs/auth/microsoft/azure-easyauth.md index 00d798dce9..3571a3e5c5 100644 --- a/docs/auth/microsoft/azure-easyauth.md +++ b/docs/auth/microsoft/azure-easyauth.md @@ -19,7 +19,7 @@ export default async function createPlugin( env: PluginEnvironment, ): Promise { const authProviderFactories = { - 'azure-easyAuth': providers.easyAuth.create({ + 'azure-easyauth': providers.easyAuth.create({ signIn: { resolver: async (info, ctx) => { const { @@ -52,7 +52,7 @@ export default async function createPlugin( ``` Now the backend is ready to serve auth requests on the -`/api/auth/azure-easyAuth/refresh` endpoint. All that's left is to update the frontend +`/api/auth/azure-easyauth/refresh` endpoint. All that's left is to update the frontend sign-in mechanism to poll that endpoint through the IAP, on the user's behalf. ## Frontend Changes @@ -65,7 +65,7 @@ installed in `packages/app/src/App.tsx` like this: const app = createApp({ components: { -+ SignInPage: props => , ++ SignInPage: props => , ``` See the [Sign-In with Proxy Providers](../index.md#sign-in-with-proxy-providers) section for more information. diff --git a/plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts b/plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts index f9f0796f7a..b521ddeb10 100644 --- a/plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts +++ b/plugins/auth-backend/src/providers/azure-easyauth/provider.test.ts @@ -256,7 +256,7 @@ describe('easyAuth factory', () => { }); expect(() => factory({} as any)).toThrow( - 'Authentication provider is not Azure Active Directory', + 'Authentication provider is not Azure Active Directory', ); }); diff --git a/plugins/auth-backend/src/providers/azure-easyauth/provider.ts b/plugins/auth-backend/src/providers/azure-easyauth/provider.ts index 8debc3afb6..405ca9ed59 100644 --- a/plugins/auth-backend/src/providers/azure-easyauth/provider.ts +++ b/plugins/auth-backend/src/providers/azure-easyauth/provider.ts @@ -178,25 +178,15 @@ function validateAppServiceConfiguration(env: NodeJS.ProcessEnv) { if (env.WEBSITE_SKU === undefined) { throw new Error('Backstage is not running on Azure App Services'); } - if (!isEqualCaseInsensitive(env.WEBSITE_AUTH_ENABLED, 'True')) { + if (env.WEBSITE_AUTH_ENABLED?.toLowerCase() !== 'true') { throw new Error('Azure App Services does not have authentication enabled'); } if ( - !isEqualCaseInsensitive( - env.WEBSITE_AUTH_DEFAULT_PROVIDER, - 'AzureActiveDirectory', - ) + env.WEBSITE_AUTH_DEFAULT_PROVIDER?.toLowerCase() !== 'azureactivedirectory' ) { - throw new Error('Authentication provider is not Azure Active Directory'); + throw new Error('Authentication provider is not Azure Active Directory'); } - if (!isEqualCaseInsensitive(process.env.WEBSITE_AUTH_TOKEN_STORE, 'True')) { + if (process.env.WEBSITE_AUTH_TOKEN_STORE?.toLowerCase() !== 'true') { throw new Error('Token Store is not enabled'); } } - -function isEqualCaseInsensitive(left: string | undefined, right: string) { - return ( - left !== undefined && - right.localeCompare(left, undefined, { sensitivity: 'base' }) === 0 - ); -} From d37248ac6c3f26a359153c536b881cf26cbe72fd Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 14 Feb 2023 16:13:56 +0100 Subject: [PATCH 158/417] docs: add release notes for 1.11 Signed-off-by: blam --- .github/vale/Vocab/Backstage/accept.txt | 1 + docs/releases/v1.11.0.md | 100 ++++++++++++++++++++++++ microsite/sidebars.json | 1 + 3 files changed, 102 insertions(+) create mode 100644 docs/releases/v1.11.0.md diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 08e325c38b..63fa474115 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -241,6 +241,7 @@ OAuth octokit oidc Okta +Olausson Oldsberg onboarding Onboarding diff --git a/docs/releases/v1.11.0.md b/docs/releases/v1.11.0.md new file mode 100644 index 0000000000..da33e65ff0 --- /dev/null +++ b/docs/releases/v1.11.0.md @@ -0,0 +1,100 @@ +--- +id: v1.11.0 +title: v1.11.0 +description: Backstage Release v1.11.0 +--- + +These are the release notes for the v1.11.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done. + +## Highlights + +### Scaffolder Alpha + +With this release, we’ve been working on getting things ready for testing for the upcoming Scaffolder v2.0.0 release, and there’s now the ability to test the upcoming version in the form of an alpha! It would be great if you have the time to test out the new release to see if all your templates work as expected. There’s some documentation on how to test out the new version and what’s new under [testing scaffolder alpha](https://backstage.io/docs/features/software-templates/testing-scaffolder-alpha). + +We’d love to hear if you have any issues when testing the new version, please reach out on Discord or [create a new issue](http://github.com/backstage/backstage/issues/new) if there’s anything you find! + +### Backend System Alpha + +The [new Backend System](https://backstage.io/docs/backend-system/) is now in alpha. We encourage plugin owners to try out the new system by adding support for it in their plugin backends, but we do not yet recommend migrating over to using this new system for production backend deployments. + +This new system aims to greatly simplify the setup and wiring of Backstage backends. It formalizes and simplifies how common services and plugins are installed and interact with each other, and restructures both plugins and backends to make them much easier to maintain. To read more about this new system and how it came about, check out our [blog post](#TODO) on the topic. + +The documentation starts [here](https://backstage.io/docs/backend-system/). Migration guides exist to help you get your [backend](https://backstage.io/docs/backend-system/building-backends/migrating) and [plugins](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating) migrated, but you don’t have to do it all in one go - the path forward can be incremental. + +If you were already using the new backend system before this release, you may also be interested in the following. + +There have been a number of tweaks to types and exports, following a thorough API review before its alpha release. Notably, + +Service factories are now exported with the pattern `ServiceFactory` instead of `Factory`, e.g. `configServiceFactory` +The `createBackendPlugin` parameter that used to be named `id` is now `pluginId` +The interface of the `CacheService` has changed slightly, so you may want to use the new `cacheToPluginCacheManager` to get compatibility with your not-yet-converted backend plugins +The `scaffolderCatalogModule` that was exported from the Scaffolder backend is renamed to `catalogModuleTemplateKind`, to fit the proper naming patterns + +There are a few smaller tweaks as well, that you can read about in the [`@backstage/backend-app-api`](https://github.com/backstage/backstage/blob/master/packages/backend-app-api/CHANGELOG.md) and [`@backstage/backend-plugin-api`](https://github.com/backstage/backstage/blob/master/packages/backend-plugin-api/CHANGELOG.md) changelogs. + +### New package: `@backstage/eslint-plugin` + +We created a separate ESlint plugin package that houses some rules that are helpful for Backstage monorepos. Not only does it make a convenient bundle of them all, it also comes with a pretty healthy speed boost. [The pull request](https://github.com/backstage/backstage/pull/16174) contains some more details. + +### New plugin: Entity Feedback + +A plugin that allows users to rate the quality of entities in your Backstage catalog. Allowing your users to rate entities brings them into the feedback loop that can help notify owners if something is wrong with their entity (i.e. taking inspiration from the feedback model of TechDocs). Check out [the README](https://github.com/backstage/backstage/tree/master/plugins/entity-feedback)! + +Contributed by [@kuangp](https://github.com/kuangp) in [#15881](https://github.com/backstage/backstage/pull/15881) + +### New plugin: Entity Validator + +This plugin helps users create and edit their YAML definitions of entities, with live validation. It leverages the actual catalog backend for checks, so that you can submit catalog info file changes that fit your particular organization with greater confidence. Installation instructions and details are in [the README](https://github.com/backstage/backstage/tree/master/plugins/entity-validation). + +Contributed by [@ivangonzalezacuna](https://github.com/ivangonzalezacuna) in [#16050](https://github.com/backstage/backstage/pull/16050) + +### New Plugin: Microsoft Calendar + +This plugin lets you show your MS calendars directly in Backstage. More information and installation instructions in [the README](https://github.com/backstage/backstage/tree/master/plugins/microsoft-calendar)! + +Contributed by [@Abhay-soni-developer](https://github.com/Abhay-soni-developer) in [#16101](https://github.com/backstage/backstage/pull/16101) + +### New plugin: GraphQL Voyager + +This nifty plugin presents a graph structure of your entire GraphQL API. Check out [its README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager) for a screenshot and instructions on installing it. + +Contributed by [@MitchWijt](https://github.com/MitchWijt) in [#16015](https://github.com/backstage/backstage/pull/16015) + +### New plugin: Linguist + +This plugin lets you see a nice visual representation of the breakdown of languages that a component’s repository is using, similar to the repository information that e.g. GitHub presents. More about that [in the README](https://github.com/backstage/backstage/tree/master/plugins/linguist)! + +Contributed by [@ahhhndre](https://github.com/ahhhndre) in [#14718](https://github.com/backstage/backstage/pull/14718) + +### Lighthouse Backend + +The [Lighthouse plugin](https://github.com/backstage/backstage/tree/master/plugins/lighthouse) now has a [corresponding backend](https://github.com/backstage/backstage/tree/master/plugins/lighthouse-backend). This allows you to conveniently schedule audits from within Backstage. + +Note that as part of this, a `@backstage/plugin-lighthouse-common` package was also created, and types that were common to the frontend and backend were moved there. This means that if you were explicitly importing types from the frontend package, you may see compilation errors and need to add a dependency on the new common package and point your imports there instead. + +Contributed by [@dpfaffenbauer](https://github.com/dpfaffenbauer) in [#15846](https://github.com/backstage/backstage/pull/15846) + +## Security Fixes + +`@backstage/core-components`, `@backstage/catalog-model`, and `@backstage/plugin-catalog-backend`, have all had precautionary validation added, please upgrade to the latest versions of these packages. Special thanks to Philip Olausson ([Programmatic](https://www.programmatic.se/)) who found these issues as part of [Roadie's](https://roadie.io/) regular third-party pen testing. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) + +- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.11.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://mailchi.mp/spotify/backstage-community) if you want to be informed about what is happening in the world of Backstage. diff --git a/microsite/sidebars.json b/microsite/sidebars.json index b7e2068aca..adeb5a6609 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -1,6 +1,7 @@ { "releases": { "Release Notes": [ + "releases/v1.11.0", "releases/v1.10.0", "releases/v1.9.0", "releases/v1.8.0", From 3e8e40ae2c53ee72c30f38e8c9e521818ed61bd2 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 14 Feb 2023 16:54:34 +0100 Subject: [PATCH 159/417] chore: woops, wrong version Signed-off-by: blam --- docs/features/software-templates/testing-scaffolder-alpha.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md index d10c7e7a0f..2182a86976 100644 --- a/docs/features/software-templates/testing-scaffolder-alpha.md +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -33,7 +33,7 @@ There's also a lot of bug fixes, and other things, but these are the main ones t ## How do I test out the `alpha` version? -With the release of `v1.12.0` it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes as part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. +With the release of [`v1.11.0`](https://github.com/backstage/backstage/releases/tag/v1.11.0) it's now possible to run the `scaffolder/next` plugin and it be a drop in replacement for the current version that you use today. This means that you can start using the new code, and start testing it out. Once we have collected enough feedback, and squashed any bugs that might block us from releasing, it will be promoted from the `/alpha` exports and replace the existing code leading to breaking changes if you haven't already made these changes as part of this testing pilot. Those that have chosen to opt into this testing pilot means that once we promote it from the `/alpha` exports, you will need to update your code to point to the original exports from the `scaffolder` plugin, just like the code is today but with the [breaking changes](#breaking-changes) that you already made to your `Custom Field Extensions`. It's also worth calling out that if you do test this out, and find some issues or something not working out as expected, feel free to raise an issue in the [repo](https://github.com/backstage/backstage) or reach out to us on Discord! From 0c06ac1d03e770448c2d7401619a8220232a5117 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 16:11:21 +0000 Subject: [PATCH 160/417] chore(deps): update dependency esbuild to v0.17.8 Signed-off-by: Renovate Bot --- yarn.lock | 182 +++++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/yarn.lock b/yarn.lock index 76d79c7da4..96e391b60a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9234,9 +9234,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/android-arm64@npm:0.17.6" +"@esbuild/android-arm64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/android-arm64@npm:0.17.8" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -9255,9 +9255,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/android-arm@npm:0.17.6" +"@esbuild/android-arm@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/android-arm@npm:0.17.8" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -9269,9 +9269,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/android-x64@npm:0.17.6" +"@esbuild/android-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/android-x64@npm:0.17.8" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -9283,9 +9283,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/darwin-arm64@npm:0.17.6" +"@esbuild/darwin-arm64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/darwin-arm64@npm:0.17.8" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -9297,9 +9297,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/darwin-x64@npm:0.17.6" +"@esbuild/darwin-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/darwin-x64@npm:0.17.8" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -9311,9 +9311,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/freebsd-arm64@npm:0.17.6" +"@esbuild/freebsd-arm64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/freebsd-arm64@npm:0.17.8" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -9325,9 +9325,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/freebsd-x64@npm:0.17.6" +"@esbuild/freebsd-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/freebsd-x64@npm:0.17.8" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -9339,9 +9339,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-arm64@npm:0.17.6" +"@esbuild/linux-arm64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-arm64@npm:0.17.8" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -9353,9 +9353,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-arm@npm:0.17.6" +"@esbuild/linux-arm@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-arm@npm:0.17.8" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -9367,9 +9367,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-ia32@npm:0.17.6" +"@esbuild/linux-ia32@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-ia32@npm:0.17.8" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -9388,9 +9388,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-loong64@npm:0.17.6" +"@esbuild/linux-loong64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-loong64@npm:0.17.8" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -9402,9 +9402,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-mips64el@npm:0.17.6" +"@esbuild/linux-mips64el@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-mips64el@npm:0.17.8" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -9416,9 +9416,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-ppc64@npm:0.17.6" +"@esbuild/linux-ppc64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-ppc64@npm:0.17.8" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -9430,9 +9430,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-riscv64@npm:0.17.6" +"@esbuild/linux-riscv64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-riscv64@npm:0.17.8" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -9444,9 +9444,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-s390x@npm:0.17.6" +"@esbuild/linux-s390x@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-s390x@npm:0.17.8" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -9458,9 +9458,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/linux-x64@npm:0.17.6" +"@esbuild/linux-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/linux-x64@npm:0.17.8" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -9472,9 +9472,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/netbsd-x64@npm:0.17.6" +"@esbuild/netbsd-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/netbsd-x64@npm:0.17.8" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -9486,9 +9486,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/openbsd-x64@npm:0.17.6" +"@esbuild/openbsd-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/openbsd-x64@npm:0.17.8" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -9500,9 +9500,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/sunos-x64@npm:0.17.6" +"@esbuild/sunos-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/sunos-x64@npm:0.17.8" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -9514,9 +9514,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/win32-arm64@npm:0.17.6" +"@esbuild/win32-arm64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/win32-arm64@npm:0.17.8" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -9528,9 +9528,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/win32-ia32@npm:0.17.6" +"@esbuild/win32-ia32@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/win32-ia32@npm:0.17.8" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -9542,9 +9542,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.17.6": - version: 0.17.6 - resolution: "@esbuild/win32-x64@npm:0.17.6" +"@esbuild/win32-x64@npm:0.17.8": + version: 0.17.8 + resolution: "@esbuild/win32-x64@npm:0.17.8" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -21620,31 +21620,31 @@ __metadata: linkType: hard "esbuild@npm:^0.17.0": - version: 0.17.6 - resolution: "esbuild@npm:0.17.6" + version: 0.17.8 + resolution: "esbuild@npm:0.17.8" dependencies: - "@esbuild/android-arm": 0.17.6 - "@esbuild/android-arm64": 0.17.6 - "@esbuild/android-x64": 0.17.6 - "@esbuild/darwin-arm64": 0.17.6 - "@esbuild/darwin-x64": 0.17.6 - "@esbuild/freebsd-arm64": 0.17.6 - "@esbuild/freebsd-x64": 0.17.6 - "@esbuild/linux-arm": 0.17.6 - "@esbuild/linux-arm64": 0.17.6 - "@esbuild/linux-ia32": 0.17.6 - "@esbuild/linux-loong64": 0.17.6 - "@esbuild/linux-mips64el": 0.17.6 - "@esbuild/linux-ppc64": 0.17.6 - "@esbuild/linux-riscv64": 0.17.6 - "@esbuild/linux-s390x": 0.17.6 - "@esbuild/linux-x64": 0.17.6 - "@esbuild/netbsd-x64": 0.17.6 - "@esbuild/openbsd-x64": 0.17.6 - "@esbuild/sunos-x64": 0.17.6 - "@esbuild/win32-arm64": 0.17.6 - "@esbuild/win32-ia32": 0.17.6 - "@esbuild/win32-x64": 0.17.6 + "@esbuild/android-arm": 0.17.8 + "@esbuild/android-arm64": 0.17.8 + "@esbuild/android-x64": 0.17.8 + "@esbuild/darwin-arm64": 0.17.8 + "@esbuild/darwin-x64": 0.17.8 + "@esbuild/freebsd-arm64": 0.17.8 + "@esbuild/freebsd-x64": 0.17.8 + "@esbuild/linux-arm": 0.17.8 + "@esbuild/linux-arm64": 0.17.8 + "@esbuild/linux-ia32": 0.17.8 + "@esbuild/linux-loong64": 0.17.8 + "@esbuild/linux-mips64el": 0.17.8 + "@esbuild/linux-ppc64": 0.17.8 + "@esbuild/linux-riscv64": 0.17.8 + "@esbuild/linux-s390x": 0.17.8 + "@esbuild/linux-x64": 0.17.8 + "@esbuild/netbsd-x64": 0.17.8 + "@esbuild/openbsd-x64": 0.17.8 + "@esbuild/sunos-x64": 0.17.8 + "@esbuild/win32-arm64": 0.17.8 + "@esbuild/win32-ia32": 0.17.8 + "@esbuild/win32-x64": 0.17.8 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -21692,7 +21692,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 13c4c3bcaa7ff291810d2c8294a1eb997b4672c60a9285b32d8eafcbc552e4468e06efe9d1a15067f5cbd41adcb12ddb4362618845e2e916e437f281c9aa80ab + checksum: d09776fcf3da2726975d0d3c11afe0a1db2a8fbb88cbcb25d97f269a1e58f17fa04cb881b9189195d8e76b8a1cfb165e990e27527ae0366f6dc2721fb0ed0af9 languageName: node linkType: hard From 34f90e6b3079a81720209d8fed4e9c93fb890884 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 14 Feb 2023 17:32:38 +0100 Subject: [PATCH 161/417] chore: fixing release notes and removing link from todo Signed-off-by: blam --- docs/releases/v1.11.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases/v1.11.0.md b/docs/releases/v1.11.0.md index da33e65ff0..e385bfead5 100644 --- a/docs/releases/v1.11.0.md +++ b/docs/releases/v1.11.0.md @@ -20,7 +20,7 @@ We’d love to hear if you have any issues when testing the new version, please The [new Backend System](https://backstage.io/docs/backend-system/) is now in alpha. We encourage plugin owners to try out the new system by adding support for it in their plugin backends, but we do not yet recommend migrating over to using this new system for production backend deployments. -This new system aims to greatly simplify the setup and wiring of Backstage backends. It formalizes and simplifies how common services and plugins are installed and interact with each other, and restructures both plugins and backends to make them much easier to maintain. To read more about this new system and how it came about, check out our [blog post](#TODO) on the topic. +This new system aims to greatly simplify the setup and wiring of Backstage backends. It formalizes and simplifies how common services and plugins are installed and interact with each other, and restructures both plugins and backends to make them much easier to maintain. The documentation starts [here](https://backstage.io/docs/backend-system/). Migration guides exist to help you get your [backend](https://backstage.io/docs/backend-system/building-backends/migrating) and [plugins](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating) migrated, but you don’t have to do it all in one go - the path forward can be incremental. From 3e3eea4bc7ee74f09b20733927bd781671e10a5b Mon Sep 17 00:00:00 2001 From: Dan Hoizner Date: Tue, 14 Feb 2023 15:48:47 -0500 Subject: [PATCH 162/417] feat(proxy-backend): configure request body revival for all targets Signed-off-by: Dan Hoizner --- .changeset/shaggy-lies-know.md | 14 ---- .changeset/ten-tigers-marry.md | 16 ++++ plugins/proxy-backend/api-report.md | 3 + plugins/proxy-backend/config.d.ts | 5 -- plugins/proxy-backend/src/plugin.ts | 6 +- .../proxy-backend/src/service/router.test.ts | 84 ++++++++++++++----- plugins/proxy-backend/src/service/router.ts | 12 ++- 7 files changed, 96 insertions(+), 44 deletions(-) delete mode 100644 .changeset/shaggy-lies-know.md create mode 100644 .changeset/ten-tigers-marry.md diff --git a/.changeset/shaggy-lies-know.md b/.changeset/shaggy-lies-know.md deleted file mode 100644 index cc016ed226..0000000000 --- a/.changeset/shaggy-lies-know.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@backstage/plugin-proxy-backend': minor ---- - -The proxy-backend plugin now supports reviving request bodies that have previously been consumed by an express middleware (e.g. `express.json()`). This is done by setting `reviveRequestBody: true` on the proxy configuration. In order to preserve the current behavior, the proxy will **not** revive request bodies by default. - -The following is an example of a proxy configuration that revives request bodies: - -```diff -proxy: - '/target': - target: 'http://proxy-route' -+ reviveRequestBody: true -``` diff --git a/.changeset/ten-tigers-marry.md b/.changeset/ten-tigers-marry.md new file mode 100644 index 0000000000..f90f7b3ea2 --- /dev/null +++ b/.changeset/ten-tigers-marry.md @@ -0,0 +1,16 @@ +--- +'@backstage/plugin-proxy-backend': patch +--- + +The proxy-backend plugin now supports reviving request bodies that have previously been consumed by an express middleware (e.g. `express.json()`). This is done by setting `reviveConsumedRequestBodies: true` on the proxy `RouterOptions`. In order to preserve the current behavior, the proxy will **not** revive request bodies by default. + +The following is an example of a proxy `createRouter` invocation that revives request bodies: + +```diff +const router = await createRouter({ + config, + logger, + discovery, ++ reviveConsumedRequestBodies: true, +}); +``` diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index 741f7c3b54..12d799bdf7 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-backend/api-report.md @@ -17,6 +17,7 @@ export const proxyPlugin: ( options?: | { skipInvalidProxies?: boolean | undefined; + reviveConsumedRequestBodies?: boolean | undefined; } | undefined, ) => BackendFeature; @@ -30,6 +31,8 @@ export interface RouterOptions { // (undocumented) logger: Logger; // (undocumented) + reviveConsumedRequestBodies?: boolean; + // (undocumented) skipInvalidProxies?: boolean; } ``` diff --git a/plugins/proxy-backend/config.d.ts b/plugins/proxy-backend/config.d.ts index d248845df1..59fc0dc5a6 100644 --- a/plugins/proxy-backend/config.d.ts +++ b/plugins/proxy-backend/config.d.ts @@ -50,11 +50,6 @@ export interface Config { * and headers that are set by the proxy will be forwarded. */ allowedHeaders?: string[]; - /** - * Revive request body if it was consumed by a middleware before reaching the proxy. By default, the request - * body is not revived. - */ - reviveRequestBody?: boolean; }; }; } diff --git a/plugins/proxy-backend/src/plugin.ts b/plugins/proxy-backend/src/plugin.ts index d095bee527..66eeb4a7b2 100644 --- a/plugins/proxy-backend/src/plugin.ts +++ b/plugins/proxy-backend/src/plugin.ts @@ -27,7 +27,10 @@ import { createRouter } from './service/router'; * @alpha */ export const proxyPlugin = createBackendPlugin( - (options?: { skipInvalidProxies?: boolean }) => ({ + (options?: { + skipInvalidProxies?: boolean; + reviveConsumedRequestBodies?: boolean; + }) => ({ pluginId: 'proxy', register(env) { env.registerInit({ @@ -44,6 +47,7 @@ export const proxyPlugin = createBackendPlugin( discovery, logger: loggerToWinstonLogger(logger), skipInvalidProxies: options?.skipInvalidProxies, + reviveConsumedRequestBodies: options?.reviveConsumedRequestBodies, }), ); }, diff --git a/plugins/proxy-backend/src/service/router.test.ts b/plugins/proxy-backend/src/service/router.test.ts index aa51fe5a08..9e8c909d25 100644 --- a/plugins/proxy-backend/src/service/router.test.ts +++ b/plugins/proxy-backend/src/service/router.test.ts @@ -36,25 +36,30 @@ const mockCreateProxyMiddleware = createProxyMiddleware as jest.MockedFunction< describe('createRouter', () => { describe('where all proxy config are valid', () => { + const logger = getVoidLogger(); + const config = new ConfigReader({ + backend: { + baseUrl: 'https://example.com:7007', + listen: { + port: 7007, + }, + }, + proxy: { + '/test': { + target: 'https://example.com', + headers: { + Authorization: 'Bearer supersecret', + }, + }, + }, + }); + const discovery = SingleHostDiscovery.fromConfig(config); + + beforeEach(() => { + mockCreateProxyMiddleware.mockClear(); + }); + it('works', async () => { - const logger = getVoidLogger(); - const config = new ConfigReader({ - backend: { - baseUrl: 'https://example.com:7007', - listen: { - port: 7007, - }, - }, - proxy: { - '/test': { - target: 'https://example.com', - headers: { - Authorization: 'Bearer supersecret', - }, - }, - }, - }); - const discovery = SingleHostDiscovery.fromConfig(config); const router = await createRouter({ config, logger, @@ -62,6 +67,36 @@ describe('createRouter', () => { }); expect(router).toBeDefined(); }); + + it('revives request bodies when set', async () => { + const router = await createRouter({ + config, + logger, + discovery, + reviveConsumedRequestBodies: true, + }); + expect(router).toBeDefined(); + + expect( + mockCreateProxyMiddleware.mock.calls[0][1]?.onProxyReq, + ).toBeDefined(); + expect(mockCreateProxyMiddleware.mock.calls[0][1]?.onProxyReq).toEqual( + fixRequestBody, + ); + }); + + it('does not revive request bodies when not set', async () => { + const router = await createRouter({ + config, + logger, + discovery, + }); + expect(router).toBeDefined(); + + expect( + mockCreateProxyMiddleware.mock.calls[0][1]?.onProxyReq, + ).not.toBeDefined(); + }); }); describe('where buildMiddleware would fail', () => { @@ -395,10 +430,15 @@ describe('buildMiddleware', () => { }); it('revives request body when configured', async () => { - buildMiddleware('/proxy', logger, '/test', { - target: 'http://mocked', - reviveRequestBody: true, - }); + buildMiddleware( + '/proxy', + logger, + '/test', + { + target: 'http://mocked', + }, + true, + ); expect(createProxyMiddleware).toHaveBeenCalledTimes(1); diff --git a/plugins/proxy-backend/src/service/router.ts b/plugins/proxy-backend/src/service/router.ts index 1f66bc7f6b..b669e82f3f 100644 --- a/plugins/proxy-backend/src/service/router.ts +++ b/plugins/proxy-backend/src/service/router.ts @@ -54,6 +54,7 @@ export interface RouterOptions { config: Config; discovery: PluginEndpointDiscovery; skipInvalidProxies?: boolean; + reviveConsumedRequestBodies?: boolean; } export interface ProxyConfig extends Options { @@ -69,6 +70,7 @@ export function buildMiddleware( logger: Logger, route: string, config: string | ProxyConfig, + reviveConsumedRequestBodies?: boolean, ): RequestHandler { const fullConfig = typeof config === 'string' ? { target: config } : { ...config }; @@ -177,7 +179,7 @@ export function buildMiddleware( }); }; - if (fullConfig.reviveRequestBody) { + if (reviveConsumedRequestBodies) { fullConfig.onProxyReq = fixRequestBody; } @@ -248,7 +250,13 @@ function configureMiddlewares( try { router.use( route, - buildMiddleware(pathPrefix, options.logger, route, proxyRouteConfig), + buildMiddleware( + pathPrefix, + options.logger, + route, + proxyRouteConfig, + options.reviveConsumedRequestBodies, + ), ); } catch (e) { if (options.skipInvalidProxies) { From db485e20618a2273caa1828cb8b4ac2ea1a5e372 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Tue, 24 Jan 2023 23:53:15 -0500 Subject: [PATCH 163/417] feat: Add Community page & Docusaurus 2 config Signed-off-by: Carlos Esteban Lopez --- microsite-next/docusaurus.config.js | 273 ++++++++--------- microsite-next/package.json | 9 +- .../src/pages/community.module.scss | 81 +++++ microsite-next/src/pages/community.tsx | 281 ++++++++++++++++++ microsite-next/tsconfig.json | 6 + microsite-next/typings.d.ts | 1 + microsite-next/yarn.lock | 103 ++++++- 7 files changed, 612 insertions(+), 142 deletions(-) create mode 100644 microsite-next/src/pages/community.module.scss create mode 100644 microsite-next/src/pages/community.tsx create mode 100644 microsite-next/tsconfig.json create mode 100644 microsite-next/typings.d.ts diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index 2b37ae20b2..55d24ba678 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// @ts-check + +/** @type {import('@docusaurus/types').Config} */ module.exports = { title: 'Backstage Software Catalog and Developer Platform', tagline: 'An open platform for building developer portals', @@ -40,6 +44,7 @@ module.exports = { presets: [ [ '@docusaurus/preset-classic', + /** @type {import('@docusaurus/preset-classic').Options} */ { docs: { showLastUpdateAuthor: true, @@ -60,138 +65,140 @@ module.exports = { }, ], ], - plugins: [], - themeConfig: { - navbar: { - title: 'Backstage Software Catalog and Developer Platform', - items: [ - { - href: 'https://github.com/backstage/backstage', - label: 'GitHub', - position: 'left', - }, - { - to: 'docs/overview/what-is-backstage', - label: 'Docs', - position: 'left', - }, - { - to: '/plugins', - label: 'Plugins', - position: 'left', - }, - { - to: '/blog', - label: 'Blog', - position: 'left', - }, - { - to: 'docs/releases/v1.8.0', - label: 'Releases', - position: 'left', - }, - { - to: '/demos', - label: 'Demos', - position: 'left', - }, - { - to: '/community', - label: 'Community', - position: 'left', - }, - ], + plugins: ['docusaurus-plugin-sass'], + themeConfig: + /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ + { + navbar: { + title: 'Backstage Software Catalog and Developer Platform', + items: [ + { + href: 'https://github.com/backstage/backstage', + label: 'GitHub', + position: 'left', + }, + { + to: 'docs/overview/what-is-backstage', + label: 'Docs', + position: 'left', + }, + { + to: '/plugins', + label: 'Plugins', + position: 'left', + }, + { + to: '/blog', + label: 'Blog', + position: 'left', + }, + { + to: 'docs/releases/v1.8.0', + label: 'Releases', + position: 'left', + }, + { + to: '/demos', + label: 'Demos', + position: 'left', + }, + { + to: '/community', + label: 'Community', + position: 'left', + }, + ], + }, + image: 'img/sharing-opengraph.png', + footer: { + links: [ + { + items: [ + { + html: '', + }, + ], + }, + { + title: 'Docs', + items: [ + { + label: 'What is Backstage?', + to: 'docs/overview/what-is-backstage', + }, + { + label: 'Getting started', + to: 'docs/getting-started/', + }, + { + label: 'Software Catalog', + to: 'docs/features/software-catalog/software-catalog-overview', + }, + { + label: 'Create a Plugin', + to: 'docs/plugins/create-a-plugin', + }, + { + label: 'Designing for Backstage', + to: 'docs/dls/design', + }, + ], + }, + { + title: 'Community', + items: [ + { + label: 'Support chatroom', + to: 'https://discord.gg/MUpMjP2', + }, + { + label: 'Contributing', + to: 'https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md', + }, + { + label: 'Adopting', + to: 'https://backstage.spotify.com', + }, + { + label: 'Subscribe to our newsletter', + to: 'https://mailchi.mp/spotify/backstage-community', + }, + { + label: 'CNCF Incubation', + to: 'https://www.cncf.io/projects/', + }, + ], + }, + { + title: 'More', + items: [ + { + label: 'Open Source @ Spotify', + to: 'https://spotify.github.io/', + }, + { + label: 'Spotify Engineering Blog', + to: 'https://engineering.atspotify.com/', + }, + { + label: 'Spotify for Developers', + to: 'https://developer.spotify.com/', + }, + { + label: 'Github', + to: 'https://github.com/backstage/', + }, + ], + }, + ], + copyright: + '

    Made with ❤️ at Spotify

    ', + }, + algolia: { + appId: 'AZYC4ZFNTN', + apiKey: '7dbd2089b0d445ee0d87db71abfc794f', + indexName: 'backstage', + searchParameters: {}, + }, }, - image: 'img/sharing-opengraph.png', - footer: { - links: [ - { - items: [ - { - html: '', - }, - ], - }, - { - title: 'Docs', - items: [ - { - label: 'What is Backstage?', - to: 'docs/overview/what-is-backstage', - }, - { - label: 'Getting started', - to: 'docs/getting-started/', - }, - { - label: 'Software Catalog', - to: 'docs/features/software-catalog/software-catalog-overview', - }, - { - label: 'Create a Plugin', - to: 'docs/plugins/create-a-plugin', - }, - { - label: 'Designing for Backstage', - to: 'docs/dls/design', - }, - ], - }, - { - title: 'Community', - items: [ - { - label: 'Support chatroom', - to: 'https://discord.gg/MUpMjP2', - }, - { - label: 'Contributing', - to: 'https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md', - }, - { - label: 'Adopting', - to: 'https://backstage.spotify.com', - }, - { - label: 'Subscribe to our newsletter', - to: 'https://mailchi.mp/spotify/backstage-community', - }, - { - label: 'CNCF Incubation', - to: 'https://www.cncf.io/projects/', - }, - ], - }, - { - title: 'More', - items: [ - { - label: 'Open Source @ Spotify', - to: 'https://spotify.github.io/', - }, - { - label: 'Spotify Engineering Blog', - to: 'https://engineering.atspotify.com/', - }, - { - label: 'Spotify for Developers', - to: 'https://developer.spotify.com/', - }, - { - label: 'Github', - to: 'https://github.com/backstage/', - }, - ], - }, - ], - copyright: - '

    Made with ❤️ at Spotify

    ', - }, - algolia: { - appId: 'AZYC4ZFNTN', - apiKey: '7dbd2089b0d445ee0d87db71abfc794f', - indexName: 'backstage', - searchParameters: {}, - }, - }, }; diff --git a/microsite-next/package.json b/microsite-next/package.json index 478fce0196..fa33da8306 100644 --- a/microsite-next/package.json +++ b/microsite-next/package.json @@ -17,17 +17,22 @@ "docusaurus": "docusaurus" }, "devDependencies": { + "@docusaurus/module-type-aliases": "^2.2.0", "@spotify/prettier-config": "^14.0.0", + "@tsconfig/docusaurus": "^1.0.6", "js-yaml": "^4.1.0", "prettier": "^2.6.2", - "replace": "^1.2.2" + "replace": "^1.2.2", + "typescript": "^4.9.4" }, "prettier": "@spotify/prettier-config", "dependencies": { "@docusaurus/core": "2.2.0", "@docusaurus/preset-classic": "2.2.0", "clsx": "^1.1.1", + "docusaurus-plugin-sass": "^0.2.3", "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "sass": "^1.57.1" } } diff --git a/microsite-next/src/pages/community.module.scss b/microsite-next/src/pages/community.module.scss new file mode 100644 index 0000000000..4fadb9bf55 --- /dev/null +++ b/microsite-next/src/pages/community.module.scss @@ -0,0 +1,81 @@ +.communityPage { + // --ifm-spacing-horizontal: 2rem; + + font-size: 1.25rem; + + h1 { + font-size: 54px; + line-height: 56px; + word-break: break-word; + } +} + +.banner, +.officialInitiatives, +.communityInitiatives, +.trainingNCertifications, +.commercialPartners { + :global(.row .col) { + max-width: 50%; + + display: flex; + flex-direction: column; + + :global(.bulletLine) { + width: 50px; + height: 3px; + background: linear-gradient( + 89.75deg, + #9bf0e1 -1.5%, + rgba(155, 240, 225, 0) 111.48% + ); + } + + p { + flex: 1; + } + } +} + +.banner, +.communityInitiatives, +.commercialPartners { + background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%); + // clip-path: polygon(0 0, 100% 0, 100% calc(100% - 2vw - 10px), 0 100%); +} + +.banner { + ul { + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + } +} + +.officialInitiatives { + background: linear-gradient( + 178.64deg, + hsla(0, 0%, 100%, 0) 57.61%, + hsla(0, 0%, 100%, 0.17) 127.71% + ), + linear-gradient( + 144.35deg, + rgba(98, 197, 179, 0) 56.68%, + rgba(98, 197, 179, 0.59) 109.25% + ), + linear-gradient( + 192.29deg, + rgba(155, 240, 225, 0) 54.17%, + rgba(155, 240, 225, 0.67) 137.34% + ); +} + +.communityInitiatives { +} + +.trainingNCertifications { +} + +.partners { +} diff --git a/microsite-next/src/pages/community.tsx b/microsite-next/src/pages/community.tsx new file mode 100644 index 0000000000..40868f6c72 --- /dev/null +++ b/microsite-next/src/pages/community.tsx @@ -0,0 +1,281 @@ +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Layout from '@theme/Layout'; +import { clsx } from 'clsx'; +import React from 'react'; + +import communityStyles from './community.module.scss'; + +interface ICollectionItem { + title?: string; + content: React.ReactNode; + label: string; + link: string; +} + +export default function Community() { + const { siteConfig } = useDocusaurusContext(); + + const communityListItems: ICollectionItem[] = [ + { + content: 'Chat and get support on our', + label: 'Discord', + link: 'https://discord.gg/MUpMjP2', + }, + { + content: 'Get into contributing with the', + label: 'Good First Issues', + link: 'https://github.com/backstage/backstage/contribute', + }, + { + content: 'Subscribe to the', + label: 'Community newsletter', + link: 'https://info.backstage.spotify.com/newsletter_subscribe', + }, + { + content: 'Join the', + label: 'Twitter community', + link: 'https://twitter.com/i/communities/1494019781716062215', + }, + ]; + + const officialInitiatives: ICollectionItem[] = [ + { + title: 'Community sessions', + content: + 'Maintainers and adopters meet monthly to share updates, demos, and ideas. Yep, all sessions are recorded!', + link: '/on-demand', + label: 'Join a session', + }, + { + title: 'Newsletter', + content: + "The official monthly Backstage newsletter. Don't miss the latest news from your favorite project!", + link: 'https://info.backstage.spotify.com/newsletter_subscribe', + label: 'Subscribe', + }, + { + title: 'Contributor Spotlight', + content: + "A recognition for valuable community work. Nominate contributing members for their efforts! We'll put them in the spotlight ❤️", + link: '/nominate', + label: 'Nominate now', + }, + ]; + + const communityInitiatives: ICollectionItem[] = [ + { + title: 'Open Mic Meetup', + content: ( + <> + A casual get together of Backstage users sharing their experiences and + helping each other. Hosted by{' '} + Roadie.io and{' '} + Frontside Software. + + ), + link: 'https://backstage-openmic.com/', + label: 'Learn more', + }, + { + title: 'Backstage Weekly Newsletter', + content: ( + <> + A weekly newsletter with news, updates and things community from your + friends at Roadie.io. + + ), + link: 'https://roadie.io/backstage-weekly/', + label: 'Learn more', + }, + ]; + + const trainingNCertifications: ICollectionItem[] = [ + { + title: 'Open Mic Meetup', + content: + 'This is a course produced and curated by the Linux Foundation. This course introduces you to Backstage and how to get started with the project.', + link: 'https://training.linuxfoundation.org/training/introduction-to-backstage-developer-portals-made-easy-lfs142x/', + label: 'Learn more', + }, + ]; + + const partners: { name: string; url: string; logo: string }[] = [ + { + name: 'Frontside Software', + url: 'https://frontside.com/backstage/', + logo: 'img/partner-logo-frontside.png', + }, + { + name: 'Roadie', + url: 'https://roadie.io/', + logo: 'img/partner-logo-roadie.png', + }, + { + name: 'ThoughtWorks', + url: 'https://www.thoughtworks.com', + logo: 'img/partner-logo-thoughtworks.png', + }, + { + name: 'VMWare', + url: 'https://www.vmware.com', + logo: 'img/partner-logo-vmware.png', + }, + ]; + + return ( + +
    +
    +
    +
    +
    +

    + Backstage Community +

    + +

    + Join the vibrant community around Backstage through social + media and different meetups. To ensure that you have a + welcoming environment, we follow the + + {' '} + CNCF Code of Conduct{' '} + + in everything we do. +

    +
    + +
    +

    + Get started in our community! +

    + +
      + {communityListItems.map( + ({ content: text, link, label }, index) => ( +
    • +

      + {text} {label} +

      +
    • + ), + )} +
    +
    +
    +
    +
    + +
    +
    +
    +

    Offical Backstage initiatives

    + +

    Stay tuned to the latest developments

    +
    + +
    + {officialInitiatives.map( + ({ title, content, link, label }, index) => ( +
    +
    + +

    {title}

    + +

    {content}

    + + + {label} + +
    + ), + )} +
    +
    +
    + +
    +
    +
    +

    Community initiatives

    +
    + +
    + {communityInitiatives.map( + ({ title, content, link, label }, index) => ( +
    +
    + +

    {title}

    + +

    {content}

    + + + {label} + +
    + ), + )} +
    +
    +
    + +
    +
    +
    +

    Trainings and Certifications

    +
    + +
    + {trainingNCertifications.map( + ({ title, content, link, label }, index) => ( +
    +
    + +

    {title}

    + +

    {content}

    + + + {label} + +
    + ), + )} +
    +
    +
    + +
    +
    +
    +

    Commercial Partners

    +
    + +
    + {partners.map(({ name, url, logo }, index) => ( +
    + + {name} + +
    + ))} +
    +
    +
    +
    +
    + ); +} diff --git a/microsite-next/tsconfig.json b/microsite-next/tsconfig.json new file mode 100644 index 0000000000..57bbce401d --- /dev/null +++ b/microsite-next/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@tsconfig/docusaurus/tsconfig.json", + "compilerOptions": { + "baseUrl": "." + } +} diff --git a/microsite-next/typings.d.ts b/microsite-next/typings.d.ts new file mode 100644 index 0000000000..d5cf927a7c --- /dev/null +++ b/microsite-next/typings.d.ts @@ -0,0 +1 @@ +declare module '*.scss'; diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 251ae303c0..6091c6683c 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -1794,7 +1794,7 @@ __metadata: languageName: node linkType: hard -"@docusaurus/module-type-aliases@npm:2.2.0": +"@docusaurus/module-type-aliases@npm:2.2.0, @docusaurus/module-type-aliases@npm:^2.2.0": version: 2.2.0 resolution: "@docusaurus/module-type-aliases@npm:2.2.0" dependencies: @@ -2608,6 +2608,13 @@ __metadata: languageName: node linkType: hard +"@tsconfig/docusaurus@npm:^1.0.6": + version: 1.0.6 + resolution: "@tsconfig/docusaurus@npm:1.0.6" + checksum: fb0d7965c01fe64fc6369a72695b903d654bd5fb145f373d707c2bae3c2d828703517d812cef1c041ae44b108f44e52778b9d9837a54fdf782e68e6619a90a4d + languageName: node + linkType: hard + "@types/body-parser@npm:*": version: 1.19.2 resolution: "@types/body-parser@npm:1.19.2" @@ -3566,14 +3573,19 @@ __metadata: resolution: "backstage-microsite@workspace:." dependencies: "@docusaurus/core": 2.2.0 + "@docusaurus/module-type-aliases": ^2.2.0 "@docusaurus/preset-classic": 2.2.0 "@spotify/prettier-config": ^14.0.0 + "@tsconfig/docusaurus": ^1.0.6 clsx: ^1.1.1 + docusaurus-plugin-sass: ^0.2.3 js-yaml: ^4.1.0 prettier: ^2.6.2 react: ^17.0.2 react-dom: ^17.0.2 replace: ^1.2.2 + sass: ^1.57.1 + typescript: ^4.9.4 languageName: unknown linkType: soft @@ -3939,7 +3951,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.4.2, chokidar@npm:^3.5.3": +"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.4.2, chokidar@npm:^3.5.3": version: 3.5.3 resolution: "chokidar@npm:3.5.3" dependencies: @@ -4790,6 +4802,18 @@ __metadata: languageName: node linkType: hard +"docusaurus-plugin-sass@npm:^0.2.3": + version: 0.2.3 + resolution: "docusaurus-plugin-sass@npm:0.2.3" + dependencies: + sass-loader: ^10.1.1 + peerDependencies: + "@docusaurus/core": ^2.0.0-beta + sass: ^1.30.0 + checksum: 928b02fd7c63835d54cdcce2eeda01cb6124707c6d43ef8e77db06474d3e3b4b7282cc0d88fed378cf1f3db2fc93ba8c11366965bb9b668eae19ca805e578acb + languageName: node + linkType: hard + "dom-converter@npm:^0.2.0": version: 0.2.0 resolution: "dom-converter@npm:0.2.0" @@ -6214,6 +6238,13 @@ __metadata: languageName: node linkType: hard +"immutable@npm:^4.0.0": + version: 4.2.2 + resolution: "immutable@npm:4.2.2" + checksum: 4d6437ea9388fe8ceca7eed5c768cf438cda7fa14d2831b87b90aa00cc60d536964d107c255b8a2e5dbf4f44a0e1295afbb9d1f0a65fb4f57b936e71df601862 + languageName: node + linkType: hard + "import-fresh@npm:^3.1.0, import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" @@ -6793,10 +6824,10 @@ __metadata: languageName: node linkType: hard -"klona@npm:^2.0.5": - version: 2.0.5 - resolution: "klona@npm:2.0.5" - checksum: 8c976126ea252b766e648a4866e1bccff9d3b08432474ad80c559f6c7265cf7caede2498d463754d8c88c4759895edd8210c85c0d3155e6aae4968362889466f +"klona@npm:^2.0.4, klona@npm:^2.0.5": + version: 2.0.6 + resolution: "klona@npm:2.0.6" + checksum: ac9ee3732e42b96feb67faae4d27cf49494e8a3bf3fa7115ce242fe04786788e0aff4741a07a45a2462e2079aa983d73d38519c85d65b70ef11447bbc3c58ce7 languageName: node linkType: hard @@ -9214,6 +9245,44 @@ __metadata: languageName: node linkType: hard +"sass-loader@npm:^10.1.1": + version: 10.4.1 + resolution: "sass-loader@npm:10.4.1" + dependencies: + klona: ^2.0.4 + loader-utils: ^2.0.0 + neo-async: ^2.6.2 + schema-utils: ^3.0.0 + semver: ^7.3.2 + peerDependencies: + fibers: ">= 3.1.0" + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + sass: ^1.3.0 + webpack: ^4.36.0 || ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + checksum: df9a65a62247e95305299ccbdf212cffdcdb69490928aecdf4f3dcf539b5302ed7cbffa663f83c5fc3ce0864decf84257a9ce484f6df4cb4426feeb88445dcd0 + languageName: node + linkType: hard + +"sass@npm:^1.57.1": + version: 1.57.1 + resolution: "sass@npm:1.57.1" + dependencies: + chokidar: ">=3.0.0 <4.0.0" + immutable: ^4.0.0 + source-map-js: ">=0.6.2 <2.0.0" + bin: + sass: sass.js + checksum: 734a08781bcbe0e8defb2d54864e7012014ed3e68ba5fcb766189b002929019fc37b2f83a18d4be0b5f69ad77317c92396ce6112447ab47a194ed600ae1afb27 + languageName: node + linkType: hard + "sax@npm:^1.2.4": version: 1.2.4 resolution: "sax@npm:1.2.4" @@ -9603,7 +9672,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.0.2": +"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.2": version: 1.0.2 resolution: "source-map-js@npm:1.0.2" checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c @@ -10092,6 +10161,26 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^4.9.4": + version: 4.9.4 + resolution: "typescript@npm:4.9.4" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: e782fb9e0031cb258a80000f6c13530288c6d63f1177ed43f770533fdc15740d271554cdae86701c1dd2c83b082cea808b07e97fd68b38a172a83dbf9e0d0ef9 + languageName: node + linkType: hard + +"typescript@patch:typescript@^4.9.4#~builtin": + version: 4.9.4 + resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=a1c5e5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 37f6e2c3c5e2aa5934b85b0fddbf32eeac8b1bacf3a5b51d01946936d03f5377fe86255d4e5a4ae628fd0cd553386355ad362c57f13b4635064400f3e8e05b9d + languageName: node + linkType: hard + "ua-parser-js@npm:^0.7.30": version: 0.7.33 resolution: "ua-parser-js@npm:0.7.33" From a3383f007974711f0e95d4e0779bfdfdbbdeeebc Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Sat, 28 Jan 2023 01:11:07 -0500 Subject: [PATCH 164/417] feat: Add plugins page with Webpack require.context & folder per page Signed-off-by: Carlos Esteban Lopez --- microsite-next/docusaurus.config.js | 18 +++- microsite-next/package.json | 4 +- microsite-next/src/css/customTheme.css | 15 +++- .../{ => community}/community.module.scss | 15 ---- .../src/pages/{ => community}/community.tsx | 10 ++- microsite-next/src/pages/community/index.tsx | 3 + microsite-next/src/pages/plugins/index.tsx | 3 + .../src/pages/plugins/plugin-card.tsx | 54 +++++++++++ .../src/pages/plugins/plugins.module.scss | 33 +++++++ microsite-next/src/pages/plugins/plugins.tsx | 90 +++++++++++++++++++ microsite-next/tsconfig.json | 8 +- microsite-next/yarn.lock | 34 +++++++ 12 files changed, 263 insertions(+), 24 deletions(-) rename microsite-next/src/pages/{ => community}/community.module.scss (84%) rename microsite-next/src/pages/{ => community}/community.tsx (97%) create mode 100644 microsite-next/src/pages/community/index.tsx create mode 100644 microsite-next/src/pages/plugins/index.tsx create mode 100644 microsite-next/src/pages/plugins/plugin-card.tsx create mode 100644 microsite-next/src/pages/plugins/plugins.module.scss create mode 100644 microsite-next/src/pages/plugins/plugins.tsx diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index 55d24ba678..28e74f3633 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -65,7 +65,23 @@ module.exports = { }, ], ], - plugins: ['docusaurus-plugin-sass'], + plugins: [ + 'docusaurus-plugin-sass', + () => ({ + configureWebpack() { + return { + module: { + rules: [ + { + test: /\.ya?ml$/, + use: 'yaml-loader', + }, + ], + }, + }; + }, + }), + ], themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ { diff --git a/microsite-next/package.json b/microsite-next/package.json index fa33da8306..01feee18dc 100644 --- a/microsite-next/package.json +++ b/microsite-next/package.json @@ -20,10 +20,12 @@ "@docusaurus/module-type-aliases": "^2.2.0", "@spotify/prettier-config": "^14.0.0", "@tsconfig/docusaurus": "^1.0.6", + "@types/webpack-env": "^1.18.0", "js-yaml": "^4.1.0", "prettier": "^2.6.2", "replace": "^1.2.2", - "typescript": "^4.9.4" + "typescript": "^4.9.4", + "yaml-loader": "^0.8.0" }, "prettier": "@spotify/prettier-config", "dependencies": { diff --git a/microsite-next/src/css/customTheme.css b/microsite-next/src/css/customTheme.css index 3b71d51d62..1a39467516 100644 --- a/microsite-next/src/css/customTheme.css +++ b/microsite-next/src/css/customTheme.css @@ -25,7 +25,7 @@ background-color: white; } -/* Utility API Styling */ +/* #region Utility API Styling */ .textGreen { color: #82b366; } @@ -44,4 +44,15 @@ .textAlignCenter { text-align: center; } -/* End of Utility API Styling */ +/* #endregion */ + +/* #region Utility component styles */ +.bulletLine { + height: 3px; + background: linear-gradient( + 89.75deg, + #9bf0e1 -1.5%, + rgba(155, 240, 225, 0) 111.48% + ); +} +/* #endregion */ diff --git a/microsite-next/src/pages/community.module.scss b/microsite-next/src/pages/community/community.module.scss similarity index 84% rename from microsite-next/src/pages/community.module.scss rename to microsite-next/src/pages/community/community.module.scss index 4fadb9bf55..87dcdf92d1 100644 --- a/microsite-next/src/pages/community.module.scss +++ b/microsite-next/src/pages/community/community.module.scss @@ -23,12 +23,6 @@ :global(.bulletLine) { width: 50px; - height: 3px; - background: linear-gradient( - 89.75deg, - #9bf0e1 -1.5%, - rgba(155, 240, 225, 0) 111.48% - ); } p { @@ -70,12 +64,3 @@ rgba(155, 240, 225, 0.67) 137.34% ); } - -.communityInitiatives { -} - -.trainingNCertifications { -} - -.partners { -} diff --git a/microsite-next/src/pages/community.tsx b/microsite-next/src/pages/community/community.tsx similarity index 97% rename from microsite-next/src/pages/community.tsx rename to microsite-next/src/pages/community/community.tsx index 40868f6c72..3ea0c36da9 100644 --- a/microsite-next/src/pages/community.tsx +++ b/microsite-next/src/pages/community/community.tsx @@ -13,9 +13,10 @@ interface ICollectionItem { link: string; } -export default function Community() { +export function Community() { const { siteConfig } = useDocusaurusContext(); + //#region Collection Data const communityListItems: ICollectionItem[] = [ { content: 'Chat and get support on our', @@ -122,6 +123,7 @@ export default function Community() { logo: 'img/partner-logo-vmware.png', }, ]; + //#endregion return ( @@ -140,10 +142,10 @@ export default function Community() { Join the vibrant community around Backstage through social media and different meetups. To ensure that you have a welcoming environment, we follow the - + {' '} CNCF Code of Conduct{' '} - + in everything we do.

  • @@ -158,7 +160,7 @@ export default function Community() { ({ content: text, link, label }, index) => (
  • - {text} {label} + {text} {label}

  • ), diff --git a/microsite-next/src/pages/community/index.tsx b/microsite-next/src/pages/community/index.tsx new file mode 100644 index 0000000000..5f3fd915db --- /dev/null +++ b/microsite-next/src/pages/community/index.tsx @@ -0,0 +1,3 @@ +import { Community } from './community'; + +export default Community; diff --git a/microsite-next/src/pages/plugins/index.tsx b/microsite-next/src/pages/plugins/index.tsx new file mode 100644 index 0000000000..9aec0c2586 --- /dev/null +++ b/microsite-next/src/pages/plugins/index.tsx @@ -0,0 +1,3 @@ +import { Plugins } from './plugins'; + +export default Plugins; diff --git a/microsite-next/src/pages/plugins/plugin-card.tsx b/microsite-next/src/pages/plugins/plugin-card.tsx new file mode 100644 index 0000000000..dec62af06f --- /dev/null +++ b/microsite-next/src/pages/plugins/plugin-card.tsx @@ -0,0 +1,54 @@ +import Link from '@docusaurus/Link'; +import React from 'react'; + +export interface IPluginData { + author: string; + authorUrl: string; + category: string; + description: string; + documentation: string; + iconUrl: string; + title: string; + order?: number; +} + +const defaultIconUrl = 'img/logo-gradient-on-dark.svg'; + +export const PluginCard = ({ + author, + authorUrl, + category, + description, + documentation, + iconUrl, + title, +}: IPluginData) => ( +
    +
    + {title} + +

    {title}

    + +

    + by {author} +

    + + + {category} + +
    + +
    +

    {description}

    +
    + +
    + + Explore + +
    +
    +); diff --git a/microsite-next/src/pages/plugins/plugins.module.scss b/microsite-next/src/pages/plugins/plugins.module.scss new file mode 100644 index 0000000000..d21444583a --- /dev/null +++ b/microsite-next/src/pages/plugins/plugins.module.scss @@ -0,0 +1,33 @@ +.pluginsPage { + :global(.marketplaceBanner) { + display: flex; + align-items: center; + } + + :global(.marketplaceContent) { + flex: 1; + } + + :global(.card .card__header) { + display: grid; + row-gap: 0.25rem; + column-gap: 1rem; + align-items: center; + grid-template-columns: auto 1fr; + + > * { + margin: 0; + } + + :global(img) { + width: 80px; + grid-row: 1/4; + } + } + + :global(.pluginsContainer) { + gap: 1rem; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + } +} diff --git a/microsite-next/src/pages/plugins/plugins.tsx b/microsite-next/src/pages/plugins/plugins.tsx new file mode 100644 index 0000000000..c904b57382 --- /dev/null +++ b/microsite-next/src/pages/plugins/plugins.tsx @@ -0,0 +1,90 @@ +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Layout from '@theme/Layout'; +import clsx from 'clsx'; +import React from 'react'; + +import { IPluginData, PluginCard } from './plugin-card'; +import pluginsStyles from './plugins.module.scss'; + +//#region Plugin data import +const maxDescLength = 160; + +const truncatePluginDescription = (pluginData: IPluginData) => + pluginData.description.length > maxDescLength + ? { + ...pluginData, + description: pluginData.description.slice(0, maxDescLength) + '...', + } + : pluginData; + +const pluginsContext = require.context( + '../../../../microsite/data/plugins', + false, + /\.ya?ml/, +); + +const plugins = pluginsContext.keys().reduce( + (acum, id) => { + const pluginData: IPluginData = pluginsContext(id).default; + + acum[ + pluginData.category === 'Core Feature' ? 'corePlugins' : 'otherPlugins' + ].push(truncatePluginDescription(pluginData)); + + return acum; + }, + { corePlugins: [] as IPluginData[], otherPlugins: [] as IPluginData[] }, +); + +plugins.corePlugins.sort((a, b) => a.order - b.order); +plugins.otherPlugins.sort((a, b) => a.order - b.order); +//#endregion + +export function Plugins() { + const { siteConfig } = useDocusaurusContext(); + + return ( + +
    +
    +
    +

    Plugin Marketplace

    + +

    + Open source plugins that you can add to your Backstage deployment. + Learn how to build a plugin. +

    +
    + + + Add to Marketplace + +
    + +
    + +

    Core Features

    + +
    + {plugins.corePlugins.map(pluginData => ( + + ))} +
    + +

    All Plugins

    + +
    + {plugins.otherPlugins.map(pluginData => ( + + ))} +
    +
    +
    + ); +} diff --git a/microsite-next/tsconfig.json b/microsite-next/tsconfig.json index 57bbce401d..ae8fe2298a 100644 --- a/microsite-next/tsconfig.json +++ b/microsite-next/tsconfig.json @@ -1,6 +1,12 @@ { "extends": "@tsconfig/docusaurus/tsconfig.json", "compilerOptions": { - "baseUrl": "." + "baseUrl": ".", + "types": [ + "node", + "@docusaurus/module-type-aliases", + "@docusaurus/theme-classic", + "@types/webpack-env" + ] } } diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 6091c6683c..8dc3fce883 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -2958,6 +2958,13 @@ __metadata: languageName: node linkType: hard +"@types/webpack-env@npm:^1.18.0": + version: 1.18.0 + resolution: "@types/webpack-env@npm:1.18.0" + checksum: ecf4daa31cb37d474ac0ce058d83a3cadeb9881ca8107ae93c2299eaa9954943aae09b43e143c62ccbe4288a14db00c918c9debd707afe17c3998f873eaabc59 + languageName: node + linkType: hard + "@types/ws@npm:^8.5.1": version: 8.5.3 resolution: "@types/ws@npm:8.5.3" @@ -3577,6 +3584,7 @@ __metadata: "@docusaurus/preset-classic": 2.2.0 "@spotify/prettier-config": ^14.0.0 "@tsconfig/docusaurus": ^1.0.6 + "@types/webpack-env": ^1.18.0 clsx: ^1.1.1 docusaurus-plugin-sass: ^0.2.3 js-yaml: ^4.1.0 @@ -3586,6 +3594,7 @@ __metadata: replace: ^1.2.2 sass: ^1.57.1 typescript: ^4.9.4 + yaml-loader: ^0.8.0 languageName: unknown linkType: soft @@ -6653,6 +6662,13 @@ __metadata: languageName: node linkType: hard +"javascript-stringify@npm:^2.0.1": + version: 2.1.0 + resolution: "javascript-stringify@npm:2.1.0" + checksum: 009981ec84299da88795fc764221ed213e3d52251cc93a396430a7a02ae09f1163a9be36a36808689681a8e6113cf00fe97ec2eea2552df48111f79be59e9358 + languageName: node + linkType: hard + "jest-util@npm:^29.3.1": version: 29.3.1 resolution: "jest-util@npm:29.3.1" @@ -10966,6 +10982,17 @@ __metadata: languageName: node linkType: hard +"yaml-loader@npm:^0.8.0": + version: 0.8.0 + resolution: "yaml-loader@npm:0.8.0" + dependencies: + javascript-stringify: ^2.0.1 + loader-utils: ^2.0.0 + yaml: ^2.0.0 + checksum: d12dd264666b80baec23cea9f81cb677a9102d6f34ab45d8b6c085ace4d05b7285db9ce317db57264c3317af01128ce6e5b754e6866d15ccd75e8141902fb529 + languageName: node + linkType: hard + "yaml@npm:^1.10.0, yaml@npm:^1.10.2, yaml@npm:^1.7.2": version: 1.10.2 resolution: "yaml@npm:1.10.2" @@ -10973,6 +11000,13 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.0.0": + version: 2.2.1 + resolution: "yaml@npm:2.2.1" + checksum: 84f68cbe462d5da4e7ded4a8bded949ffa912bc264472e5a684c3d45b22d8f73a3019963a32164023bdf3d83cfb6f5b58ff7b2b10ef5b717c630f40bd6369a23 + languageName: node + linkType: hard + "yargs-parser@npm:^18.1.2": version: 18.1.3 resolution: "yargs-parser@npm:18.1.3" From 4ce998cf8e785edb9b26891f91d53a75fe3ac282 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Thu, 2 Feb 2023 16:53:18 -0500 Subject: [PATCH 165/417] feat: Add demos page Signed-off-by: Carlos Esteban Lopez --- .../src/pages/demos/demos.module.scss | 28 +++ microsite-next/src/pages/demos/demos.tsx | 213 ++++++++++++++++++ microsite-next/src/pages/demos/index.tsx | 3 + 3 files changed, 244 insertions(+) create mode 100644 microsite-next/src/pages/demos/demos.module.scss create mode 100644 microsite-next/src/pages/demos/demos.tsx create mode 100644 microsite-next/src/pages/demos/index.tsx diff --git a/microsite-next/src/pages/demos/demos.module.scss b/microsite-next/src/pages/demos/demos.module.scss new file mode 100644 index 0000000000..0a567c45a7 --- /dev/null +++ b/microsite-next/src/pages/demos/demos.module.scss @@ -0,0 +1,28 @@ +.communityPage { + // --ifm-spacing-horizontal: 2rem; + + font-size: 1.25rem; + + h1 { + font-size: 54px; + line-height: 56px; + word-break: break-word; + } +} + +.banner { + p { + flex: 1; + text-align: justify; + } + + iframe { + width: 100%; + height: 100%; + min-height: 500px; + } +} + +.bannerGradient { + background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%); +} diff --git a/microsite-next/src/pages/demos/demos.tsx b/microsite-next/src/pages/demos/demos.tsx new file mode 100644 index 0000000000..4c035dd130 --- /dev/null +++ b/microsite-next/src/pages/demos/demos.tsx @@ -0,0 +1,213 @@ +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Layout from '@theme/Layout'; +import { clsx } from 'clsx'; +import React from 'react'; + +import demosStyles from './demos.module.scss'; + +interface IDemoItem { + title: string; + content: React.ReactNode; + actionItemLink?: string; + media: { + type: 'image' | 'video'; + link: string; + }; +} + +export function Demos() { + const { siteConfig } = useDocusaurusContext(); + + //#region Collection Data + const demoItems: IDemoItem[] = [ + { + title: 'See us in action', + content: ( + <> +

    + Watch the videos below to get an introduction to Backstage and to + see how we use different plugins to customize{' '} + + our internal version of Backstage at Spotify + +

    +

    + To see how other companies have already started using Backstage, + watch these presentations from{' '} + Expedia,{' '} + Zalando, and{' '} + TELUS. For + more, join our{' '} + + Community Sessions + +

    +

    + To explore the UI and basic features of Backstage firsthand, go to:{' '} + demo.backstage.io. (Tip:{' '} + click “All” to view all the example components in the software + catalog.) +

    + + ), + media: { + type: 'image', + link: `${siteConfig.baseUrl}img/demo-screen.png`, + }, + }, + { + title: 'Introduction to Backstage', + content: + 'Backstage is an open source platform for building developer portals. We’ve been using our homegrown version at Spotify for years — so it’s already packed with features. (We have over 120 internal plugins, built by 60 different teams.) In this live demo recording, Stefan Ålund, product manager for Backstage, tells the origin story of Backstage and gives you a tour of how we use it here at Spotify.', + actionItemLink: 'https://www.youtube.com/watch?v=1XtJ5FAOjPk', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/1XtJ5FAOjPk', + }, + }, + { + title: 'Control cloud costs', + content: ( + <> +

    + How do you control cloud costs while maintaining the speed and + independence of your development teams? With the{' '} + Cost Insights plugin{' '} + for Backstage, managing cloud costs becomes just another part of an + engineer’s daily development process. They get a clear view of their + spending — and can decide for themselves how they want to optimize + it. Learn more about the{' '} + + Cost Insights plugin + +

    + + ), + actionItemLink: 'https://youtu.be/YLAd5hdXR_Q', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/YLAd5hdXR_Q', + }, + }, + { + title: 'Make documentation easy', + content: ( + <> +

    + Documentation! Everyone needs it, no one wants to create it, and no + one can ever find it. Backstage follows a “docs like code” approach: + you write documentation in Markdown files right alongside your code. + This makes documentation easier to create, maintain, find — and, you + know, actually use. This demo video showcases Spotify’s internal + version of TechDocs. Learn more about{' '} + + TechDocs + + . +

    + + ), + actionItemLink: 'https://youtu.be/mOLCgdPw1iA', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/mOLCgdPw1iA', + }, + }, + { + title: 'Manage your tech health', + content: + 'Instead of manually updating a spreadsheet, what if you had a beautiful dashboard that could give you an instant, interactive picture of your entire org’s tech stack? That’s how we do it at Spotify. With our Tech Insights plugin for Backstage, anyone at Spotify can see which version of which software anyone else at Spotify is using — and a whole a lot more. From managing migrations to fighting tech entropy, Backstage makes managing our tech health actually kind of pleasant.', + actionItemLink: + 'https://www.youtube.com/watch?v=K3xz6VAbgH8&list=PLf1KFlSkDLIBtMGwRDfaVlKMqTMrjD2yO&index=6', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/K3xz6VAbgH8', + }, + }, + { + title: 'Create a microservice', + content: + 'You’re a Spotify engineer about to build a new microservice (or any component) using Spring Boot. Where do you start? Search for a quick start guide online? Create an empty repo on GitHub? Copy and paste an old project? Nope. Just go to Backstage, and you’ll be up and running in two minutes — with a “Hello World” app, CI, and documentation all automatically set up and configured in a standardized way.', + actionItemLink: 'https://www.youtube.com/watch?v=U1iwe3L5pzc', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/U1iwe3L5pzc', + }, + }, + { + title: 'Search all your services', + content: + 'All of Spotify’s services are automatically indexed in Backstage. So our engineers can stop playing detective — no more spamming Slack channels asking if anyone knows who owns a particular service and where you can find its API, only to discover that the owner went on sabbatical three months ago and you have to hunt them down on a mountain in Tibet where they’re on a 12-day silent meditation retreat. At Spotify, anyone can always find anyone else’s service, inspect its APIs, and contact its current owner — all with one search.', + actionItemLink: 'https://www.youtube.com/watch?v=vcDL9tOv7Eo', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/vcDL9tOv7Eo', + }, + }, + { + title: 'Manage data pipelines', + content: + 'We manage a lot of data pipelines (also known as workflows) here at Spotify. So, of course, we made a great workflows plugin for our version of Backstage. All our workflow tools — including a scheduler, log inspector, data lineage graph, and configurable alerts — are integrated into one simple interface.', + actionItemLink: 'https://www.youtube.com/watch?v=rH46MLNZIPM', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/rH46MLNZIPM', + }, + }, + ]; + //#endregion + + return ( + +
    + {demoItems.map((demoItem, index) => ( +
    +
    +
    +
    +

    + {demoItem.title} +

    + + {React.isValidElement(demoItem.content) ? ( + demoItem.content + ) : ( +

    {demoItem.content}

    + )} + + {demoItem.actionItemLink && ( + + WATCH NOW + + )} +
    + +
    + {demoItem.media.type === 'image' ? ( + {demoItem.title} + ) : ( + + )} +
    +
    +
    +
    + ))} +
    +
    + ); +} diff --git a/microsite-next/src/pages/demos/index.tsx b/microsite-next/src/pages/demos/index.tsx new file mode 100644 index 0000000000..07330b7607 --- /dev/null +++ b/microsite-next/src/pages/demos/index.tsx @@ -0,0 +1,3 @@ +import { Demos } from './demos'; + +export default Demos; From 69c4fe79abe5ca9b318ab6abcbb3ef5ea2652a0c Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Thu, 2 Feb 2023 18:12:26 -0500 Subject: [PATCH 166/417] fix: Update deps & fix named page files to ignore by router Signed-off-by: Carlos Esteban Lopez --- microsite-next/package.json | 6 +- .../{community.tsx => _community.tsx} | 0 .../src/pages/community/community.module.scss | 1 + microsite-next/src/pages/community/index.tsx | 2 +- .../src/pages/demos/{demos.tsx => _demos.tsx} | 0 microsite-next/src/pages/demos/index.tsx | 2 +- .../{plugin-card.tsx => _plugin-card.tsx} | 0 .../plugins/{plugins.tsx => _plugins.tsx} | 2 +- microsite-next/src/pages/plugins/index.tsx | 2 +- microsite-next/yarn.lock | 367 ++++++++++-------- 10 files changed, 205 insertions(+), 177 deletions(-) rename microsite-next/src/pages/community/{community.tsx => _community.tsx} (100%) rename microsite-next/src/pages/demos/{demos.tsx => _demos.tsx} (100%) rename microsite-next/src/pages/plugins/{plugin-card.tsx => _plugin-card.tsx} (100%) rename microsite-next/src/pages/plugins/{plugins.tsx => _plugins.tsx} (97%) diff --git a/microsite-next/package.json b/microsite-next/package.json index 01feee18dc..861d0ff958 100644 --- a/microsite-next/package.json +++ b/microsite-next/package.json @@ -17,7 +17,7 @@ "docusaurus": "docusaurus" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^2.2.0", + "@docusaurus/module-type-aliases": "2.3.0", "@spotify/prettier-config": "^14.0.0", "@tsconfig/docusaurus": "^1.0.6", "@types/webpack-env": "^1.18.0", @@ -29,8 +29,8 @@ }, "prettier": "@spotify/prettier-config", "dependencies": { - "@docusaurus/core": "2.2.0", - "@docusaurus/preset-classic": "2.2.0", + "@docusaurus/core": "2.3.0", + "@docusaurus/preset-classic": "2.3.0", "clsx": "^1.1.1", "docusaurus-plugin-sass": "^0.2.3", "react": "^17.0.2", diff --git a/microsite-next/src/pages/community/community.tsx b/microsite-next/src/pages/community/_community.tsx similarity index 100% rename from microsite-next/src/pages/community/community.tsx rename to microsite-next/src/pages/community/_community.tsx diff --git a/microsite-next/src/pages/community/community.module.scss b/microsite-next/src/pages/community/community.module.scss index 87dcdf92d1..5052b7d3b2 100644 --- a/microsite-next/src/pages/community/community.module.scss +++ b/microsite-next/src/pages/community/community.module.scss @@ -26,6 +26,7 @@ } p { + text-align: justify; flex: 1; } } diff --git a/microsite-next/src/pages/community/index.tsx b/microsite-next/src/pages/community/index.tsx index 5f3fd915db..474352685a 100644 --- a/microsite-next/src/pages/community/index.tsx +++ b/microsite-next/src/pages/community/index.tsx @@ -1,3 +1,3 @@ -import { Community } from './community'; +import { Community } from './_community'; export default Community; diff --git a/microsite-next/src/pages/demos/demos.tsx b/microsite-next/src/pages/demos/_demos.tsx similarity index 100% rename from microsite-next/src/pages/demos/demos.tsx rename to microsite-next/src/pages/demos/_demos.tsx diff --git a/microsite-next/src/pages/demos/index.tsx b/microsite-next/src/pages/demos/index.tsx index 07330b7607..db9298c0c6 100644 --- a/microsite-next/src/pages/demos/index.tsx +++ b/microsite-next/src/pages/demos/index.tsx @@ -1,3 +1,3 @@ -import { Demos } from './demos'; +import { Demos } from './_demos'; export default Demos; diff --git a/microsite-next/src/pages/plugins/plugin-card.tsx b/microsite-next/src/pages/plugins/_plugin-card.tsx similarity index 100% rename from microsite-next/src/pages/plugins/plugin-card.tsx rename to microsite-next/src/pages/plugins/_plugin-card.tsx diff --git a/microsite-next/src/pages/plugins/plugins.tsx b/microsite-next/src/pages/plugins/_plugins.tsx similarity index 97% rename from microsite-next/src/pages/plugins/plugins.tsx rename to microsite-next/src/pages/plugins/_plugins.tsx index c904b57382..2e165ba60b 100644 --- a/microsite-next/src/pages/plugins/plugins.tsx +++ b/microsite-next/src/pages/plugins/_plugins.tsx @@ -4,7 +4,7 @@ import Layout from '@theme/Layout'; import clsx from 'clsx'; import React from 'react'; -import { IPluginData, PluginCard } from './plugin-card'; +import { IPluginData, PluginCard } from './_plugin-card'; import pluginsStyles from './plugins.module.scss'; //#region Plugin data import diff --git a/microsite-next/src/pages/plugins/index.tsx b/microsite-next/src/pages/plugins/index.tsx index 9aec0c2586..d95494d73d 100644 --- a/microsite-next/src/pages/plugins/index.tsx +++ b/microsite-next/src/pages/plugins/index.tsx @@ -1,3 +1,3 @@ -import { Plugins } from './plugins'; +import { Plugins } from './_plugins'; export default Plugins; diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 8dc3fce883..7c627edcb4 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -1660,9 +1660,9 @@ __metadata: languageName: node linkType: hard -"@docusaurus/core@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/core@npm:2.2.0" +"@docusaurus/core@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/core@npm:2.3.0" dependencies: "@babel/core": ^7.18.6 "@babel/generator": ^7.18.7 @@ -1674,13 +1674,13 @@ __metadata: "@babel/runtime": ^7.18.6 "@babel/runtime-corejs3": ^7.18.6 "@babel/traverse": ^7.18.8 - "@docusaurus/cssnano-preset": 2.2.0 - "@docusaurus/logger": 2.2.0 - "@docusaurus/mdx-loader": 2.2.0 + "@docusaurus/cssnano-preset": 2.3.0 + "@docusaurus/logger": 2.3.0 + "@docusaurus/mdx-loader": 2.3.0 "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/utils": 2.2.0 - "@docusaurus/utils-common": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/utils": 2.3.0 + "@docusaurus/utils-common": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 "@slorber/static-site-generator-webpack-plugin": ^4.0.7 "@svgr/webpack": ^6.2.1 autoprefixer: ^10.4.7 @@ -1740,40 +1740,40 @@ __metadata: react-dom: ^16.8.4 || ^17.0.0 bin: docusaurus: bin/docusaurus.mjs - checksum: ff47e6cf85b0f7dc0a9e5b9b0d26e33a6f7385f067566ff4f9b026d044839e4dfb4c3bc9476cfab7a7e95a0065478a534cda403dac3bb7bac9987406f1978a11 + checksum: 59954cd761e1cf55c951014a5bb960498b619a6a65fa82c853cc55317e8d27385f0be410b76381221dca136ab0d0030dcbaedca173f38f8495fefbac3e5235d4 languageName: node linkType: hard -"@docusaurus/cssnano-preset@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/cssnano-preset@npm:2.2.0" +"@docusaurus/cssnano-preset@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/cssnano-preset@npm:2.3.0" dependencies: cssnano-preset-advanced: ^5.3.8 postcss: ^8.4.14 postcss-sort-media-queries: ^4.2.1 tslib: ^2.4.0 - checksum: eff9707414867bf844ef5d84bde1c843593b9b7f542dd1a0a7acc88798b0c5ddb721124229912c234bd88b93cb18d8d69c6115cbf706c2a790497f7d9dd23757 + checksum: ec51299236c1fdad1ce7f761eb85076ebddefbbc21bba9596a226a6e830060e0905fcc072a5dad4e1f668956329b7296e3b1b4468956d29cd607190d7dd5531b languageName: node linkType: hard -"@docusaurus/logger@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/logger@npm:2.2.0" +"@docusaurus/logger@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/logger@npm:2.3.0" dependencies: chalk: ^4.1.2 tslib: ^2.4.0 - checksum: b3ce6e18721a34793a892221485c941d5f7112ae96d569f7918d12c1f50bde9c99bc4195f4d225e874b2bd5800a35413bfeaf78b63c6fbae5f3015d44d118eee + checksum: bf668d380e35ab795c0c28c4891794519093d13ae00221fe43981be1863fdada1f2de1c46095a9c949c15c545d1ad007d1714ee8a3862042c8f75785fded6e1a languageName: node linkType: hard -"@docusaurus/mdx-loader@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/mdx-loader@npm:2.2.0" +"@docusaurus/mdx-loader@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/mdx-loader@npm:2.3.0" dependencies: "@babel/parser": ^7.18.8 "@babel/traverse": ^7.18.8 - "@docusaurus/logger": 2.2.0 - "@docusaurus/utils": 2.2.0 + "@docusaurus/logger": 2.3.0 + "@docusaurus/utils": 2.3.0 "@mdx-js/mdx": ^1.6.22 escape-html: ^1.0.3 file-loader: ^6.2.0 @@ -1790,16 +1790,16 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: fee586498f43c46581062e681424c4637e75d505d813d8bf25f5315c912560f6600cd925bc5b07a93d5d5966741439578e7e72f30030b4c58a5cfdf72e0d8928 + checksum: e07be7155941ca9e3e07f996a0364e12bd5b9793b804bf87121341a491420047e88f7c010bde5ee71e65bed47b4febda242b601773f74bcafc116dd09ec8f5b5 languageName: node linkType: hard -"@docusaurus/module-type-aliases@npm:2.2.0, @docusaurus/module-type-aliases@npm:^2.2.0": - version: 2.2.0 - resolution: "@docusaurus/module-type-aliases@npm:2.2.0" +"@docusaurus/module-type-aliases@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/module-type-aliases@npm:2.3.0" dependencies: "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/types": 2.2.0 + "@docusaurus/types": 2.3.0 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -1809,21 +1809,21 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: ebcb9dff2f88b5962cd34aaa78b1a48531da4776229ef507665e3f053cccb185aadcc16c3703f21031e14ccb6c8312662a6eec1a2a06bc0a423221ad200e1e9e + checksum: 96d9dc39d90bbec155a55403272a9c3be2603fd556c1e4da6db161e3841de671e9e219b1de153f072ab09a440f523a628c4e382ff527acd527780e7843aebe0d languageName: node linkType: hard -"@docusaurus/plugin-content-blog@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/plugin-content-blog@npm:2.2.0" +"@docusaurus/plugin-content-blog@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-content-blog@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/logger": 2.2.0 - "@docusaurus/mdx-loader": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils": 2.2.0 - "@docusaurus/utils-common": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/logger": 2.3.0 + "@docusaurus/mdx-loader": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils": 2.3.0 + "@docusaurus/utils-common": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 cheerio: ^1.0.0-rc.12 feed: ^4.2.2 fs-extra: ^10.1.0 @@ -1836,21 +1836,21 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 6d51e3b17b6fdeb4e04ddebe4d4ba8c7cc830bdc066c2b7898e4dee185e408f0d28ea873d18b5ee4406a568a9b05f70d17c986a9ed16b16b1450d34ca190fd06 + checksum: e5b89196ddec47f7c282b9f5fba1d1caada0c6d44776e2f55ee5b13b440661f586bef18553d49e3b44a417982e4c799d3e18e10f60d60e90a0b8c90b8b30232a languageName: node linkType: hard -"@docusaurus/plugin-content-docs@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/plugin-content-docs@npm:2.2.0" +"@docusaurus/plugin-content-docs@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-content-docs@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/logger": 2.2.0 - "@docusaurus/mdx-loader": 2.2.0 - "@docusaurus/module-type-aliases": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/logger": 2.3.0 + "@docusaurus/mdx-loader": 2.3.0 + "@docusaurus/module-type-aliases": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 "@types/react-router-config": ^5.0.6 combine-promises: ^1.1.0 fs-extra: ^10.1.0 @@ -1863,116 +1863,132 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 3a262b49dd6f9d59f4e10dd25185bb4280dbf77b62e28a1dd658d5db0861ae8c82dd025f24212f0d8fec0a46a37f6ef0f2cde25ac736d445247e8727177da660 + checksum: a18bd0c7e089239819938675fd3c3f5a7447cfeae6f27dac165a34558d4b39cad8a4934736228ecf4d7dde6f28fe4e1c5ed97ba9f5cba3251f5eb4781517f413 languageName: node linkType: hard -"@docusaurus/plugin-content-pages@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/plugin-content-pages@npm:2.2.0" +"@docusaurus/plugin-content-pages@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-content-pages@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/mdx-loader": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/mdx-loader": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 fs-extra: ^10.1.0 tslib: ^2.4.0 webpack: ^5.73.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 1e22fb8deb9b8f612ebe1ea6f8b1ce76acfc6eb8cbc0d5fc9b99b99d64e2f356d0fb136247e9f72cd84b2788eaf953a640d23ff7e2a5d650de6ec06468181a94 + checksum: 3ff7090045929a64b87da4e5e5a57cf725e552b03569d2a0086cf79849316393948e239d58f4bea758d131224b165ceb96ab1e908e357e6e256b5e499f0d4ad6 languageName: node linkType: hard -"@docusaurus/plugin-debug@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/plugin-debug@npm:2.2.0" +"@docusaurus/plugin-debug@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-debug@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils": 2.3.0 fs-extra: ^10.1.0 react-json-view: ^1.21.3 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: edf2a416b790591c66ffa8ca1fd4ed15ab2d2dc15cd67c5253714502a6828739a7a47996c3664731c6b24da1da5862ddfef60defb84bd3b8273313267db0cb54 + checksum: 770cd5749730ebb3f8633f7c07b0e5248ee24c175dcb6bfc99717253fc6e16ac75d720e373a4d98ade51ca47ec69543cd7159f215961f64d41f95120efe06c76 languageName: node linkType: hard -"@docusaurus/plugin-google-analytics@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/plugin-google-analytics@npm:2.2.0" +"@docusaurus/plugin-google-analytics@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-google-analytics@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 44ad3a6c1b661516cb87553103565af64a6f145d823b16882d5c7d23b99e091b7c4ba8323c5f6fe756e70fbb0f9f31d56c74512dc17da6d3c16dfabd17d719ac + checksum: 2de84efb8998c36315d856ec1c7fe40af9265d078642f2984d280d9e698af45922dcc205039fbaeb30f45802d788e230fe34cd4d292d57d95f99c006b92f2e25 languageName: node linkType: hard -"@docusaurus/plugin-google-gtag@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/plugin-google-gtag@npm:2.2.0" +"@docusaurus/plugin-google-gtag@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-google-gtag@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 4e7d6fcc3f30f1d54933fdeb59d3065989596e91940304965635867808d89c7b864a394f5fab2bcde98037539bf6840efc692e856fb7a4ae32ce8b5f8a4e191a + checksum: 8d1c192163ed902498ed8ff5fef668a8ebd8fd63b3da691295a875ef96eb98e2e9b0967986dff2ea454f2094479fec2e4876d2f66c643a174df26204e4aab2a2 languageName: node linkType: hard -"@docusaurus/plugin-sitemap@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/plugin-sitemap@npm:2.2.0" +"@docusaurus/plugin-google-tag-manager@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-google-tag-manager@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/logger": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils": 2.2.0 - "@docusaurus/utils-common": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 + tslib: ^2.4.0 + peerDependencies: + react: ^16.8.4 || ^17.0.0 + react-dom: ^16.8.4 || ^17.0.0 + checksum: dd9830fd4f3ee5f4ab1a8a26a055b7551084e49dd33046eb62950fa74a30d1c6371cacb10f42753ba0b32b025bdcb34abf6877dd7b7fe42e9ab86f3539634483 + languageName: node + linkType: hard + +"@docusaurus/plugin-sitemap@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/plugin-sitemap@npm:2.3.0" + dependencies: + "@docusaurus/core": 2.3.0 + "@docusaurus/logger": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils": 2.3.0 + "@docusaurus/utils-common": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 fs-extra: ^10.1.0 sitemap: ^7.1.1 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 8ae78093d17a96fc2c6f3829d425731dae3af19b0eec29c61a6465342462a8c24da4c5a10f1a1b1813630d2408f2e11fa17af652b74b4e8fda975d4a00bf1389 + checksum: f2ace8f5a121aa616d411dbe0211ecba5ca57ad1fceb4529f8418c4c5259cfe62a5a511332289502242e6ff04116d27ddf5a8826d16324cc1ccaacfca29b49b1 languageName: node linkType: hard -"@docusaurus/preset-classic@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/preset-classic@npm:2.2.0" +"@docusaurus/preset-classic@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/preset-classic@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/plugin-content-blog": 2.2.0 - "@docusaurus/plugin-content-docs": 2.2.0 - "@docusaurus/plugin-content-pages": 2.2.0 - "@docusaurus/plugin-debug": 2.2.0 - "@docusaurus/plugin-google-analytics": 2.2.0 - "@docusaurus/plugin-google-gtag": 2.2.0 - "@docusaurus/plugin-sitemap": 2.2.0 - "@docusaurus/theme-classic": 2.2.0 - "@docusaurus/theme-common": 2.2.0 - "@docusaurus/theme-search-algolia": 2.2.0 - "@docusaurus/types": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/plugin-content-blog": 2.3.0 + "@docusaurus/plugin-content-docs": 2.3.0 + "@docusaurus/plugin-content-pages": 2.3.0 + "@docusaurus/plugin-debug": 2.3.0 + "@docusaurus/plugin-google-analytics": 2.3.0 + "@docusaurus/plugin-google-gtag": 2.3.0 + "@docusaurus/plugin-google-tag-manager": 2.3.0 + "@docusaurus/plugin-sitemap": 2.3.0 + "@docusaurus/theme-classic": 2.3.0 + "@docusaurus/theme-common": 2.3.0 + "@docusaurus/theme-search-algolia": 2.3.0 + "@docusaurus/types": 2.3.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 70214f17766097a2e9c4b21a343bf323f7ed3d2e23c6169577cd14333a074fa15aabff6532c1774ec17c54f50c1616dbd8625c41a115d2fe799b2b7fa830c2c9 + checksum: 0806924793094a4446b20d63fdc910c5ae82b2353905502f886c2a02981a4e42378b0251e38a60caf496e6e6034014096829eb51401685f747934eb83f15dcbb languageName: node linkType: hard @@ -1988,22 +2004,22 @@ __metadata: languageName: node linkType: hard -"@docusaurus/theme-classic@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/theme-classic@npm:2.2.0" +"@docusaurus/theme-classic@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/theme-classic@npm:2.3.0" dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/mdx-loader": 2.2.0 - "@docusaurus/module-type-aliases": 2.2.0 - "@docusaurus/plugin-content-blog": 2.2.0 - "@docusaurus/plugin-content-docs": 2.2.0 - "@docusaurus/plugin-content-pages": 2.2.0 - "@docusaurus/theme-common": 2.2.0 - "@docusaurus/theme-translations": 2.2.0 - "@docusaurus/types": 2.2.0 - "@docusaurus/utils": 2.2.0 - "@docusaurus/utils-common": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/mdx-loader": 2.3.0 + "@docusaurus/module-type-aliases": 2.3.0 + "@docusaurus/plugin-content-blog": 2.3.0 + "@docusaurus/plugin-content-docs": 2.3.0 + "@docusaurus/plugin-content-pages": 2.3.0 + "@docusaurus/theme-common": 2.3.0 + "@docusaurus/theme-translations": 2.3.0 + "@docusaurus/types": 2.3.0 + "@docusaurus/utils": 2.3.0 + "@docusaurus/utils-common": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 "@mdx-js/react": ^1.6.22 clsx: ^1.2.1 copy-text-to-clipboard: ^3.0.1 @@ -2020,20 +2036,20 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: ccfb0bef12178d0fbe3329a3238cd6bf7223ee03d890594676c06490eabfd59908bb1872c1a007f605db4edf402bc49cdf14aa7116550e95844d5135a92c2969 + checksum: a6206f34161aa388e36dde2f8eb9291cec34dba890a40cd7226040efd303aa322110237464016ce407a65b8a2bff755470ff6c5250b20e3a27645d8860246a65 languageName: node linkType: hard -"@docusaurus/theme-common@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/theme-common@npm:2.2.0" +"@docusaurus/theme-common@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/theme-common@npm:2.3.0" dependencies: - "@docusaurus/mdx-loader": 2.2.0 - "@docusaurus/module-type-aliases": 2.2.0 - "@docusaurus/plugin-content-blog": 2.2.0 - "@docusaurus/plugin-content-docs": 2.2.0 - "@docusaurus/plugin-content-pages": 2.2.0 - "@docusaurus/utils": 2.2.0 + "@docusaurus/mdx-loader": 2.3.0 + "@docusaurus/module-type-aliases": 2.3.0 + "@docusaurus/plugin-content-blog": 2.3.0 + "@docusaurus/plugin-content-docs": 2.3.0 + "@docusaurus/plugin-content-pages": 2.3.0 + "@docusaurus/utils": 2.3.0 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -2041,26 +2057,27 @@ __metadata: parse-numeric-range: ^1.3.0 prism-react-renderer: ^1.3.5 tslib: ^2.4.0 + use-sync-external-store: ^1.2.0 utility-types: ^3.10.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 23cbba8e7e24494c6d106ce3d0b90ef461580bfacef9f27dfbc4f0b33fcb349394faf2bedf0a44db8c455535e50e828e82270c8f159c3d8d60f0e0980170be4e + checksum: e38683aa8fd74599b9ccb6032af7a0ccb76144f5b3ccc4b93d423be263ca5ffb1ace42c22ce789c11ab45ae076fdf95bd36287b551edbf51d55c2e848e8a6189 languageName: node linkType: hard -"@docusaurus/theme-search-algolia@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/theme-search-algolia@npm:2.2.0" +"@docusaurus/theme-search-algolia@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/theme-search-algolia@npm:2.3.0" dependencies: "@docsearch/react": ^3.1.1 - "@docusaurus/core": 2.2.0 - "@docusaurus/logger": 2.2.0 - "@docusaurus/plugin-content-docs": 2.2.0 - "@docusaurus/theme-common": 2.2.0 - "@docusaurus/theme-translations": 2.2.0 - "@docusaurus/utils": 2.2.0 - "@docusaurus/utils-validation": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/logger": 2.3.0 + "@docusaurus/plugin-content-docs": 2.3.0 + "@docusaurus/theme-common": 2.3.0 + "@docusaurus/theme-translations": 2.3.0 + "@docusaurus/utils": 2.3.0 + "@docusaurus/utils-validation": 2.3.0 algoliasearch: ^4.13.1 algoliasearch-helper: ^3.10.0 clsx: ^1.2.1 @@ -2072,23 +2089,23 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 42b6cb0322d6c772b7796ea6e9693d596554ebd087792ad71238cebedf3b632bfa8005138d521bce1ff118f49aea7d72e5dc97a03f236b4728a2dc7576870071 + checksum: 97d7314ae6c612eda1b8aa24b6d812c66a8da1030f7eea8d04c9ab8caba62bb66ec95dfcbb613f0f522fa6130e51cd41fcc7eca1c0fe50e533ccbf5aa9e2047d languageName: node linkType: hard -"@docusaurus/theme-translations@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/theme-translations@npm:2.2.0" +"@docusaurus/theme-translations@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/theme-translations@npm:2.3.0" dependencies: fs-extra: ^10.1.0 tslib: ^2.4.0 - checksum: 7fe7d104fd094f2af2321986a86edef1eb8ab25415ea94ab1b242d08aec7627b3d5790001631621cd80c57c710714308aad5adfbf570cb74e0f01fda93b610be + checksum: df11b8a0b569a5adaec505d52cccffef1d903404232c776354035a387b56fcc7aa7d742aa0df622ccc052b61443ba134b6dcc6d3a4076aced4cd253d6cf957f6 languageName: node linkType: hard -"@docusaurus/types@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/types@npm:2.2.0" +"@docusaurus/types@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/types@npm:2.3.0" dependencies: "@types/history": ^4.7.11 "@types/react": "*" @@ -2101,13 +2118,13 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 5166ca49bb9333e4d733e4bf8d49d65e11ea6b39e4d8eecc24e1de24d61d2459c52dd8bd27362b66b03e41df96acf1a449145211b3bf0c5a59a987c77102e8f1 + checksum: 563749b9473e35848c3e462c7e401d292dbf3f36e3ab72b5a03aebe204f1147b666953fc8e176c2024ea9c2b3a8aa7fd33f500df576afff456dea003b742c52b languageName: node linkType: hard -"@docusaurus/utils-common@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/utils-common@npm:2.2.0" +"@docusaurus/utils-common@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/utils-common@npm:2.3.0" dependencies: tslib: ^2.4.0 peerDependencies: @@ -2115,29 +2132,30 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 05d23a2f82a1bc119e3ad6b37481c9bc984f62efd3a79046567216784b78fb20fe7452252d610bb4c063e4ded8a7ab7efa1dc9f9f228357c20b9f4729c7a0576 + checksum: 67711f2a53cd9e91768645015ab17e9c3b46d850958a4dcab6e0fb939b4d90bb3bb0323f8c70446246af6aacad98c1044d33f5f74dcc8e8bc9871ae62ea33a7b languageName: node linkType: hard -"@docusaurus/utils-validation@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/utils-validation@npm:2.2.0" +"@docusaurus/utils-validation@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/utils-validation@npm:2.3.0" dependencies: - "@docusaurus/logger": 2.2.0 - "@docusaurus/utils": 2.2.0 + "@docusaurus/logger": 2.3.0 + "@docusaurus/utils": 2.3.0 joi: ^17.6.0 js-yaml: ^4.1.0 tslib: ^2.4.0 - checksum: a30e47cf84628950176cc02a121f31b200b46cdccf02e80d76f24b51b9d33fccee35c43047f507b8fb48deb38f863580ecbcdc1393718c6f3a14fcd40d5d1ab6 + checksum: 0275530f4c49a1d0269422dfbe8f7abcda94c83fb3c20d1be36f9259b16c2170f8090f30077091b02e1059b2c683726d40b19235f07250f245719159d3ecd98c languageName: node linkType: hard -"@docusaurus/utils@npm:2.2.0": - version: 2.2.0 - resolution: "@docusaurus/utils@npm:2.2.0" +"@docusaurus/utils@npm:2.3.0": + version: 2.3.0 + resolution: "@docusaurus/utils@npm:2.3.0" dependencies: - "@docusaurus/logger": 2.2.0 + "@docusaurus/logger": 2.3.0 "@svgr/webpack": ^6.2.1 + escape-string-regexp: ^4.0.0 file-loader: ^6.2.0 fs-extra: ^10.1.0 github-slugger: ^1.4.0 @@ -2156,7 +2174,7 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: d027a6d2417e043ac463402aadca22f1101f942daaf02330d9bb4743dcbe3bd2fd46d27dedf316fcf2b6698713fede974ba59eb5d4bc92c8959e23bc25e7a03a + checksum: 6874bd327af99bc97bdea3fca6ce71f917b6a89fa18bbd81a2d955a33ccf1746f70960f27fc7fca557bc9e1a671a6f369e7aade28f7908727dc58e84f9ac5851 languageName: node linkType: hard @@ -3579,9 +3597,9 @@ __metadata: version: 0.0.0-use.local resolution: "backstage-microsite@workspace:." dependencies: - "@docusaurus/core": 2.2.0 - "@docusaurus/module-type-aliases": ^2.2.0 - "@docusaurus/preset-classic": 2.2.0 + "@docusaurus/core": 2.3.0 + "@docusaurus/module-type-aliases": 2.3.0 + "@docusaurus/preset-classic": 2.3.0 "@spotify/prettier-config": ^14.0.0 "@tsconfig/docusaurus": ^1.0.6 "@types/webpack-env": ^1.18.0 @@ -10496,6 +10514,15 @@ __metadata: languageName: node linkType: hard +"use-sync-external-store@npm:^1.2.0": + version: 1.2.0 + resolution: "use-sync-external-store@npm:1.2.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a + languageName: node + linkType: hard + "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" From c0e0bcc137b3293a48b7f57e18c500536893169b Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Fri, 3 Feb 2023 22:02:42 -0500 Subject: [PATCH 167/417] feat: Add home page with first banner Signed-off-by: Carlos Esteban Lopez --- microsite-next/src/pages/home/_home.tsx | 82 +++++++++++++++++++ .../src/pages/home/home.module.scss | 44 ++++++++++ microsite-next/src/pages/index.tsx | 12 +-- 3 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 microsite-next/src/pages/home/_home.tsx create mode 100644 microsite-next/src/pages/home/home.module.scss diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx new file mode 100644 index 0000000000..f7ad7f6bf9 --- /dev/null +++ b/microsite-next/src/pages/home/_home.tsx @@ -0,0 +1,82 @@ +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Layout from '@theme/Layout'; +import { clsx } from 'clsx'; +import React from 'react'; + +import homeStyles from './home.module.scss'; + +export function Home() { + const { siteConfig } = useDocusaurusContext(); + + return ( + +
    +
    +
    +
    +
    +
    + 🗞️ Want to stay up to date with Backstage? Sign up for our{' '} + + Newsletter + + ! +
    + +
    X
    +
    +
    +
    + +
    +
    +

    An open platform for building developer portals

    + +

    + Powered by a centralized software catalog, Backstage restores + order to your infrastructure and enables your product teams to + ship high-quality code quickly — without compromising autonomy. +

    + +
    + + GITHUB + + + OFFICE HOURS + +
    +
    + +
    + + +
    +
    +
    +
    +
    + ); +} diff --git a/microsite-next/src/pages/home/home.module.scss b/microsite-next/src/pages/home/home.module.scss new file mode 100644 index 0000000000..ae804e344d --- /dev/null +++ b/microsite-next/src/pages/home/home.module.scss @@ -0,0 +1,44 @@ +.homePage { + font-size: 1.25rem; + + h1 { + font-size: 54px; + line-height: 56px; + word-break: break-word; + } + + :global(.buttonsContainer) { + gap: 1rem; + display: grid; + grid-template-columns: repeat(2, auto); + } +} + +.newsletterBanner { + --ifm-link-hover-color: var(--ifm-color-info); + + flex-direction: row; + color: var(--ifm-button-color); + background-color: var(--ifm-color-primary); + + :global(.bannerContent) { + flex: 1; + } +} + +.openPlatformBanner { + :global(.svgContainer) { + position: relative; + + :global(img.laptopSvg) { + width: 100%; + } + + :global(img.laptopScreenGif) { + position: absolute; + top: 3%; + left: 17%; + width: 70%; + } + } +} diff --git a/microsite-next/src/pages/index.tsx b/microsite-next/src/pages/index.tsx index 3bbf03b0e2..853a4b2c82 100644 --- a/microsite-next/src/pages/index.tsx +++ b/microsite-next/src/pages/index.tsx @@ -1,11 +1,3 @@ -import Layout from '@theme/Layout'; -import React from 'react'; +import { Home } from './home/_home'; -function Index() { - return ( - -

    HELLO

    -
    - ); -} -export default Index; +export default Home; From 2c21d5f6c57562ba6a6b456826a76da782ac6803 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Mon, 6 Feb 2023 22:01:49 -0500 Subject: [PATCH 168/417] feat: Extract reusable block & add catalog section to home page Signed-off-by: Carlos Esteban Lopez --- .../banner-section-columns.module.scss | 43 +++++ .../banner-section/banner-section-columns.tsx | 34 ++++ .../banner-section/banner-section.module.scss | 29 ++++ .../banner-section/banner-section.tsx | 27 ++++ .../content-block/content-block.module.scss | 22 +++ .../content-block/content-block.tsx | 55 +++++++ microsite-next/src/pages/home/_home.tsx | 152 ++++++++++++++---- .../src/pages/home/home.module.scss | 44 +++-- 8 files changed, 360 insertions(+), 46 deletions(-) create mode 100644 microsite-next/src/components/banner-section/banner-section-columns.module.scss create mode 100644 microsite-next/src/components/banner-section/banner-section-columns.tsx create mode 100644 microsite-next/src/components/banner-section/banner-section.module.scss create mode 100644 microsite-next/src/components/banner-section/banner-section.tsx create mode 100644 microsite-next/src/components/content-block/content-block.module.scss create mode 100644 microsite-next/src/components/content-block/content-block.tsx diff --git a/microsite-next/src/components/banner-section/banner-section-columns.module.scss b/microsite-next/src/components/banner-section/banner-section-columns.module.scss new file mode 100644 index 0000000000..32cc53eb5e --- /dev/null +++ b/microsite-next/src/components/banner-section/banner-section-columns.module.scss @@ -0,0 +1,43 @@ +.bannerSection { + display: block; + + &:global(.greyBackground) { + background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%); + } + + &:global(.greenGradientBackground) { + background: linear-gradient( + 178.64deg, + hsla(0, 0%, 100%, 0) 57.61%, + hsla(0, 0%, 100%, 0.17) 127.71% + ), + linear-gradient( + 144.35deg, + rgba(98, 197, 179, 0) 56.68%, + rgba(98, 197, 179, 0.59) 109.25% + ), + linear-gradient( + 192.29deg, + rgba(155, 240, 225, 0) 54.17%, + rgba(155, 240, 225, 0.67) 137.34% + ); + } + + &:global(.greenBottomGradientBackground) { + background: linear-gradient( + 178.64deg, + hsla(0, 0%, 100%, 0) 57.61%, + hsla(0, 0%, 100%, 0.17) 127.71% + ), + linear-gradient( + 144.35deg, + rgba(98, 197, 179, 0) 56.68%, + rgba(98, 197, 179, 0.59) 109.25% + ), + linear-gradient( + 192.29deg, + rgba(155, 240, 225, 0) 54.17%, + rgba(155, 240, 225, 0.67) 137.34% + ); + } +} diff --git a/microsite-next/src/components/banner-section/banner-section-columns.tsx b/microsite-next/src/components/banner-section/banner-section-columns.tsx new file mode 100644 index 0000000000..db33b52961 --- /dev/null +++ b/microsite-next/src/components/banner-section/banner-section-columns.tsx @@ -0,0 +1,34 @@ +import clsx from 'clsx'; +import React, { PropsWithChildren, ReactNode } from 'react'; + +import bannerColumnStyles from './banner-section-columns.module.scss'; + +export type IBannerSectionColumnsProps = PropsWithChildren<{ + header?: ReactNode; + // children: ReactNode | ReactNode[]; +}>; + +export const BannerSectionColumns = ({ + header, + children, +}: IBannerSectionColumnsProps) => ( + <> + {header && ( +
    +
    {header}
    +
    + )} + + {Array.isArray(children) ? ( +
    + {children.map((child, index) => ( +
    + {child} +
    + ))} +
    + ) : ( + children + )} + +); diff --git a/microsite-next/src/components/banner-section/banner-section.module.scss b/microsite-next/src/components/banner-section/banner-section.module.scss new file mode 100644 index 0000000000..478790877c --- /dev/null +++ b/microsite-next/src/components/banner-section/banner-section.module.scss @@ -0,0 +1,29 @@ +.bannerSection { + display: block; + + &:global(.greyBackground) { + background: linear-gradient(90.49deg, #121212 15.36%, #282828 70.44%); + } + + &:global(.greenGradientBackground) { + background: linear-gradient(70.44deg, #121212 55%, #5d817b); + } + + &:global(.greenBottomGradientBackground) { + background: linear-gradient( + 178.64deg, + hsla(0, 0%, 100%, 0) 57.61%, + hsla(0, 0%, 100%, 0.17) 127.71% + ), + linear-gradient( + 144.35deg, + rgba(98, 197, 179, 0) 56.68%, + rgba(98, 197, 179, 0.59) 109.25% + ), + linear-gradient( + 192.29deg, + rgba(155, 240, 225, 0) 54.17%, + rgba(155, 240, 225, 0.67) 137.34% + ); + } +} diff --git a/microsite-next/src/components/banner-section/banner-section.tsx b/microsite-next/src/components/banner-section/banner-section.tsx new file mode 100644 index 0000000000..d3530d7e49 --- /dev/null +++ b/microsite-next/src/components/banner-section/banner-section.tsx @@ -0,0 +1,27 @@ +import clsx from 'clsx'; +import React, { PropsWithChildren } from 'react'; + +import bannerStyles from './banner-section.module.scss'; + +export type IBannerSectionProps = PropsWithChildren<{ + greyBackground?: boolean; + greenGradientBackground?: boolean; + greenBottomGradientBackground?: boolean; +}>; + +export const BannerSection = ({ + children, + greyBackground = false, + greenGradientBackground = false, + greenBottomGradientBackground = false, +}: IBannerSectionProps) => ( +
    +
    {children}
    +
    +); diff --git a/microsite-next/src/components/content-block/content-block.module.scss b/microsite-next/src/components/content-block/content-block.module.scss new file mode 100644 index 0000000000..77f98400f7 --- /dev/null +++ b/microsite-next/src/components/content-block/content-block.module.scss @@ -0,0 +1,22 @@ +.contentBlock { + gap: 1.5rem; + display: grid; + + > *, + h1, + h2 { + margin: 0; + padding: 0; + } + + :global(.bulletLine) { + width: 50px; + margin-bottom: 0.5rem; + } + + :global(.actionButtons) { + gap: 1rem; + display: grid; + grid-template-columns: repeat(2, auto); + } +} diff --git a/microsite-next/src/components/content-block/content-block.tsx b/microsite-next/src/components/content-block/content-block.tsx new file mode 100644 index 0000000000..4c1cc6272e --- /dev/null +++ b/microsite-next/src/components/content-block/content-block.tsx @@ -0,0 +1,55 @@ +import Link from '@docusaurus/Link'; +import clsx from 'clsx'; +import React, { FC, PropsWithChildren, ReactNode } from 'react'; + +import contentBlockStyles from './content-block.module.scss'; + +export interface ContentBlockActionButtonProps { + label: string; + link: string; +} + +export type IContentBlockProps = PropsWithChildren<{ + title?: ReactNode; + className?: string; + topImgSrc?: string; + hasBulletLine?: boolean; + actionButtons?: ContentBlockActionButtonProps[]; +}>; + +export const ContentBlock = ({ + children, + title, + className, + topImgSrc, + hasBulletLine, + actionButtons, +}: IContentBlockProps) => { + return ( +
    + {topImgSrc && {topImgSrc}} + +
    + {hasBulletLine &&
    } + + {title && React.isValidElement(title) ? title :

    {title}

    } +
    + + {children &&

    {children}

    } + + {actionButtons && ( +
    + {actionButtons.map(({ link, label }, index) => ( + + {label} + + ))} +
    + )} +
    + ); +}; diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx index f7ad7f6bf9..da99da6f1a 100644 --- a/microsite-next/src/pages/home/_home.tsx +++ b/microsite-next/src/pages/home/_home.tsx @@ -4,17 +4,20 @@ import Layout from '@theme/Layout'; import { clsx } from 'clsx'; import React from 'react'; +import { BannerSection } from '../../components/banner-section/banner-section'; import homeStyles from './home.module.scss'; +import { BannerSectionColumns } from '../../components/banner-section/banner-section-columns'; +import { ContentBlock } from '@site/src/components/content-block/content-block'; export function Home() { const { siteConfig } = useDocusaurusContext(); return ( -
    -
    -
    -
    +
    + + X
    -
    -
    + } + > + An open platform for building developer portals} + actionButtons={[ + { + link: 'https://github.com/backstage/backstage#getting-started', + label: 'GITHUB', + }, + { + link: 'https://info.backstage.spotify.com/office-hours', + label: 'OFFICE HOURS', + }, + ]} + > + Powered by a centralized software catalog, Backstage restores + order to your infrastructure and enables your product teams to + ship high-quality code quickly — without compromising autonomy. + -
    -
    -

    An open platform for building developer portals

    - -

    - Powered by a centralized software catalog, Backstage restores - order to your infrastructure and enables your product teams to - ship high-quality code quickly — without compromising autonomy. -

    - -
    - - GITHUB - - - OFFICE HOURS - -
    -
    - -
    +
    + + + + + + + At Spotify, we've always believed in the speed and ingenuity that + comes from having autonomous development teams. But as we learned + firsthand, the faster you grow, the more fragmented and complex + your software ecosystem becomes. And then everything slows down + again. + + + + By centralizing services and standardizing your tooling, Backstage + streamlines your development environment from end to end. Instead + of restricting autonomy, standardization frees your engineers from + infrastructure complexity. So you can return to building and + scaling, quickly and safely. + + + + + +
    +
    + Software Catalog Planet GIF + +

    Backstage Software Catalog

    + +

    Build an ecosystem, not a wilderness

    +
    + + + + + + + + Backstage makes it easy for one team to manage 10 services — and + makes it possible for your company to manage thousands of them + + + + Every team can see all the services they own and related resources + (deployments, data pipelines, pull request status, etc.) + + + + All that information can be shared with plugins inside Backstage + to enable other management features, like resource monitoring and + testing + + + + Libraries, websites, ML models — you name it, Backstage knows all + about it, including who owns it, dependencies, and more + + + + No more orphan software hiding in the dark corners of your tech + stack +
    -
    -
    + +
    ); } diff --git a/microsite-next/src/pages/home/home.module.scss b/microsite-next/src/pages/home/home.module.scss index ae804e344d..aa442a0c7b 100644 --- a/microsite-next/src/pages/home/home.module.scss +++ b/microsite-next/src/pages/home/home.module.scss @@ -26,19 +26,41 @@ } } -.openPlatformBanner { - :global(.svgContainer) { - position: relative; +.svgContainer { + position: relative; - :global(img.laptopSvg) { - width: 100%; - } + :global(img.laptopSvg) { + width: 100%; + } - :global(img.laptopScreenGif) { - position: absolute; - top: 3%; - left: 17%; - width: 70%; + :global(img.laptopScreenGif) { + position: absolute; + top: 3%; + left: 17%; + width: 70%; + } +} + +.catalogContainer { + gap: 2rem; + display: grid; + align-items: center; + + grid-template-columns: repeat(4, 1fr); + + picture { + display: block; + + grid-row: 1/3; + grid-column: 3/-1; + } + + :global(.catalogTitle) { + grid-column: 1/3; + + img { + max-width: 190px; + max-height: 190px; } } } From ed297eead273b5860b14eaf62dd4c1b77815f1e7 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Tue, 7 Feb 2023 21:13:35 -0500 Subject: [PATCH 169/417] feat: Add all Call to Action banners in 1 go, CSS grid media query Signed-off-by: Carlos Esteban Lopez --- .../banner-section/banner-section.module.scss | 6 ++ .../banner-section/banner-section.tsx | 5 +- microsite-next/src/pages/home/_home.tsx | 83 ++++++++++++++++++- .../src/pages/home/home.module.scss | 23 +++-- 4 files changed, 105 insertions(+), 12 deletions(-) diff --git a/microsite-next/src/components/banner-section/banner-section.module.scss b/microsite-next/src/components/banner-section/banner-section.module.scss index 478790877c..2beabf9738 100644 --- a/microsite-next/src/components/banner-section/banner-section.module.scss +++ b/microsite-next/src/components/banner-section/banner-section.module.scss @@ -26,4 +26,10 @@ rgba(155, 240, 225, 0.67) 137.34% ); } + + &:global(.greenCallToActionGradientBackground) { + background: linear-gradient(87.29deg, #9bf0e1 17.71%, #36baa2 80.85%); + + color: var(--ifm-color-gray-900); + } } diff --git a/microsite-next/src/components/banner-section/banner-section.tsx b/microsite-next/src/components/banner-section/banner-section.tsx index d3530d7e49..dbab99200e 100644 --- a/microsite-next/src/components/banner-section/banner-section.tsx +++ b/microsite-next/src/components/banner-section/banner-section.tsx @@ -7,6 +7,7 @@ export type IBannerSectionProps = PropsWithChildren<{ greyBackground?: boolean; greenGradientBackground?: boolean; greenBottomGradientBackground?: boolean; + greenCallToActionGradientBackground?: boolean; }>; export const BannerSection = ({ @@ -14,14 +15,16 @@ export const BannerSection = ({ greyBackground = false, greenGradientBackground = false, greenBottomGradientBackground = false, + greenCallToActionGradientBackground = false, }: IBannerSectionProps) => (
    -
    {children}
    +
    {children}
    ); diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx index da99da6f1a..a715ee93a9 100644 --- a/microsite-next/src/pages/home/_home.tsx +++ b/microsite-next/src/pages/home/_home.tsx @@ -130,10 +130,7 @@ export function Home() { makes it possible for your company to manage thousands of them - + Every team can see all the services they own and related resources (deployments, data pipelines, pull request status, etc.) @@ -158,6 +155,84 @@ export function Home() {

    (;GZU@d|)|LT99DZa@I{N`Rbss<2a%I!qnHO!xzN4U<5&BOmiMM;)kxB~a)$Ape z>aEu(lJK^V8(UW`ZOWnoanv@tGK19vAbHul-_|j^E=X^jYb zcxmg(?fWycQ{j2z7t_e5P7koc;Sg7Z{4cwuqxE;y7$zklfAf(OOI!sVLgwR2T8NO$ zRlnmn-)jI4To)v5dmBXh2N0twe8Qj;XAPYOZ56NkTg1mgzMp&aTL?mfdU3G`T#kg0 z7`dTK_(TLp>V-2i)ERag@$-x3ahM%WWpd4JsL<;U|-WYu$sbB4dk_mud$w5Mg`j+TOSc<$&$idFW{1s)8UgTKb zjndgz2~S%{`!I+2&y-|&Km4jozyOt=i&?k59b1|b$)jeIwYFOaP1XEv1@dqYAnp`< z?*nV@JM zEe#I^3Q<1_@zT#{hKk2mEq;bhy80I(t@h|McGQ(o7apTTAE%=P=csuWc{Mgaq$WNL zkUfC4>_PtSBq!oeWJ)lxrZo^Ot#FEDK|rMjoKr#Q9U$ZgmYgt0~V-L9Zg?=8+$-2?dI2i@9PLCx%!yg_ouT7LPAd;uxHj!x)A6N_&?jeaJ&- zeKtCc@_zwmG#?H!k^7f$a&+d)VIC!+`exY`IVAdgRD3lq-w$`I4(%Nf|5+r<@ri^z z?yKLG7I@8>PaXzHvQ~tT5|4BD0# zh5Ea_P2U)t%KfJ#r(G#91k*+n^c~Li_vrb{SsQZLXc{ZLo5?1aYkJqi((dMKI{ZhI znQ;gVoI;Jfc_kY#?5zjUjFvlnks)fB3^*F;l){cjuJ-`pV0^pw?8h2`%rLM=De+>` z2Yn{g#5rOF`>&qldIc)f#Yo@CH?}dxQw&UzVA(gO=Fqr;Qv8>okwvg`9Lt)~Qj=liZy@ zKNHbNB8`k#z&t4K^45q9R?Tr1Xb_6;z0&dULVEpCj!a@M6{bXusemr)lm#$B3Yis- zuheiq*AM?Qah3vm=;MI>kwSQjTtouzJ)QIiUCaF5?~KWW^2 zF(>7O0&8spW18hx)AVBvLDy`miIc4;CKve@T@ z+N+F;PGqlqoy9d8=0VZo)ZxK2wM|~Ffr(g(G_yVCwCd?;)7XefP$mBmz0+y_T}Fql zeRV~xnM1$;BCYt4ho3gbj-9;a>tU6?s#LErpm(|tQjflo`dg3b5{5XWSnlkNShico zEmUzA^|d$*AS&#QnXsW(BL^;vcB_w`$aV5NN{`{Il{#b6v@-*`GPS>xXKD_TyfJ+-EGO3$$%_BD+@`)&V(k%3{bHUs4NMzYPdmSi?C${FMQk!cZczLZ z52c*^^&_vq8;9P=G~U)vu%m-XVu?9sgsXWATIoQv?z$|h?df@nHf`bYqiu0_PA~DI zUfi#Y*@Kt~$DYNkaFyu_ME5X#9A)N*C$m5hcHVPo>4|w}Nh4Zo`6StU4-lG$Y!io+ zoEY{;U;n&&1phe*{uhVu+@xqim*BR+EUR{&(oq~#R_-egJZg{IQVqxH2iOW^kqc)A zdYFhC=6|kAGO!A=r;}v~G1~EWITIpsFuGSIMmIqr`!d_GGRgd1$7p-m$;?eaQ*3{o zr)YGg8b){tSL*qr(6xv@yr=FW`VFfk%IZrZVoK;SGX%xQ!r32xKyS>}+_B*Ro=6 z<8BgnW-)vGA=C#a_x9b(!>;b&#hgjrA{U@xW@vxA-^ z#2PX=(j39tVPP!h;#(VCZtE;}0}d zDg3`XDo1nbzRVU;_ zvJ!IP&1JJ=7=k73wrk#QOXK<@FdE17i7cs~F#e^4&-2Y3+u}N7tR_pADND~2yu?@O zDNwmpbYfqzCtrSB8hzl>|Oh|O6&&($F1S0T+ ze>Eb|>j0tbVC@r`E?epaIj$I^Q}5%F-T6;Rf8q6BX}e6Mj;DAkVq}eu+m~x+Kk-gL zIU4_$AjRj0t8E#_LPfTbZ15xZGbt(Yc;G-eLwY|z0c>4^bWF=x^)qV_Ul$~gVzX?K zTJY#}y5KZ(jLPP;FS?hjI?m;Aw#00h2(b?jB##Eq=)lEiCnx%9<0T!~s-=Mv>mEO& z%XX8MH1o>R(T|$$%qvFtOO&3cH4>9O$z=4Uj>YtN+kZjbOg(@Mgff>G@`jx?ZWiaO z))1qFItwRo+h-@Xmn#o8w2F5*3bV1A@`P?}-gj!*G2@q{{Cq2%M-1)=w6%*^hrc^n%qg;KB0nv0J8%IzlOU zFKXg-5LXY|5Yu7vZ5J`})%`2G#i`DxDcd@no6uHc!|W0c_WZ{}1*`WMTw*uZ#$Uf# zkwsb5MQq;~-X;j0lPAEJ`@*)vLiX;s)p@HeqNDXph81%L9=70cPdQGGdi~{CCcQTW zzbq9GXiJtHdup`LbO?5c#O_ArkP;>Cue8j#eA*|wGwkqg=kOFtXjxpJ{Ddu4X57r_ zO~sD`C+BG`|096HI1FiBn)qLrY=TXM@#W(w4J0VDrZFCF0!ocr$7b^8FR0}hMlxBW z*w}Cpnnr~5@i{(WuUA^?KM>87gA5J#JUds}rr}il30nux^Tq`OVvL*a(2S>h60ViS8MbH%|iWj>p1nhe8MJW zYw(YuW4!qA`|{Pz9Wq_L$2hdjxR26JjiW@)_(q!htzs{4V=V7CB%6H=tzdY4ls)1z zf%9VXZACU=6eeA-YS`U+g^X0Ri|E60h2LvF@@DMuHBZuznIF(IE)?22hH)lODEl3t zW4zB$rDeOUaN6rN)+y z9I)j(w|7W~qqFe~HziOQjR=u@l;8RIQDXW@*=FvAkm+Rif0*r>uOW1+YcEUEczj&< z&#mR$Q~1Kq{&=^P(m3=cZ!KQigpl=TrVIAH>5VKM8VQNgI%=mV+9w*7l7^a|$fC4W z(zo?+UX-WmB|)^4jj{$POh7OAi-0}NS4WWFmzJQWxho;po2#8J;T@REG!7Ef9LRV# zffh8S4gy0gAE^~}1pR^u^uxeu6)>wEx|G((VfDG3(vY^zzg`G`;sN850&1|)P5Rbu2u9M14qeM;_5%|H0(Epj0aNtCO6NKz2ryBvtjY#W! zXDr=H!3+!#!KR81!$s!l>~NDo;dTBcJn-;{;AfF)hgWjc8F=UxpjcL(d|62xgm055 z`A+4Dn;HKg#3q=*2vFjxC);lp2TFhH_oG;L`~W#4utl@%Z_w7s)}8) z3x!hY_T4A|hovUek6)?48`1D#733ykHg*%pQj{DP+;RP$s>oK~5xSb021|s+?+7j> ze@VYX;^h88xO@QhawVzUUah_IbR{Rn#7onYOV%!@6&Tl^!F2tO+VnCTXOV_NRgs<2 zZWsAKJOY1%sQ&vOfOflFr2mxhWOc)gpXb(10(T9n=;SZ)4&3zKCa>UoQt41V5)yF2Y7M0EAb%EFD*SqI(+y~CD zJ>vVyDeng5X?`)Q0}OX2-UyLuGgbLeu&6z(rKjT9I)O*z$%03~1Qz)N(_v#MzlqZn z0%WNG^_c~5QpvuDG#ag;M$WwvR;HJ>I~-CnMd?2$TQ`1C!Q*hcZ|-%tGiqYFg>KF7 z33q!V9r;GOv2UK9O(bi7^EJ73G54#>0^D>iae_vE)N;$aK!CoBux!u0KfGfKa{jH< ziz`Jo#*HqF2u>YpdLG=~v}dy0E{z|{!6(A{Zzp>uree=4qYNv z^EB!bPn>ewG{%Xv_hQd+^rBle#d}$p(zdPcJ5+*+$r5(HdDl?hG_#7K3^ZvEX$9KFj!k#%i`zV^ zg(R&jo|ibQL5rm8qC;SGa=L*2KduIyN9nCj$%?`ABQ} zVI~ZYOW5QKF`0f4v%9i%vN_@whG3XTkpGF`JE|etwh8JhiGUxoNVR||=`z5uVuDA% z$&*56c+3<{la(pq%vel9&6Plnm!cg#sQQp;$*N4~E=~Q{qn7eZR_L0Z+5-#db z0u=JS93Ca+Z@3Jz8+!}t`8CUmBPr&LP60=q1@985(+7u$?O^&x9boNK;+hUdvSTGz zzkz_)Ib0Qlm$UO$BWtCAYt*Kk6QovPp1fC_I!i0X|Kqv%Mz4`oB@(?&=`*5D+EcF) z#+lOM%D#9p(S*+Doo;sA%FAwdr9}Nwvs;Wmrz^n(`ZZ!Dve+k^IA|;|UMV-|GsDs- zQ3DoIx7S@O2fsTOT>cXS>R(cX*dzf{syBU}V7j4&AxM75dC%(%5J4z4ZXA2+JD(3R zLal*BTcR4Ouo@p;DWl)1C;lpCcdHtlCE}kjkSh(hfJG2KcSR?iOmqML zmEeR}ATZ$-L2iAX7I;px`-l=>Fe#w3Cg>nik2iSBs&?X9_*-=p9_A>Hz$Sk6q|Pzr zYuGr00LsxT)1gE?khry$E@Fgn(C zS*OO$W)iS{idXQy1|^Se1)X^!41K!7uSRTjY^Z9!K;zN0c%r7~DrqW|&1aEEkW+X>mW5x4CHHG}1 zUm!n3&9O1y>^*s!W;IM!m=%uH#`hBc-0BY zD%313Y5d5$_Z#v*Ny<$9*Oe}Eo_d1~F9w&+9=qFuVT<${b3R#N=v@BDWdUnHm;SO{ zdlQT$2A7O{VzP?IgJQVDn#v?SXxGa2z&#-p_042BdVA3M(xcg%!mQQX>u*BU6Qve? z(aPd0^~-}kQZrJpkThvxc8VY1r0XLJHU;^+PjFjDqmWv*V*L?=0SLD_rS>d4Kt>$w zg}8@y@xdO(N_exz^_YBwAb*&&wCl~izL}LII6sAPv4YbCJ8p2G+QfG$6`97=o}0Eyol!=&FG_n}84DdrS|^`x9Qo-JO8NG4)ow$1G`6Wb*FR7&Ech42y$5+Ht%Z5w#IkRLb(aY_&MO zT#VOd+Db@{pm8(W>7|oljg#(I7xdt=5Bb-blugQ)`ebWl6O}T~w68P>JXUMtUDkh@ z>HP<<>V_#oce}B)1Y6(qMLU4#-UgpiR-y~jT;Y-MK|KiMu218TXtK4d^KN5IW2Y{T zg(CYYt65g0W^_ltTZ~GDR7ld#AjNu<12Nh_aHGkItm<%ebAAB^U*MNu+`&%fIR}wWABGYmSc{jYUmf!XIqS{Z85ZSvetHSuw(w zcE(`p22=5q_Fka%kY!zu0cLdj?C@6!7MFNE&Cj8S{@J(bxVgp$wQ>v_oHg0QvLOCV z!}kl3-6)$IP zOVKz8R){(;fuo`rKzOQ+4*SXV`CR*{Du7zfiAZwZ~+<3Hqfa8`oyPzUGjpz&6>(?NZ_$f%i@}#a6KrS;-T3 zoUfc!;;#?$;$bHYD1Kuqj!F5JXQ~nu_8{P^fPWz7WP7~1_(Y=YJcoqea)T0oh4E{J zP`kD2$yBDlIrjeXN z?P>e_vG@&O82GE#)Oi0W9Iy)3WNKH!zIt5e9Y|v&5Z`2j4mE-7#WJlSKN@pzXkob{ zzy|LOV(IBjXgRWYPW7Wac4iFsGhtBQ0UY~9O|_FGx31n(YaSD|&F6f7(F~+CHaqKv zq;E_K6TrWUD9^75?(pNH@kpr%cq%J;6k|WZw~Fz1R=BxUTjX!9Tl(k&b%2+Q%@k{r zLK1t#Z~Z9YFVCNC8L(>k6~Zjm4WyP?hSrB(=}dvot-sjFBkuHrn8dmQIc}$h^Q`N7 znc5}ABdL=OKj@p(r7po5+zN)?!PXqCngr_0=#jQ-_X9ezbBB=?5k6i@C$)Bj8R7X% z-^YRk^jlUkRe-ZL!p6STAhspIfP!@Q7p6V4aUk z%$M{m?}$gs>Sso|Jf6OYy1o&0eTaaXgQ;fkfFoRdJWs(5diCzlbJSltn2Lm_TRwzG ze&2V+_vG8@B>H^bzs8L$i6DQ?F2b?NwFs@F3_imdu&T@SERnPTbI_}V1zEu4`s|8M z{=DBHURZ>ftCb`H31M5#R?402(h?QA__{GcC9s`_IAvZWgRF6ElAcC(wlg(6u0!?$ zF6U)4_>GPYI|=mo#^edFa@O&~Sy;%`S`5IjkBcx>S9CN`k~TH;n9S zN$dzI264$l#y&lZL6zx@7%3w+4)$tSM)|9PK6A0raJbwX+&dsxyLaGzydw%2Xj^x# zy00eUOhsk+#YdE}V+08AY-rCA^6dt9-yy&c=-fXs(aMhEqhl2xy>LBZd$cVW9S@_d za&-+e3@x}@v81Q6lSJebhs32QqciTLhS}aICtBY}0H%!Hs9hSha{CmD_eW*48fjA| zLsDU7e=IJ_#udh5*9r=<`}%yFU^;2*ACtOXn^$wegYnkEI%@5FbnqFmrFpQV8xI;Q z34I@Q{XeK(@@z}LrG`7#fQwYzM0G*mBrcyvtulZ0&8B#}E_T<2!%K)xekokh^D&W( z=kL5jcsu%S7FWCv;_K)GMt3w6vL_)wm`d^@RPz~h1D-s7yV#QWOnLLQZ!2VqSS+IP zro4I^gIk6j5FPgbK?c~JS{1N)@|?j{3;G<|Zpojh&9a&7JSMe&Zm34}9W));KfgnO zVQnAvuNttaqjzj%mxF#JL|ab?K=9z_oXWWX<>(7%j*)EwxF^arT^tC$&vss36qh=@ zKi<7ehW`nBsi`^2(%(kBv8E^Mjas?0ZQTc{*$|d=rl*W*mUT8a8^$CPbFMLkbz$#r z{_HZ(GR9V}?gw*-r+pjS>iB4h4cm?UywP$3oBjCLLs-Bj*t%Fv90^-<=K%)!%dvHq zj^dL`kCfsxzM|z&m|LzkN1C?jxE>r>KWm1R3}niClpy+#5>Sz=2p#OI*hL4ynO5r_ zgs7;mGp+l?KJUW=)s3!e`g6!C+~;e_eg2&uAchuK^%xaQm&_#Q!6LxVv#IIY^XE;^ zC^_`WU$W_il-%|4%mFJWk-fNGFhmr>pE1%z{0_C{fcF%06!Tu>si0yl$ugkix!`I1 zjq@_k(*;-&_Yit>wXnML(KUx><1LANGY_D%NvffD{XguzXIN9~)-|k1Fb2@5APR=E zQK^aw0RidFibSMJm5%f(AVjJPf?X+6BfSbpF9HgvbV9F+QbJXF|K{?X{p_vpbI#f4 zdcW_wz90LSAdr=;b>H`#bIdWvn0QrFS+e)(yW-#ca5to+-#9^Z9XbNyog>y@_%U^Q z{`mH8EZ?=&|;$h*4)MS9FJs?R$nrpU>UJ!-toxvur= zuowxOqp4oN>r7#1FHtun)_|KqF1u2;$?@_Whr7l1_XG<>bBTCA)<4!KaA*3$@?$JShvtGFT$g>5d09rfOI-iZL=KCsvp?;o%)dnX(CsB z=?>$KsadnO5g_xhxD6;GquGjv&YKVjqF zKJr6BZ`UW46)>>~SnQJKz9oJ6MF~1%F4bHC+WUjt?<`OE!@jze!|uHzbN)Q~(`Hxk z-lgQ~clU=bp%p|fpL^oT^YF0F)wrt`9j0fK{q{Uc`uH?HyH_@dKemtcdEncN&z|U9 zf0*s3k@>QzEM;_KRg&0P2sYSZ1Iz2CUV^g`l8xg}!yFqN^A^LxoEm0tvT101LcxMM z$=s*S+3SaQA#?X-J9C~tjFDBbd)pK%*OxGf?qM$EPcwgcsN>Qklfaa59EUhllR%I}sZ&(|voxOU2iVNEp(<-vFz$=}D_~ zqCc~}67H-r{V@J}A{B#iN!Vm@KagT(rz6{CQu%fYIJr>xHLhw+3&dv+J(+=;9L9gwEy5 zuFXw18h^?SJKd19dhReD=1QFC)k8y168<+I67w!AVQe#W?%>zM}CKv0h0mO)d5(nH3Irdvuq7PBt0 zIEQqsGomyQtLP&_Vov@zL0vPeqZ%X5DA7Z_$GF+~`QzX|W3rt_9$RgSak&X-Wxwq7 z!7`L}W$H_jMh;`DR0jR2bmnf7pc!+5AA?44wPrK*4!y{pst?4?RecZQ#b_pfA0XE> zsq=B8Wh(j*Hx_4G5La(96D~?Tve!R-wCqKOiHt%;TSiW~EbAUr3-^TdfJWiCV|V;{ zrW`mi9f7aYqq{c5wwZ++tXfE1wG${?iff)du<0m>qUTPNY3$O8x!$>g(P~?tHm+gH ziy9ug;p~NoaJdJ>d&FaGx%JCR=!MWU(c_XSQPGys6(hbjY(?dxFM#TxE1)9&VX@s> zE^|d!#atSAY7?$n9SHkN(U7iUHDhBwd)*6U92X8u`0dy`VJ5w3?|ey%$cFGpyChF9 z+}}d=zdFkO>>{tgz>bc+W5<*6OhX2p-E`*k`#|QA(ffRqlILkUj`jHd&j_oIpi**x z!**?6ZeOCwGiJ6vw~@%|fu%E?iAhE#aSm{*hJ#t}TYhypetb27V73Bs3pHgLBc6Db zmg`wbTc0TQ*elRqZX4y+B5<9<+o*0kj#qb32(Db)N_Y4ux+3znUfUK`(o&L4L_-xD zO-z833^ z3TA)7v?PvvX5zToRut^eg%s=lk}lz$>O+p}xD3Vbl-k{|lU~h&+o=Hy7oYhVQhQ-} zG0BD$53h^MYdmM81OU<3$M=i>9)Xht47}qIvvpnqq6Cob073_Y{X7&hXE8Q1Pne;Aq38k2(aBvPjFr;pFCcNhSvB z?8DMn*}N~C#B$2b2a|El^>dqBEKjADKNfO`qB4!!hbkH+YPPX22e8o2%sWzUK#yKa>H$+A=BAVhM8+mwdFi~ix1fe*YZ`Kg-& z*~;>ZkDMDdzow*S1QupqH=A0zFBV?B8n+^nDOQq@dK26w^Bj{yE-i9`YN#>H!5ME( zPVN#{QL=Ki)mUr-J;7!tob1E=$LFv&XljOGy6Fw^pS1uQ!%RtfgW0NK*(IBZgwlm1QgUt`yKB<|E`&p)F-ob(+!rvO{E8&??7MD{lcwm3L_pZGp-zUx~o6B#Y3W}xhz-0UwAwx z#*7K0-@bnQ>1T{=Q(k8Alo(5B`gn#N+WF-rhT|~<;YiDd`TfPn9>%QX@p9m=l15}P z-}GKx^Y?6Dgm>++I0(zU=@mIse}L6DN`EwbG%Td}c0!}Ktm13W()-LeV<#zY8ek_i zIigu^yTZ@=QojFWyO~mt8kZ-EZB#NYFr%C@CVF4?Wlacf93?-xpCKhC%Nq`>t`$sf zC``u@ZrnbX;Dd##+!*GO%+ry%Uyofv&5ITOvZG}wQS{5vTAttDF)fHJK^y#aP39)| z1Nl!ocnM|sd2!QH&`T0oAw5_E7GgK{k65%D>#O^EICLt)QvE-Wpu+o%j9NDw?i%-SP_K zL1#tMh3kF?@N{ZJ$MCf&`JDUT3^Xay?`+$Bg+4+jSt}<2mt1o(HMSQ*)DE{n2|uVA=doO+GSevY%QAdbd@N!RINL@s?F z19eQulI2{yq9N+(=bf^rz#ZCp+f~I8F(=+-E^NBO`BRT}M z?~5-?o9Fpv>-Ns(y7krO5d{))yweFsZn{YSQn%T`d1IalukB2F zYEj0lOPM_@!+sUXk(S<{y_z!kZlio}&m1_2F02UFi!Rr>l}p zFrqDJ@9x`FYz)kw1TZElT(s-!nE}mWQ9kF2e6hLZj~rg0y0Q-bDKn0P%vj}$Xge+D zi61+)YaJ#YF;tjjE7eFebY61#^m=)}U(C)qAUQcw3zG?pc5R<@7A+Z2TSiQ7a9yuhwP;M^(9;P(tIP{vL`k z4J(wAv=Qo!IJ4c92N|@ z?l`vnRw@bYy>{KmJ~gNQ?!2k^;z?Hfx4ZLNOT;R+pNA~Ly@6zQYGtVM)%=U6muJKYrGpz;mN;-QoWCalX#@{U| z%4ereXl|5q^5YV5R_pUUDk^!D!f#5y9MR@q`Ue=cquBZA&II;;HGzFC-7CRGlEo zoyk|8d0pU(C5N7;muO2;RiG~=Yo6zHu#jiN8>r6sF*6o@#cWxEF36-)HaoRi0gN0? zqSf*oYKi1isuftv3nR!PcCulX;O%^`-XRl=W^?B%gt-?;Nh1Z?f zL@Muxs0R0u$25Cl*dH9-ihujk_!2u4lv0ayP(>CjS}{2vz>vMVx1p9py|&$ zI{gCjF8`1^3%->N(vS;LW7$;6J#{)z?1(vW#iJC6feC<%y66TMB?OdGYGdM*sSu@Z z&*%xMce{TSt6{Vs|MaZRDBNQAyE3QQA)xZe2it3J+m-#!<&paBPOzQ15u1+eN5^*V zA|yYa$E zL3?Kgzu2Z-&R+x|{)=sBNYEBRJe{0xpMJnsRPA2f4nE5TlOL2mVKHLPTj{kgEpCtv z^~wz~R*3gAeRC56YlS28_(BkA1dFyOJHVh&kCe-AU!*X}O(P9#Ug;hWF$#dqdEATA zU)e^*;FE#9TY1xVy%>fWQ$3@S-n1k0j5AJ~->u3z9JO^f`7%qgn?B`towix{Q`z%x z(p-NgC_iUR$22(wV7aCj7O^(jqeVSdMiDTcL?g$HG6N|vjmviq`CM8O|T_(vZA^nr_-fy zAs#M(CzSEm+jBYXl4bN{On@3Z3{E{DdjddApyg6Rz>NxaD%82t;1rtYI0<%tW7dLw zGU)Cs=J7%Txdb5XMp#eCdpWmDm)RJ4= zY~w9+wVX?PNbapQBrLonF!%-!GNMU}6&br&w(5Gf9i2+|4)|1h?gO6}p6@P!Mhdze@`haRUP6P==e$iej}`O6#9cFvl}kr1P`&)rw8mPztx7jEpQHND3e|Im(QF=p#$4&qBO1Eey(j z+X%5=?RYh|xp&T0o_tvcb`}vJk|cGq+#hk7J!Ojwnh>9K`=1Z%u-YIr3{JqnTbaa7 ziL2yUQOsXTquC$OBYAYJ&4qp%jypLp(}fDyf667ecS3;R!*E3(*MA#m>-zZAY5eDV ziYG2}xd&Ir4Q_LG(tys>KIc(#?PVC8&EXt2H)bK;ZZz&uJ#|ZQy7^2O^9~b8uw1B< zikpzRSk%TclHY_5@g%gUM%>y7hbfpuSTbTTVGEvzbMQiZ5H8nnnr5T?9v{(pjA>1DW2D ze8>Q*H^W-FI}z#Z{GGN~Y4%s}#P3?4e07M;7klzkwd5b?7<}a|52e7NM~0IBeCkh( zy%FVvnMnX9B9KBg>H{(os4Ov0esoj&p!i=}98c_i)L2_*CDAfz1X=pE$d9D7SqQx0 zK;ktSNqN;#!jN=1KCo~yujg9BBw{fzJJKiuBF}g@xCB99LwKX%ty}=z3787htrNSz zeoMLlKEEUAumIBM%zkQ+%0i``Y`D57+62YLHyD%7Gkf*C31niolYZ zO>p!5OD7cCSPt?Yt0a~jRcekqdBERGfbr%XPZ_NS1%Oxel6Z1>9i+`o6O<#F1@G^m zZsAbL)RSn`Ik@(Pvo%v@ zi92MQEcobT4r{Udq(2yx!kkyxB70njL&n*ZQ{|91NJ>P&s7bioPSHb7>o5l&ni%cX zJ^IvV3sp0u?00O`4&ryna_?08`Jflifd?Z#+cwg>``@qRUw_K}7%4(8uM$_glOemb zU=qf9Z=vR@xqbx2tC3*^xANLTpR0b3b&qh4{g5Jw?E}P1lkdknnW)@2VNl&v<_TH^!mT zMcx@2s>!>h%eD_FP2>|igNxbS@l$1)VKvPBAAtjMcM zEC1sY$^L)viQuM&hBTzK~f4Z9!w=_~Y*jd64yy3E0N}>+6F9l9#CoMr0wdS0M{{|LH7oA1oF7 zg+C#euorodTlyP&D(Ao2mw)~cfBu}ik-dg~I&2B|xeG> z^Gix^?11YKJDv#2{t@H<%2(dK(3s*7@9>8OSMbjTM~5sp!lLOD=Q4bvATW8_@rG z&;Il|9aLdqPv}5xojuf`_v0)&$q%m;P_eC;6V0)u^3cy4C=PBZ4^_6%ufS(^ZMKUp6F4k@c*jGX*0pT^8!6l7f3LsQ=46_$513 zbC?@EY3GoC(tcb-#Q|ts+@c+UoIenTKdO&f99-RDMBDDrU#U_5REs}A{xEw;8SsPN zF1{bdT>yd%9Y0n4Clvihc%+5j{Qmi*!=C^45ECHUuSG+$i@*WWA*e^PK zAq+p)z3i^=32P&-S3LaFoBRu9>Mdy(c5A1_dylQY_=P#EKKz=jm zW9`}h_7WHbw7K=XG6ngkCgsOP4lBX)edL&a>hjMRn0GINvAbrVlmJltukKhE@`vJ6 zu)t~}OMjp&#+q;qI^P`eUoKICh2Io7#>w^9IDmh=3m&AoNTr8K-2?xyrvA9dlY{Vl z&o#XMeCC(U;DCI>-okwccl>vs18t1_;Y7jS|Nm?f@0)1ZCQ(G4^(Gj&nSzw#LL)Q- zFT(tNz2R-#@H&rv+0Cgpjb!Hf#&4}7<|6~{hNB2E;9j2S4`-9=pUQ! zKY!K20ee}Dfwr992aB<-X8y;@QGwgD=SK4><6j*l?-}B%W)?U<3Z9=*pcV?5hY(TFnN`gb#qBdhc3XL&4_8YCY&k@5^6F&+oSs zbDcUU5`Dm*sS{M&M1jFGq`n3m#A}jZXIZd37Eb7#whv~;-;>k_tGkoHW4qX4XzVHO z+UNZI04O8(+S468)ueOt+dKQ&u>WF_jWNQ)ER7=M188)Ghw=l|dt#2Pueq;7gTJh= z>_aMhe6d33)<8SZxH_1{4Cdq1%?m;MIjq0bBLarzvYW=UWz*h3n6PaHMt^6RctW^{ ztxdo#Hdc}HBthtYS%Fsmf&3Ng{65nnr?EXhKC%k7@uI*x`mq77?ko1Ib?Z zfe3Ad2;Uwn7^Fh_7gu(1rH>;#i&{ZVhRST{`qG&7SfE&8CQ;a?3;Oxi#|pnZDp;=j z&rkXHlizy|fyeY3ldb{~m%=dr=sVWYUS|yOby>|xaGQ-UgxU5wo8rl5f-hl)E&=Hd_kM#x zIxbV_9tB5a9-!v%%RavM=R@xgVCvVeyze0q^8_Un2e^Ax#g8y0U50ttz4bSJ-BSWT zug$I0k9ItH$?k{HtevKMyVjuD^j?|gdp3~6TM@mvVGuMAD%r_sguuG<-0xMxFtTSB z7d3}RUO0w;NSo3H5W#o&yaz71_qn(4U%sg^D#)z}a@{@t7d&s2wP9 zQ}L`z)5{58JLMnem=$u4EzA#%{(6pa zs_gN>A`-^4pvvq|rRzQxp8&!@rm&-T=uSn8T6YVPc8}%T4opQ`4|D(r8PqNI+Rr|& zUjj|>df;VWQ_s}1b{X(=RfT@ND$I;s8}}s%kh$_i?rS92s7m6-) zcmXF+aRf94FgZOo#bMBh9oXQxnrGGG+*+uDn<1`@ae>XEg9mQcslhF(>DsSDbzkzK z4WWVVqAz9^NraGg@hM2neGRu*1=e#;hZQUkK_#5?l{!)Xi=*zfG94t?unS90_uk7& zR_5&$zSKj`n|EvbcJSs*g=uE#!uOPYz-5P{X{7-c-us(C`RaeQI?(IVW1RpdB^$tG z+XPN{s6QnhfH)6U#43yTHmB2T? zItMb>+JgRs+6(2E6pj|rtdvk1Q`Ax?L`U;s)t+0(&r9ktk@(B&@DXyzT}WJdw%cze zaq^)O>lj|>g_yJDx4Ste$cuQVAt@1~i_4EZ`;UZEr4mK9P$x3%jQPDZxsdGZDRvej z%60908(h&@XMQ4lXu0Qy!@JV2iUydv;;(;hvA$1U5R4f z@Qv)9jic8D%ClvZ5;nk;^A&D1r9m z<8|PD+eUdVXptJNvql$}VI*3vSC6Sj<>StjOsfOj!l%XvQ(c(0uy6Nb35b(ZEb5DhRyrWrOTLKmer z*K)?dxP*e5x86En}m)3u0yXNz`os(8cCCa0 zA8gCIMEf!~yFq)JR%~LzH03N;tXUmjnw8ga9&jx_Q#(6L+VS8)kqFqm-Wapf8rio6qV*^ZHK#H9D2qmB-f)lQ;CQ*GarhX-|L(v1+>NNF8Vxu_H3^_`@FCa*5&M2kGp7m!#IoNU?uV^=yaV1M~7jsDhcXQ?3}j*f5Wa^i^pLS9xghbB2{dDF^yB8 za@Q9pTi%|mT5|!Ma3+BMZ9fjOj%~%Mq; zPJ`ITl>!tzrBqH&vh>dUqourbv5-&or&&>Rq-nqYfE@Yf_m_Oa={yoy+2BLVeqyV5 zRGY?KezABWJBU8x)Y71@kqc={Al#Yo0k74gre#MM92}AHV$cK*N73#(M4#H^Iu9}O zeh-b{zkV>kY(nmPP|Eo?pVRM)ltjk@ODpe$=6)U-v>|UDf|;F5kj@TRIXrvsl;zLQ zX)AT0KKpZD>~LeWE!kTtZI06RG0Diw{`uX#T+G3@Sk=ipuHrJ_H-=* zO*JI73~~S#e;Q;f*l20ixD(?M&BzzvoH6`BZs!T9^|{Ak`0L=&&||xy9KnJ`mst6c)XEJRE^_HR=`R4`yJ`+3AClxs%MU_A;&SN5W=SPAhq(v9Ac9aP zE!tL=X((Cv?-)JZ#&dNf5nL*XfXmv?_ub24r*=+hN6$fWZQoYXfhfSclz_k4vt>95 z>f#iF5W1)A{j(e&ITi2Cv^(2YW<1ZB2AZAD(FvgPm%c@A87_(~@OaGaigCCCz3-5b1L_++z^Wwb|ha+wl4bk=4|$ zMaVmaF+FwzW^MW!-Qv6M`OgdkqA&Mt$hMI$`R=?^tjZ(jFHY)Mx`cG^#~A9 zrP-V7G1*s~A0}k+C}K{J(Z;UdZ6pkKNE^+LQNfJqM`ay`BMy+3M1aie`_b7E0YV*v zWK5P1l9+o1psf}qriClG6+H3?Rgn84h!vm#O8Qr zdH7D8m>&&elH&#(?acYgusAi6!IWsYn#ER#(mN4Ig~|Y3s9E^7K*F?>*`4Bng3~blHE0EO>L3APN)t86G4@76>Gz z&!>kAJHSSxM+d^TeJq`g8*s-ZSvZwKoYYD>5ECyOuuHkzf4Y=#O9lkV>Y)7FC#a9B zV%!rmvxRuprS!_B5l4XjB9NIGmpucJF#RaJq%v2^pbTla2~fet#qNf0$RH-LvK6R5 zLiTNoSo|R(BROYk;>SO2S^*66&W4l!-q6d(%GtQdb=eBQy;PU#nI-f(b?Vn7!f!|gW$MSwR^Z;*9$ZC_Op07 zZw#c{L01!o5YMim;p>WqK3H%lvKDih*q@K{+&5RM7NeMDJ|Oly>&?!{+hyA}9@V8m zg{C+l=almNzGb=-#%K1VSxO~heqY66Ap_2u7 ziR=yh=bth?icC`_g5*~{oEU6H^z}DEsQhW!`PV=EKQi9(MG;`m`e?m1!9x8eO$V^bI&j7OvnblO5Yado@(Spsh^uUYxsMkH zh>Ij5$0HutEVa3ODK%vb)CH@rpZ2K7cXX~;4kpR6`YZHpWPuw8Btcav~$gO3sOq2Cd|f^KEDKKhYXi>;bI;`Pdzx_IeVdqO1Kg?C6#~iFz!3aprcM8owt#-|40SvPWjN6KE@dA<(QL5-Z|J)!{ z0hH?NQ!~pbnb!vN0WDA@K4L`a(=iKiXPirc5sYPtGQgdY(D^w;OAyk7Y0r#D&J+z5 zx$Nr+)*!XOEp)~M%u*8EW`|Sus0Iq64FMQa?2y>+6F1!g*_}Dm?Ry>hD|VptMn$!< zsBw?NN+D7vz}Bp|*lB^&|Lqd-ls_-mN@Oo&@RPO!h$274RMsN4ADQL9e&T-u=pNVr z@YQmZ+1dk!nPLJ004918Cgz-?)(Jj3)-e?W8w(=h>D7VSd6sRwj?D^8UCqzQ`<3bQ zuP{6V%}o?%QdC}|o4cC*?0o;^`RTrmxu_qlu?NU>_LuhgLGxcSuyX;@$F_5n0Ay(& zyH(k_Gs{p>X3IOZFL4dk6!N&hcAV1#9I9VRV4{?Yf#D^VAEpR{#;r0ungAJ4%1S9^ z(}irkVA)0y3esR7w2uO*=lT;54fPBiEdx7Wu@ydsPjHL~L#&NMS|g8L>Rfw5nEj3$ zRnv)oD8AZQ3bPQ^y>JlQocxrk7_G5IA&c4fGaBZvZ0f8c zBg9_w`NcQ1?x5hsYiB!@Wi*3nn*E)C8m&%J7hbUy?+ucfj zUblPQr{)ns8psecAtCu8H}v4)XF6GM%o4Z&p`_Hv&XyrOZsv*4xwtn$kO#64i|{?v zdeZ1y`2nO}m|VGYOzTf#gj^LGKWCIKXp0ByP0o-1y{wVz%w>)yP89GpH`Q8)^`vr$`bWrw-CJ2$t6i+r&QN z4Ef<{O?%LWiH$7rl|dtZ0AYe=%69Wl64<E%4_cW zupv_={a_3?eQJ+0rDMLunJ)=xa|{CrcRw{@I;_mL;xbI=W9FNt^|R#HFTRlUEEp~F+^6Y7ixqGRQBMyW2iBk^dX8M)nNAyy* zQ2r54tsE`kePl!8#KuDk~HYJ7|+u z5VW-a6@t&2zP+=%-|2}6=GACZtgnXi!bDdry{|3`FAD-qh4eCZvul|!kM){VnruG} z^4aS_C5x8Wg9n{0$VmiyPG>hhWE!UB2vq3Z++En8QI$8!haP-{yT~OmncFIxS&bO| zcE6I$bubtPJW0;iq!H8|1@?;&YDU0OE)vVO$@uqT|O9Cjy-?Ar=C`8JPZQ* z;}^NyNoHpO{|UT$bEv-xFz)H`kWtoqUT*S&kyu1j(T$T~h`p|>wA=D)Cg+n0jtRj8t8h!uT z(_Z1KN^I{*qUWL)5@>?=2@*gK-WJi*2>~r*D%V8Ck03Xv-h1a7DkIbvX1tpqnV7C6 zH-RxO+gt*v1lm)e3R9W_Co0A|CLd|YAO`O=7v&EyUPn&A3Omhh=TRKgEV9>M;)C54 zWVU#JhJ-5ihG*9=V;Rz37(jG<-r_$mLixdVTOX$3NQ0`uF8ZO_#_#t)SQ+ulhznVv zbf(3v)+1m|YDbx;2MaegpWV0`$;n_3Gvyd}=(^&e@h4QoHFgfxRvX_atCJzfkw|HU z00dhCN~$rU9!g$^0oz2ivP#WTlY^Nz|C6eb0Q-^eYd zGH${0-#+MY$I}M;f=xL6xT!?lEV8I_)18R-U)O`))PB?fKSqD80np{@kCTsFfsU9% zD=6?~>cxqie0VWyv@kg866(A?4aXr2;{mYQrgz`TdfraET*`fekss510~S+B*WEfN z8^Zw;+jlry%wE62b`KCpvVP;M2eHIer1*`7M5`M}j7ZwihZiG{18YI9qqPn)vCdC|GRB z@y)D5!*ya*6{TMH2?I^>CbKVyjuyC195;c*nMcseI&l(UCBn;NRR5$;SkeFd_6$a_ zweygcMtV6rGo0y$l`N~91lUnHOf-wyL_$}$Dj>Mfq84 zr}~PSa<7uIx(v|1>M-AJUIaPl@JE4i^3}{*mUgr8zkYp=mjWwQ}qV|zmYWo=MQJ@EmIDp)9_yIvv zzo_eHuei9U_aPBb|!7@fu5InKVZWK^Pv_@H?VZ7XZDp~d-dyR zT7_b(!;lgs88$`TJ|ridg|yp^6k{Qjh#-;(Wg<1P`Xl5*<~qKYGG%w%cnqV0h}Pki zbnQ0rtHF0(gNv)Jwk^4!ae)2uEHpBVCWXYhAq}br8CgrAY*olHUU%~Gsi$SpZ(Aqr z-R(E{ZHC7C9x~Ww@8ELhXXe?1?No)VelZ~{(2&+j$`vD)uTWBBKUSJjbii)VOcJ6; z!8;g&Eph`Cq;wg|shr4M24<0=z^dBYaAC`?Mp|Yom4W(XcpjArzZ` zpSUp_JzPmEa4#a-Du7lIwy;Rr804{XsoTY6l;~wuZaX{c?AnK7KzdXaUG}XYC3hTT z`hz0a=wwI#fvH`F{!mgsFeyF{Gnpt7GM_KRdo;`RWZB(|JNUfaqB+h#Op55$OK}{o zyX(=8P0Mwe)OP%Qmy5>Qi1vDYD@$ARd=dy7)UAPPe$Bl>;BL|F+KV>6 z0&nS_Lyq9jV7B+^-EbIDpWvHQC;8lFbe30-N!w)A*OaJNZSodtxc!vHrhp@ZT$5Sn1L2r2b!{Br%Ocn zS0N6qK%t5H)|fZ#ys5ev#rP$44~WBse5c#j*VJtLVp*j_>bkd^dYFUemfCgdRY&}aVpY#+jeH>ja{^d zo9^H()8+wK4num`>5t~xP^{E)jJ@Yz6GUr)?K=|V`_is?_5qh9n7QdG2mtonXLbpO z@+4wsnJ8GB88M$kx--Jsae<(vIC!OeTs zp!M4CS^)N+cHZ^D3Rym9UM?I`s}jNA@&q9Nf}K+yP(H#DtX4b^(BtN*kM&KX2Hp4h zETwNiZqsGtIO~&XNxlKzXKp#*&vVUJL`eG?Mh4AFZ;P!(Boq#Cnce>7cDk`6JRQWM zvtVY6lxNVsqji9`MQ6>XQBr*E0IC_HQh9BK(C|QH4 z78C)tA?Qm(9|#aw>=t8`^iq)6hx_|aRQ4}A&j!KjE{i&Wu!(F``^UHKI&A>J&)18$ zOPd!55zMphx4!EgBX1a;sXHX534dozZTmZ9-X9G{%lOtyKMY!;MDqfPO90~itiISjn$_G>^|-V=__hZ z!kxed>4F-M^`i+$gcEvrYv zfwb0K{K~|Rq)rn;++?<;oAkIk;Y6xntG8G+;xvylzfxuMW6 zB$In~A7|kgQ+ICY7^PIic|>8h+pPb^b6 z;{0v``OnZmiRVC?mLQAY!F>TSw|4s9^?T}s;$WDE!n9@ffdA9c!uuY>yIs-@W4ER} zN0u!QyE`Jp%P!rzk?l5Xy1E*}K5Rf3&8fsyo`Z&V7CS?}mmvt$CG6hU>xpO&4@80G zSz*0ahM_Z`vs!6=0G>a(cchio={CgEQn*rHkF>SYkBh=pt|rSb|p==uX!< z0nH;}MG2+4#V3U0=^na$pp)T37%=nYTg;9di~JMTmS%eRk5iBOpa zS7NUCtOD68l3?`SSV0PFX`URA!dqdT24PLupdY}8JvP;BPBG`+`(TkqEa_p74uP{y z(sN}$-ikj75lKcG{Ie-Mrz?Vm@P)3UI3u8sMj9D8qfjg7S74#c4-Ct^3pE)_pOS0*aT)Z<7W27{<5%->x&nOz8eCo|)=exBRKLkaw>^7Api^)LC5!tZi@$2uLc|qc`HNCzupTZd@jh zf6a@P9>`i<$4n!=VEWD^?bj*I8}kRe!1kdY!SE~h{(#-!&kGEKcXKLszS)*9wV7He zj&u=}#V3V|qtY1O%mDVhlKQUX64WZf+MUy{K#x|OjV|Pl=o=|6pXiIkNXRvGaf_bq zBRRl@7q*j)mMUEJmD2J2A;l?7u9Rvlwf#p@Tn6B;v*gjMc|sVS_St>@!J{Jb$Om^1 ziJRot%zD$4=Rs=p_lf|qWTR*!1n-RU4RQTc>7Nn4s10c{Y0%1ZW9{%mEeHd-nTQA6 zP0;4r=<8lw385?=T{?I!8s&Mrs(}RbixU-{_ADkeKR@}O3k_%({;@7l(3Mu%qH^MB zzXjlXniDPO1@K5W%#dD)v;=S%Sva9BNe2|s=GEUjVJpGA!~*e(vE8(^OWghHGEarU zR=lZmut!^y8;B*j_~C+odwKj8P*=JhKIoNf!+wX3xv-4{URWIBU*EMJ6=l*~67}L& z-ckTMUF47ATg0adh9*X>EbGPs6~DA_8}l0WG`T~Wkw-8y3vO|O9)1^%uZ<_ZMg4)V zqPr@hD@_v(0oO6Lnng9K6Gk z`vR<_7J2E1oXvL27pBXQ~~4B{r7{#Loz(n&v0n1-xy9^&=#tvB2z!-6PrcNllpt3Q6FE0#$>yzi41G@rKt5L6v~B%yKPVpJ zE6*Yln{Of#S4tMNJpq;bp{2M@qfgjU)#wtw+vzJ%qfan@I&)YH>!Zkg*+@kLp$qRl zt(4Edl=5(dtkT99d@cTZf-KfY^%J9a9a81HIWGKC<*R&0ox6`=$6rs$SUKq%!zH-zG#6?3Fff82&u)&EQ9`iV))ULjFz`kt{ievP2vGe#ovF@9_ zin6BMXIvrZDtc2_Am`;kNJb4HACr9_7X*U7ZvffmI3(}7l_@KAlnqbA3|H9KlV(nE z9G&R7=nCsODr5RpUi|7jD5C8sRoBjV1c5vw-fJ7vQSG@+M$R>jM&mh8Nzkj>)2^-w z)Y8(u$6RSIgWQ+!|HIyw$JM;GZy%Jll0pN`n-dyDq*9s<4H{I^OoockprWWW2`Pz+ zW;ALZB+(!W(VPZSkpuP8Zt#z+^yzc9E$Y{n~3+OZ%~`Fr#_BT7C$?Idw}G`O1a6G4FiL_jCKDrjn24Srw)v!&RhfTsFheEma#-u z!B@t@_r{IS86VR)EQdZJd(g7FZSVCG29}K@jL*7v&Y&yc3{PT%=)i}{wWWXOj3xkr z(X74dQ?-NQ_0gy|`amX|B>3EW*Cy(`gk4>of4ioeB*saYvrNBf`&N)sc0I4gn9NF; zOwNULeT|w!&j|(@)xs;lqWT#K^?YGGd=TlPsfTTDiW=Krj?bE^JrQfDqsYeIuwrB1 z2Wogymb}ivGqr}-_9pK-Kifo9TeNl&djQ?K(Ueh}ON#=u-B{0kWl=v@xMx;bnQlq* zar#Du@eS23N8WK%bXB#=o)|V>{jM+P#c1Dgr!M*U4= zw>78un}KVMIPjKh#!Na2tAOIkU;g16PhYfPW$J9zxVx>AfrLvU<0l)?RP!3<*=)&4 z)Wmnkv8?4g@>IO#SO^+x_zPa3mgaw)v~Xp!9ARf~=aE=Wp}HxOz5;(X-5Py0{^70s zXEoYqhsd{v$(uGOYRAaDqEGhFQ=)WxAM5tM&Kxp?3G;?QVM8lTx@X<)vS7@yst$xC z2-q6jO<-|Iu+@L^1XZpuw>x?=w!#z(Ks^EpcBP-A+xuy^w=74Z%LIHP<-T3N-|s$h=d#3pU4ndZaq`aSR_X?_ zTZW9kvUEH06=D}w$SIB1jm_;Qn*G-kZr7<)b-O)7&eJW^9TvGxMt;06N7Z7U2d49M z!Z$zcu%A?2@Ioo~ulM;a`{zhC9J5D%wEg6G@suoPb?|l)Ys&kv-?G*xJG94)SR__(^hpsrZy z&5U9fx9(m@Vwmqjg5PJBS2cg0Hze(A9*HWDk-#7(nHaeW$!c{bj1-_C-Dh~{=CkaY zKy`ZR8-JrqkjLfUUZ^qV5K!IHLjK~_@mVo3Y;-|*0V{? z+8h_;HDtRB@uJX9hp5l=SDx)RbU=K{7>abD);6M+cJ#tv6 z2`m=zEc*o{WP9$I3VAz55 zht=@CqHFdo_bNm(A{WQ8xH9KdVqqk|` zR`IvAHrILvf9^r;_FbVogV~u%6y&r|BdCypz^a^47;mY*c9q3jEa&N(76#$Zw(7(W zUE)?FwyN9YT%F%%T`^?+-?1N_eFx83M4i(CIfS*=&wqwaVa zsa93Nd<2!l zGi-LNF%#_=N^g4rKMf3!e7@qi=Df7{OH+J_PKoV_Lu;>it=F|v8f!6a$j)T>k~no3 zC`Q5KtO~q|E_%mGVwJqF0bt-SbEtL_z^RJX`eO088s8z?dELcZge3Naw*Uy1+) zT;gW4L)eS8=hJ$s&Nc`fdza*58i8v#t(ZnfZFuCI&peaPSaBE1#KyZ0sL-g?zq_OY zHJj<^sQOmd53HfQLfyZ*=!>A-<#t#AX*5q|+m0F6J;2!B$EUWovwbP!-1z|6oSSip z)^>NY3Z1*}N3jSn#pPM^MjnTkCda08ps;CA;(|&(c_lqloYYsMNHt+UdnO*NV)veTvmZvviIkvW3>kjD0*}hi? zZKzV`NyRdHtS_?FhsLn#%$n)NdSKVWmosO~)MTV6TL(Yf^b@8R+de6Xq>qfkY^*J_ z&9%1-7%syt*+VlXWH>`h)WSt7jf_cIt@GjeRcQwnmI@P2|^K8grhcbEX%_} z5u20)c)(+F=;rqQP7sGu%x~aF-cY2x0O+rrogLR+?_>Zb;~WTX<8yLO6ME2A63Cm& zdzI%?ukQP8VGOrUx-_)`OIB6m^{k*!l#|Zo7|}Q#v3U@QhDP@S?wNEwxKv5D*G~Pd z{Cw}Lcotw+dtCKsoglv-3ea!Xw~I_hx#868bI06#|gu-sj1NO3%t3 z4mO`4W!Ch&gB4$q6v~l*BAT<6$EjgkZL!DH?sJ$TYDuMorP%rk!F<&iXF&1#uLI{j zcrZM`X`90F~I(vk>ESNC{u)Q+_ck;57wWX#gK3>1-r7VZ-I;p5R2V0x`!Er5(WPZP&-`{fMjmX>iXNuX?gwIhngh|Nu>*p@$MA1Ru z_=>`-HvT4LhN|KI_zT+D!v{Io`OPpO8tCP7z@df5hz$43^Q!`|x>kVtrA3 zdlQ!3gl^9;aTIfBKeSF3@FA)IfqA~_$jzjEz_W@UZq1i@iOor>k3DlyPiws(DNrvn z&fj=aQ4i}6ud@%J6(|W&+$sysn{Z32!~WqC7&((-wv1@`VJO)DM=w%x1Yd`XiUaZaVAKXja> zTb*C3p51*Yeh#FKc8hDtSX-YXMo=rlF<5y?9@OWx$%5W=|Dmhp`oQKc0>((ye&uK@ zeC9HjQKjc2@SN5+V)o>06#?Dm`=l8fL(R?KMvfFiZaa%7dyBK-nBP9TV`d16BV3NG zr7?PnFYw!%;gK3%Y;UgO7()ddk^=MVwr;&9;xHbrUxaBkmF8%^zmXSQ+g11$94BC}1 z?%Ce^S~w*&I4uVl$1Aps$51_Rj$=8Mcw8EBLC&tT=ysGy&wqXPG912}p$E)o(iP2T z_37B+NqfUY3m{&br0TtCe@&yDe)zAXmGCy6wN!^QDnFW|C!j10u+x)LmOA_Ws-@Rv zFM&~~GAR-S`BJ&&=+b$Z#}aue0IONm2vl!hzGG2p=}u-w33%bV{3H#pcu`Ny(6yKR_*7A3ttc_Wc3;bG%U!%nn_CY( zYbC~wsu{^~irzp4TRntBvF=fCo$sN%mSw&5(34-`r-ho0qi-!oe$se@XFQc+F|c=N ziDIlE+=bk@^eh^+9czH!HuO{#tok`8fvjkk1zsbX+7Nu`mOdgn$9PW)a_8rPNtc4G zU*1_onyB-d_g>V@uJOTO9Wf@wW6-p{x%Sz|aJMr*e7Tf%i=Y^f_x`3rtx?bFw7h$KQ-uSKf9B# zdw@K3QB*V?MYIU7D7#gEkwz>+%^?&T{cU%S{QOpQc#!M!Zn;G=(h+YoeF>&o25mRy zQBldSjL`PVj{!bnAMM)ix)A%x@opYAux0^v!C3j(Wg0oq>BVmkxcR;0|K2##NYMY- zlS~0TGSh+sS9-lzPt838c!^Y!tVO90n$%8sH|Z0Vq4)whm72WaCkJTH-3k7YHShQ? zcAAIyM-8p`g)H`=dos(knSPBd`$3&4jI!UKX)Z_}I#&*lbI7(j^)k)I-dKgB9y`8^ z{$G5Q6AnxNp$9%nwGSCrvb3fa&)_98K=TrCoKfWwnMSmGY^ZxQc?Xe&q#0P(y38|&X*G|q7(V{>n`J*|*QO88 z_zEPi=iq7llOGX6c1f7{2c;beOTT-ZUp&Lf^DKPve%Vhi;TKO!a-y@%*A_71OLRI} zeT_45BBBbjb!kM}T8;={wYlM(pBFV9UhKg$drlu6-lI9wg5^t&Xi=*p%{J>SBvQPa z`z77azje)Ayme)X&1Otzt}Lma-j?UYS<1`VVW3VU^l4k5S$kWUM9BI7i;q>l7baf{e!Fk5Q8muP z73#G2?F%^_x#JdsG~4x$t59^BzHer%%1*77)BC{A0kN>KtEb6QDQc2X=gc9;h5zEM z*W#@uW@RikqsJHRX(_js#nC;lGB*;U+1Ok@oKBk6s#G7E?fOT-Od_Y(lh34_6nMvo z>_coR-dlL?VHp}ZOqxUPRaU@Zub+Qw>r;4Z%Z_!|Q^=R@>1{bgq~b-3h=}0#`{~(8 z4*pA@Z^+*t;Qv^~Gn^hIoQS%V2-ydHL%g@|JSUu`<}<8=YcA)Gf(AcruazcXfU@ z%^G8u;jJ4UNEXcb7jL~7ZyoO0bS|BINu1u6T%ryRS!JYNqB%O_^EjQx98QCuigAA1 zQhjoIPObFN_b*e)KImBBz1e3=@zTg)gAd+1ym_;f63t1_Y~1(9PhKpcg127#DZF+& z`QkXeEqO#LKJk^+AE}d}OD`Jhab;>jHQ_qibH4O!{|oj0mkw)5@Is`t-iUJU`xQm>Yw;_Iqn2w# z+)3wN(MTG1^2Q4IYG=Q)Uv@40(&$fcC0Dw^m=uWKlE!44wB>~4r1Smt^HrfENb;1S zl+wYF*!k!?R$VN zw@3HR127i$w%W+tMr&+N!O(FRV0x_{g4lny2TdSIvvo8IGGC(AgtS=7cXgYD!K1c&C|emwxN^oo)hb;VLjXxxec4YM7k8q8@ErOE z9}@5tFsRk(0gJ?!fOC?I(3zmvYUKo)UE{5h(&Dm{kG0(wkoshlecfXKe-;C$8VKqD z`H17-K?S20_XB_{7oq&*CW=DBm$A6xPv6O*ewVX;3N_0IKuSk{1MQT?uXm8-v+8W% z-Zg`r6bN`+-(US=EC-B}I0zGQ!sj>B(?o=Szo|EbA;dBhKedft@&*)o^#H5K;0>7!QmdQ*OD%z@Bx$)Z{`#n2h<-)fO# z^pL%9EKH%0YDollF#zjYOE3wisIYvS*L?v=@6w zwxJNsi{kldbm2enW|6=A>_gT=zS`SI-dVR7xtTiFZZa}MjqGthiqz-PTDXBpv>BZv z*|+tAO3|*(4q(!8Lj7Eea`_@z=Yym^_@sQRN62hyAO6qig`>jbSgY!2@%?piebqa5 zx`hO|fk9~#<96%AfYX{PefwEWwT5V_awnzhjLL>VLA}%4`PX^S-?K?m>t2G6BN%X$ z=BLcQ^CTLbmA+`wQwjUzzXjua1lLW?Qn&81U}f(m*Z0MrYYm<+&dLn-^uH-V|b1R((f0)3EW{lxn-@I&9F^&A<_$Bz}qL^XFPpDl{6I z9VH7L>igjRMW3Vk9{{hGTYdE)~vNv8VPECC+^A9qKayOl~ST(K;izobknTpe}~ z7;l1B8$cy+%N^$r*?BIkrErP3NK-ubhba)}l$UtU%31Bprfx^r#}08yQC|5h)H)4q zB1`V?S4bisdLLJmiz*O|6Df#XXgq$OS!!>XhBvDi(2mXE)Tp?#?;WxCt**UkS-|aB zW-v<{`>4aWI~h-#N&b6%Elm78uVz6#%(lK~Hw`4XNoqUJBaKls;-&b6)KJ&IDBnB@ zyxT&snjGkJ82U{z>fV3Zbi2lowbYl>d{OcE%l;l;ZV8EDuy?*bx3=n$SiDpGm-t`? z>NI8oIMwATHhmeO(3Asb1qT?^wh;E?O*v)E%7pZBYn04Qt$ZbM>y~@)*cK80AvLR< zYoKHn%ibMWJ`tDZgE^HIuHUNn7xX($5kVph^UQfhm&odW_iX=u(SLeq!lV@H&=|iK ztAA#aKMW~>FJwys?W0E+-ejx1S#eKtRXf*h2M;O-G1&wT34Y+JYu&GBQx5_c zGVpkL%mYw5a7~TIOc|YPs<{X3QqCt|5D`6u3R#5VEN5{S9H$;%y}E>Qm5NT@KbQ26 z-z1ST;js8929z>ryK8{6iUWfHZS-b=na&<13c)GPq(l2lnC~pYbX@C_ar%O!Y2GFP6-Zn`wD=(oFM_Pjq% zpINGP^=B*CaKLv7ghgz}LQ1q2KB0Mz>npcs!5h2OGIi4w0K_>)#$aWv9& z{0}Ywa+dD1NlE%AN)+XrZLi@X!ci$lTL1^~l!=PcU0n)$WnvpiTum)B#-~n#3HTg1 z)7TFU3i#;TlX(NUbEc+GSU|VPPava&=&$7~%Z5*isR(CAyH+qOAA5h*Z}+q9J65L0 zd)JkmB2J|4du75mbI#1UMX=7T5Adjgi1vwPDXXS>q4`du{dp5Cz-!{vlXJGgZ8fb} z|C7FS=;7(x>hV*zby;3kZG^Qbh3Z5)8+g!|VbqT938`sg0Z%#SGw@PN$cg3ST4iT? zqNVo%Tn=ttS?8zeiN!G0b%fK65ApD6z$g>z(VCz&&12_2@wIOPv3_98w?3;D`^hG7 zws4};ZHKcf&}k1rof2MI3;1YiI`-a?n7#AhuN1Sn1wQC9K$1BTfmc+uLl_nj7_ESx z{xFpP*Jl~-A-svjm@)$>+fOKK@;84#)S#n(s@Nv!x)9!7oE9cpXmXrf4UgsEIkZJ@ z!r++KaB>5X*x2XPKGt~abyM-A6KJqk$yQHQc(W2z5nzzJ2->|Rp0waFX{#zxTu77V zYtS4863pWEmR`&<;US(k08_b1+7?U%%~Tb^sQeWK2d}{)>e7n!Z)(Tjsx5x=c(Xl% zDn#^Dl^K-`?aSCd3xnUuXVzb5i~eT0Z?VL+}N&?V3aldTwRZAS?+{FvJRU*5!H9`>+ZW&t(VGfNfZziv=*^2vBN!JiX zqjf{oNp`020}}?-F+Gh@P#{g6$3U)g9rKfFf%BTs_0EV_qL7}b#j7j^^{kemm z8;)TYNKl`;bHCfDB5>eaT|%beW7dKsCVafva5jya%@xA29y)M`!zByyK7R|(eCVjd zjUIly&ZjXqL~PKoi?;}_E4p6p&d0Sr5%+0#{OC-Qwv<#ID?VTN6G~T&&8s4WXG{2 z3}Ze^!O?y`03Mx)HEoH(L!<;hS}X6^>cRmUW_ z#Or|wG&H_xh;$`~f7)X$1Tb2KK&$m!AcFHV0#LF5H!1Uh8s~wMc(G}gHK$!b*hNQ4 zarmqT*6q>wrBh2A7QczOsLnto?VFOwST^qqGusWO=Y!U2;$Vm;ph%AMa>IsCqhxR0 zlN6rX(t*CJb9=)p&{39SD?A<}qA}7AV)Wgn=$4^ZW^9p$9`ZlJK==GCR+^Ws*QiGG zuxV;osm=2M!QxOho(&*`mYIbng~@=TcGJXHGqsRNYcB)w-Xfxv0nN0Wk!EJT$P?WF zx#l^u=1B{namg&h{Abfy6w&n%8;vT5ZJUj6c(GPk=u(u&Vy%RkVN}L^nUz!zi2(V? z*Q|gzemCN?t$M36;}}k606Y7&CnbZU*?Iq=PjHM2v{*}lfxeZi+i<&|&BqQSnK+yX z0T!mx-d8dqK*3PwC&n}mQtV9vQCTT#!TS%&?uY+Uya|wr{ucLSM&%XE@+;mQUO}O< z;3<(#)N6}xa}o4rCHfr1c)JSM;Yg&wByX4@zkS0<>k$&Nm*Z5p?-u3m0Fv$Na_sbd zu>&un$wAz*GMJ8!{`|ma1RecNE_3G3U239aVo5K@jm}k+SKK4;y9lgT*G^fuTiR@= zPBL)yglq|YjLA8X7~S)LBGx#+*;|Xt@eJr+9p0&UNeb1MI~D9zzGEHtymLA? zJQeVzfKfh;qVmXl!P$AtJa62%^K&<*fX0Ch6x2H6mSbJF5gzz|o)Dm45{Y4hSs-S8 zyIuTuaH##q4i6~diHuF%7X*BCnI9f9!U{~<XPk|i}>KlfzdTSS^-#2et$ z^A>;mVC(<6&KtH`))})0uJy!+nV-$t^N{0RJOgQvB92j`;hq3PFr{{a3hzAVXqPj2 zla9aL0NBP?_VNOFE-Tr*%R9CIKuTKZmlz<*pN6j!A;fOvCiHwEJi-T2Oxon;szdB! zAj%fy^JM#iK5PpUGn;NkDu2Q)hD0^#%G_vtWNa1 zOlsGz^yNL6Tf6zfSi((Yai*Sr{0v_?a9^m=GBFGwxb^|58*Zdzob5lJR5Y1ySkrH6 za+{_12YhM>sg|f6Izp3L_-9R=whhwZXhp8(5Rc%o#U&mWDhZ(Yn> z+9x*jN5tG}=p{)wIB>S&CtTl8!I+&(jCK{SW4Oq9lVI!X3O}GZ;sRfhZ4xmp0}mA@ z#X)~)-0y(#7;92UZvYmxdByo7ssl%wvpbx7DA!{nIh%3mq# zAQMSHoxp^XmhO`?X1$K}o_BWWle>zb@2a>=zudQ*gb+-kAmKijUw(t@aG#OwWtcJ% z3;`KaoqBa3Y1+L+tBC5WSbgGSX40?T+v!$puZRmuwgc zA}WS7&kCMgapDOaye}F?v-QTl#Ij~FbNmaGoBs6ae4?kG=xjr|tzZLcbC>1aTpQQe zhH2@VF={{3h{xd3KYHi(`!}JKrw|RLAbPL^g@^s0W{h7OkYeb*_cdm6DDgtMsm>L! zz{h2tlyElJoyrXz>X<6MgebBM)FEdRu$w|WyTGNHKBD8!=Mz-QLArykdF){jlCVI( z&Hx(Uq#EPQ-S*>IzQWnxf}7QI^N9#)m6C>vUs@O%nmdWo>@^DSib4bT2|`y%n*W5J zE?Fg#maEILA;?@q<3NNuuCqo;&bNFpTKN}1SA#HvgwzJh-z)(zT%nj`W*w0Rd%x3N z=OfgP=_3~tg5xuAu8^ToS+VO#-ca+7#mXP`6^(mFqnZ`h5i6!5w;N_m^?^&Q()y!( z);g|o86y2*J@-4P&$Ljy@gfq*Db3e7ZW}JLV!owZ(R@R zmK{Y_^6M)W4@1*&L~q&0HRhq(RP`3L`#bHwA;WbR!<3iSF~sV%>`#o^jatOY^hCe6 z7s-@{aNorTv&uNKV68Zt>c5iY6!KjRMrJN>%1s{eS7;w0SE&}IE0XP*|77JYQ^}+5 za`dc(@{I%!)43J!0309cZ!f-VLnu;EZsK^yB(nm0`C%tU8<9E9ouE%YM>@(#%z_l3 z@G14H^MqQdtI)_0i1Ak<>MCXjkhPKCfld{QRb85UqS-A zW<=WlpB+62tBU0X;rd10@5GL(9(O}Qd+$BwZdW{bayK~Kme4PbbKClA4z5P(!rd22 zIY5{ktvaP-PFjy*&XbO&{ms`fVetROoe3)t@DaQh$v33U(vhg>a{wpl*FpFc9wK*E zRAQpeZxD@voD<#J9u<6E)v`#w30A=+5Zxv4EZ&&}p%`l-Xd5gyqyX9iQoK4_K>7=h z>wqsQ?7ZWlEBitpr^oyCfz>dWG{N}ib$2i*d{sgyJ8#oV#BF?F8+CIw$2}6R_x=Wp zX0-ubYi0MpC8MZ#{``hZ)JiA#Y2|pFD`MHFx%6|jw=7PWluE2i!ZXj`1>?C8%U+3gP>uCV{mqyhIs--9Lf zADs!>%b7GCk$q)SHrzO}fsX2wV#%sp)HhUe!u6B9TthUUvF(jGhGxB*dyu@ab%YvZ z4>FCL!iIt-w(l_89{G+z=%9r+CY5S;qLAp%wji^1Gj|!l75-x&7?yD#f6>nIZd8eJ zE9erLu7QcbXuE62B&bB51adj%^7&(n4WkLkUR^W0a3wt54Kxv_UIWptxX z@W_i&@nW4Lj?=D;ea8a?-#zPiQB;DBxs{}yfHtY>s(QCHByY=ZI<}K$=c>=%gLWiE zN0jT}6V0Lo0bkHRyxa84rURx0ji+$Zikn7NI=ZehFI=ugXt3_IwPL8$ejfV=^EVX= z_;{5naW7mk#cRFi$t_bFk5fR09X4jWh1AcMVMsROEKzz^YeSzyw5)?F;BImn7fE2Z z2`ggMBx!Y4K7TWgJ0bSunv=$U~;icKHnYttQt$$|5vjKT)Du4~2&cm@X`oXfZIO;2L8qR!cQVqnw$5z%7; z^sH|LeTCk5&T}zy)l`~8%HrEX_)ch1e__%?rjYOmW2Urn9E)pM7%t^n-DX8|LXS); zSJ9PjxPhFWY~7P}Zj$m4?|?&>yJ+F$ zDFo~zbK+W~Jnd2Wa7sj1e2MVbqXDyv}h0mb?`H zEkAP2mfqi{i?X0n*D-}Kj=#pBks}=XIt9a|_zEkolPeX55QsI_C|05KPZvUNG)e z%33il!R8fIp1hH@6jq#rh-BgIqSNHe{^v*wp6m<%qG(>tv zQ}PU{)hPt9*^%Mm?C%12Pe25TgDK&BTZ?Qu&Xo%jA=IOKM<2sU;vvaVcP`WfjuNy) zfn)cA;<0BLXU9k&1nf!V>$^j{U}VmNs`hFUDkh1q;c}QcN6%y(1`z7Cv5e|S#N^T| zUW{be#M5s?h1V{-B6vq1$>s_V_s?2Lqng4$P*4c?qYwV|28H*ienrWF80N{bLpIp$ z=g$L;R?+Ns?rdymngwSnZG+rD%6?J;iHF~>+O9+ikYkO0&&{N=qQBmdqRe$2q&}qh zLm(de3$DGnI&;&e7A4n3#QbP-dMc-Es2Tu%b=E95y>2 zDuD#eX~h!yu@ce(w)L$|bpk#TjfABGMpUiPqFyfXc(n%OYSmt~E-xmr6(2vN)EanU z>6Xo|D^~@ytOT_V@vJt3?>$Eh75D&Bh9J;B85JJHp|xNxyp|4bfelGlttTq){SgFj zbAwA=4)4nphKiuJCMMn~RBHo2rt~T{fVi)FxGitfD2*CnawX0lvd-FM3J>o>sk6ot z^!_g`T%MFG?@2ns+pg&*9R`;(Mx*@Gg`kP~1!1r)9vg{OsA^zF$*9Vh&{u&FG#hi8 zcUe%n+`<`^RK4}VELM30B$Z`^pJ-mrAbLR`z-#31R(aeNk9y>Q|IUeP$1>&3ilHi( zek%>}VP9!LfZGCB=gLEM@9mLRgDO#N$IE-MD^F?efgh8%gM?r;O=%3!MFbaSlVes5UJADETkN#D(3R|K3j!c-E&M# ziI5U8ua{3l_*XUx5{UWJB^6w}k!F;g{A~j0sbngB793{I5AeS(_^xIH`&b-{d_SrQ zn{NJYmSF?RC7(Lbh9cWZLXG`J4UkX$+Y(Bi*EygL{Sa6TjTGY#1E9ukQtjWF7+iWl zFUZbBxO>C~d!C-#hF1s`Mn?e@+!*%@ zMbPM9Z+VR0A~6f9OY)@RcJ0Hoo`MY;e$~jvwc6p$BSYBgv%LgXKzx7}mx7}1ga`tk zAx@LgO9Hm~qBesr`6B_3&YV9u1IV5Q#P9ZB?K_k?NeV&8kyJ-K;Gg{D2ab!$3sGST zU)vGg9x$C$bPw;vF8gnoOZ8MusdU7=HOl#l{OYeM z*%G%%%vT|9*Vze^dXgcM@mvJ*cKf(>ZM7ZsL$4mSPrQ{P5LC7%lBAOc$M;fSzBgSYo*XK%V-$K1&&fOrfrTf@^lf^Hd>kLi z+#n-#HEA4`-PdprpU69gD|6_cR5aI3DgoZaKh|f{986;&`0Z(3!@`OADM}oZK_8_) z=yjVi`%>6=xur=6tEpR}GMfu_T!DUY~;X&)|sp>+doh#Sb|e6_0)*vGg} z&ru6V=vrp{^a80CsP^AV2yR>cq4xTgs0+)cM4F|1=fnj+4=s){OSBh}8ASzOGH`B6at_baSUb zWL%6;3v5_UKPQf*DAc249seqiC^DNHwP=Dkdb6GB#7ck<`4!y=Q5(WF>)f4t_`2`s zp+;tS0x{a*T-$;m`A4qUn#MVys$cf60tKO;WAiSxdyM-Jfyh$b{u{|fM7Xg^Zx>ZZ zek6zt-R`B6V)J%C@(F_|_KgI4oQ5vB9rQVmWUJHqE;;>hZlo3x?!4!5Mtm9rRn+A| z#W`uH`Fzm-=dk(=*)Ae@v8Xe8m+f6+r0JItm#MCJ=OqpROt^j)U{W(kE?ryx)y1LV z0zM$nb+|mZ8q%($x<`Kv_8!Bt#t8}7ZcKeRgW7%K4cC2eT3Tie5+w3#q{&l`%4HZr z>*cT*B>0Wg-yewYA}CJ2W)EcKG*WtbGIHzGji%UmfwVe*^Dt>^%YNdL;*m;X|86nj_+Af{I??J@{4G_cPj`} zpUkAzJs%8i3@#EB4Z-z(G)}DMz{`GjsXF<$f@z=O6P?D?)@pl_`Ct@D4KiDRGPukC z;(Zz)X2ynAD}E!qu4FH>Kb)O#>k<&~qFA+Ot>TkhN4jyrddzfR7b zcuUsGjIP#?gWsZdbu&9ABKN5OU`~B-?;1%@K{T;jsIB0lCC&+zgl4!|*a=+4Cm^e> zSUQWrVb?N#>AS9ih{BPUpgJV9FUj>4!{079Fge7oEkC+<1DJcn!48?~4mA)sw46Q{ zlNYm{PURyBwFl!3;qRRjy(DSI1JEL13hR!uxWa52jT17rWm=J!d8ghiS4id*jSwT# zSd3KriO*9R)fS=YSp*h73y#eue0dRLalgD^I~7rJVGG}t$}6STIOl;rZP$LumUw|y ziK=UthUA^ssC9+gq(AlwaiSBG{-SwqbV;1Xn?^l=;n#%v?w z^_44$GbA~M612Xt8Bd~4GjTMtkN{(M>h3`Pe&xr%X)#F4IxEozGkC>JYl`E7vLKf* zeCrD3MRhmXDl%IvBiJkd4R%V0*d2C@bSX99Dk6cz^yhKc(YBl~qT5jlbI+L-_Lf*M z9fFex36^A`v04qmBxLM+i{t|<8BkXE_$NCNSU$ItiViwiteU``xouS(l|`8(DdI-< zp$CftbVVj4y?$XPM>L-4vb6nfjzCb3itHT;@taBJx)Z@AP&AU9Z6RsTEsh^sNtKG9 z@Z=jbp>8}V3-d?nlGQVrP%F$h_>nD+a1ZT!HIslSNCBDf6}FGJjbw}0?*w=UaGsrw zk}tK_yhrYY5Z1m!%vMoegtW>MUt!U$qXfT&sH!@g;E*mf*6Z9x-tqN~l=QQNIFbP1 zgdCTw@?v$Elkt;wKZ$fuRY-?b>t0l%{7$SB)^6h;ooIWQ3#>u@RTg$6zhZa-2jFj; zxSZwyL<`AnC>{wjbx<4L<-TXF6q`(q;S2g_QtUo<$lI3_O0|Qh9Zx)>`ZX;62z*@t z834<45H?1I<3JE!U$q7@-Bsg5-4_G4^Kk@~(qXKEk7%lZuc#?*hRaCbm*0CA9{=9E zkaVOFc)rok?}#h5n6RyJlmvOr(>=X$zuK#r1S3iKlZ{T_gFTG!T@ojWeeFI$=A%OS zCEmZb0cms+rdhoMD)>AY`{MH(TfMR0R#)f8xR32Wh_fd?OXFf)_)qixH~;C=RLdPs z>4=_hQ=Kv56#F;w>o#uQc1CsgM#gQA<8@bTe5CV~y1abdvf$Gf9UiAST#>L&2!5i! zWFwW@^ws5!0iUDKlKWF0^6f_&n_7o)X2p zKUAG;hi7prHo>DM`Ca*ZMVhymU=^U;W4X%{ZG79IOC;I_uyB#Q$Lh0of>(=E>=ISw z)MYV)G-E+=adG)O7zKA3SiGH>^!%&r(T|r-pQh9|GAif86W{kZSWv!N!EG$JA!SFk zkC62WrK!npW`~YoP!Xnujv~B?!^p)!z&+LW?u|>)t`0!@IwEsVVHM9^L8t(7@3#H`VM;<8?`^JCGif5tkD3aMr^ehc3m%{i>#_y4r83U}!AYP>BNe z?F$$+b6IAmf^n`j6_uwDObe)hXQ#a*CvrA5_rNoCP%B!b-(!@rbLz>O&(FUqIXPJu zgWHU9ECbdb0MXdpV_9S>XJ_hEUyobwH^4znf-hby#2IzLlUjBl{VJoedYITDW!Bw$ z_7p~ASvxp{e>miS+7i!`b69;?S3ln>yNp8B`2DEHub}F)Dysttl9gBbrgm6N>&!Rp&(%5)zvSpcy&ls zZ_9rUdHSUP_kU*0hq4h!-O-02O=Lms^j#6)p`$2M{EXi4{jiad9JoCD2d2)EIlnEr z`}I!U1M#;A*0Q+gi191*B%&sn?bxk*8}@J?dj76B7dv#RcRx!B+kc%po69n`3}qJB zjX037CsZ|^hgExwYY`7$IeXW=nbSgov382!++2onk|DSv`D35+#9fE1$EBc ze!`{a`^3hi!A3tq`^3}BA;R0&%%C7!ck9*@$CRa%dja0Ov|8~WhO@9L3UuI<=^~qZ zf1#ru+jn&V`D1}rvIn;oce($#2SkC)+1I}Zb#`-IJw2jh7x40~#3bopC_`7<$os}n zCYa5cFo*T@>C>xU{Q|u@yq=T-_F;7P+x*!Sww1;W2ThPcH@OuGPygk+QC9&;NrOOs z1u=9+`hfAf@tGtPEY!i88S^mwPr`Fv`n!Mrryx#JfHni=1?34}v%vqq@)d`>$=1fFW@~!0Be*4zT(%jQqWjl(fPKa~M;i z*nM~oL5n*_9Ny+G=%S3VH{PSzn5hsD$4vUY}3M7;2y^w9?Qu4LqEezGbK9YqFNIpRxYKivIA> zfBEB^8(8-3iYr}J6y-;2*qNu*h_VqpCY@-x^dBcG84@YcXuD$XhJ;*Vq6Vh2bs>*P z4xj6sPMqq6xtt;4;lcw00}1Z%f9ldqq;_zNP?SW_N4FHL{C2!Kl43iHL;+AwJ%NBd zVG1X!3OkZ^e>aOV=6!o#64_DZv{kCllNoklA+uSH1He=J8&j{mcgwY|RYrilQm=n> zDV3@e931@Xk|oNzy1H?gqm!T};LQpU$|}tW$q;}PpdZclq7)t-=2Yh9#hR|Van{ev zf}+3<%q)Mjy-M^bhOdSuTThSnVXYw2FxY4R;fI~Pw*U&naIorJFP6GR8>$ev=5VGn zXU<$81`g`&X_4657}=xgC}Gw5FzcrpZX*U39-h?0FMeiaof?RK6yAU{DK*(8nu=l*;Y-+RF#ful?PmB(x+q)gQB)naH z$b3Og;@MORb=DmA>DRql0dp%|B|PFo`$nwRaMot7 zYT8r{Plqe64x}yL5tKS51CYh5N z>+AhuD#VL*sD~UbBqn>$!+E2?$e42Su(JyiCl!`+A7ypTW&>7b-1d0bgf+-UkvPe8 z2IKts^L3MT1-l!PFA|`9y1SfIU0vN?w1ts-v+#7#GXc7k801F66&a2nQz<$z`i6{s z+5>=R%YmM;Z|HB$$=bQ1H-Nb=o*H^=tZUw>8A)eVM^OWckRekTqe?XKI@m~Phl zIseuy*ay9<^ZtcmwbME&K=&^7!_xUayP9@!Pw&Y=vL`Q+yUKsu6Cyjm*nd`RGMb~D zDfSsp`&&xe(t-}ZUr`Xif>VA)g3dKg1Bgp6~OnvTrc z=JKkPzU9u*45FVf`StE8DZ1UQibKgUPcC0xRR0AtkmFES^IUXF{$IFEGw3Eo@Mv~? z^j@r9omENGl0FZEzdBY+-~Tgg`R(5L_(G*xhzH2qE|FED$jc7cmzc16olnrW(t}z( z=vB+}FLv(}UPGramvpxdHKlM$33#DN@9K01R zCBqu5%DddUe^BGJFZw}>Ke55M>pi#vr5R~&$u|9Y0$3>Pn>o9V(W+3-Ap9-$*Tj`i zI1kZNVa8N;@812?C4gHhG<)9@%iAnFnYq^;_|=bvKNNXg^%E!VW>_{@sqCt~wkhGJ zyBGrt-@&|_={Ss*_r3`~t#gQOYQeBh>Yd%U>!SsHTJ7UFr=M~I34{1z1jJZq_g6q0 z^8tgFCki%+RWK@N9?gfFmAoS(x=?t_3vAcvmGu{ecce$YLY3=ZMivfcI8f8&mAZbo z?`O_zo?gRM@)$|g0!`& zgYt59OpiEHNB`~^W$WeD_pWb_!+Zpo*r=<~jI;+pyUrhv)w6XWc4h^2(A8zqrAa0+Fm013Q zfB7jC^1^%e7^Wrt@!VN*b{(1c%{=e5JhWS)XoyLgtQ_@^G=J7i{{D9-`EfnJdcJ#@ zOujr!{!Lt#LR{WIW#2LVk^ec9prcseBiSSOLjL8aDB6*o354poXK$rHy$OC$w|0vn zU;UtMOOJ__%A<&m51DrPA#&S#nZxDVu9cA z%(jyLVXHC`SW!h2E=167_YcSR7e6ZC$Un`hJ`Xa9PqWVJ{pQ4P!Rgjq5lLsG-C2Qt zEHLQkTQ8A+lVc)gr-SSa&(WW^fUR`2H-}as{zumT{O&6i2h4xWJrZ+U`Hw|TUkO$a zC{ul^Ozq=;*moDQz`JWXP3Qc}PoX0(?8sk87PEO;c`zj{dcG8hncrPOa+JX0J^{o~5CN00LFx+RLPL>wP(!5ovMR;& zcJ_;+kD|u8s%TZd_=lD0JX<{P4=#YeUjxm8|F0~L?CMP5`PfZ>r4fL%aA3v{MPY~x_ zs2ybA*jp93-qJ)N3|_Tmga92U3-=EK^iMx3mXM=gbSQxr-N-^L4AWPtbQ2ED?uy#S zS>GQc^3ZBHo5%)dcTwbjP@vQ;c6WQXs)KPULB!YHwAoRA03~4EgsqEjttHU~BH`6e z&-1KnuN{8)xu*)i2r&}2V$75VPNWOCyI|BwBfen_?%COjIBPZaP*EXL+C8<4@tbM+ zg9n#iETvF0s@635(n`snH|alm>(B3A{YvzydUC9my>>(Xj@Y5WHrWe1Z*xBQZ~)NGiyEZc^p z3q0~C4AIxKf3f_D{3d@S9lQ^==5GTjkeE@v-BlCr|NCq@RM8)K)lyAz@DbZSGSIH2 zgg8HuI`i5V88It=MH5gLKq43U-M=c~ODU*{R-W<(p}LctM)K1PMEH~U&|*PnA69oz?CxCzOQ zH~>xc2zmIZS3HGVY+6ZrLL6weRqgKMX`_1ib{5<200B`mbn&Y9R^h5>Ih&6r5qQjp zrrx*SVsMt1s8RMtq@z}$uh`y3nbnJ%LG}lc`KKQhOGvmUoz*l0R;of-aN5k~lN|Kn zwH4p~l+WMZLYkO>g%xcNG0@{~TtY$xs>Q#`$QT>nJRpcEYC~<(emBu1`}M=E_Pw7v z?hS&b&Xreb)?8A6!6jN8Xj5_zIwKx5l;pxK7T@h-P4Tp; zq3}Hjvd%j%79`YEOES z#oA*NREm_&zJb?e4g;?@3F*Y11Oe4{z^vr!6DKnns2e~inUL0Yp3B-!$=Em?*|Hdq z@FIorzO}VFzO4k86|(L6<|`jT9JA_6Z`0A<@c$pG=jF6u8eQ%;A1{`(y*g`3HoP$H zsTZrcYquZ(Fh{rg6}*HoyH%wfy+H^_LUB)K2*|Pqfo03epOrHz*PMljg%@qOKT|>{ z7Q`0IQWaG=EUTkG$n2B?)Kp`kW$X)Xsl%7n?5lX6kn$C!wiBb-1Z9>DAooHHPqH6#T+X97t( zEaN5CYFig~#x&nfDO~c9FuX9kn>j$InHA_CXiV*vv24G*X5U$oR@E0=zFY$=AZC83 zKV}{q*u7ZVF1CBieL7&b-Xo2kb+BcP3+gUgpW##Daa}EuMvDDxL9g6g{pgmhx2zZ3wJK6}Bx@$WoOl1N*}JSGbBzAv7dHNCIXHdwlH z*~oN#;Xl^8;}RkfEww4zNceG6whtdRqL6Ze=dtpP`?!9O$M^To_w&bn-St-QUhmiI`8=QJc^t=ioCnFW2X=51%3N|N z7#LBolR0*ePQP9j)(M4-3IyS@ctO3ERW>LGEcuXuXXh==yG|+W~sn#R?w`*Z2>G`ei@ezhC%#rFJ*-T&m1n%&it%rcJgcw{8_$^;TbT7Y+vO zewCg>D>3f$>zj#*sJ;KMqw2vAr_rwP23;$BtG}Ac{Ud@Fh*O{m5?4Iw$VnYVh=Vpl zm+gxg%W?!Um&1ONN46(yI}(pvPkE0gOLtFc!%Hyo2fs=o!kDE_u)eJuE{u; zv}JeM7O=|hs+4(y*7WGZVPd+fj!5kyHGj&Qe@+BvrB-IUu@?6F^DUP8Yv1J&h{`PZ z_@_m)epG_33`=5xO0DfQ${ar=0Xjk_($1*wKX9N>KCFToRAlC72Uy6Rg?6kEA8&h~ zLwli5d7KhY#UAO!{6!KTD_lQAvauiX1-X! zK3Jb>vUT~!gJ#2>CZwwgjif9b$k))2{hWW%X}Y}Ew>GsSL+~S~U%+;qEcKglpU|}7 z1v%95Kta<_44#s7&K{R(f3u<@AN1)T1T8pKvW@C5fRbu2UduCA%-A&hjhrM%GOd5A zY4XP3a<{I3X1GZu#stk_abfQ;M0{_~;7PaGIgkmX@M?xzL@;7&?9`jByN_=+{tY ztlzTbKy}i|enUM>_S~viREa^FRYdNC6r~V-gNFApSdSB8Rx{QTbf?`t61Cf9J~ad9 zW&;BQBHB<28@Ucq#D3Iw?L@;6E4L~@$UIV*<<s%`Vc0&BQuPT(yZcX77X+VF&*rwVErBe7 zeb+8^tUm&}-$t~2tLeH{=IZJ6^2$nuD>rTk4kJDFLE}Y6Jv1yTm=L;VpYJGz$RtxXzisFvAwH z;es+AWjQn~7H&{HZO74f4~1BrxZ_k7e0r21(bdnRB%ld7eevLeTF0Iva~Ov(#V0*o zh(kRys3>;x-F!p}U5x9*r@lrhM<@9lzpvm8EKB;nVuE4)3GsNCfF!8AMtp9A#eRo8 za+`zaohjK*#Gp#ve&(GJhg$lB<2nvTn}%D`yys%`Kti6k{kZGw|f2U|D~vi1}bpx+n*uqKhx?Q8!3H~Fx zd1iA<2$6E(Q1a{SpH`sI2JGi!<)9So~gLQfGczDr{8b zlh1wsj6E55?fsiC4EV2@en0rb1^wKWKQRqI-HF-XIuY(y{!zf_sv`(U(|$I~J^%c5 zy0Lli=vq1%^kK6>SM{;^-M4o;ld?p`u?)y_Z=!|hVe zIuipL3IA(aLZkE(3h9-Gv-efQU~7MsvLqD_PcK5ftK*D}F|Kn*1c2=PKe)cR3+DYP9pLL0iNv8a&2y`jMQY|L0K}i_ zpPu63{N(Z3$S(?gn)xvQ%hdmBIsY$H|Bv>F^Z(0Cz0*!kGvL=SuD?uRN*H}pf{xK#ouk4{ z`^#GHhr`1uHx`@yS-?Nw)*SdSff$M&vIsbbm#&&z=W*h&bo4o+tP=^F0sitg*v*cN@ zgy>oEf*xSJMwzZ82VG!v+*jCt5>oy52tehJ#X2{tI7J%++1i`gW^%!FA`ao^du{*I z!6U?hJpNYwwe}?Z(iF9BznwGPqt5oaF{n*%A~ClCMIM7^8hUAPLJZ0+hpXulKb1`X z?OP``l7BMtCclO6THVvgnS)ZIixj4r76m>(3*3m>;zJ$Z7as~p4mXTl^WAd1kiW!3 zk_sL-SGvS6R^2}?3(R~IdZ%weAW;Y#Q|+Fu$M3HPVBtqHEwrJ$J2M8;aqoN&#-L32 zkV^p!>9&4XKSR3KKb8e}zv;%#FPD#Vg=%AJ&B&0mhkYUM`ZoIy?2_?T^gGHWIrjsF z-TUp@Z2o$2)ZhcVZ)cMy(W|=;AZtRidaf1s(6=hRJtmc{=*;I0yMiA2y_mUZsHAH2 zd@2JCqjy$XKpOc41!B**z2rZwklQ;oii)+Gn5cgJ!X^)f)CC8RxtcCgpP_)Tw z&RW`{9_k3Nw3Mg(NjmxW@xV!qv1~d~a@v+*($p7HX}zf~N1iCh%}ykonWYY0n@Phj zAz-|czV$5Tr;X`)jT|{a_rV(kQ9MMen>TPl1E`zO+O_RGa`=<>#rOp_m<=ZoCc8CL%mcts>I6mpEcZ$8JXYX|Rqfx%V@c^lE9@YF^}y zt(NIgv6Rf9q&dG8FyO{H5{&GdHf?$mSX)4Pes?oQsnT3d*fVy+3@ECA#{f2;QQ|WZ z-Dy@d#({o&taN493^hTHE2588UG@GgMJ18Yg1goeid`WRhBd)Qf6da3PaSblh$`VyxOXy<<3V$c6QG3w-VO+;veGTWsUg-AnH!JLr8K zv(sNS`NRbBhmB@3qmR|PlXsnM+h+p?zp0O?U3*5f|W>l&0c;r}d@nwT6n& zv6!ZQ%(lC<$ix7u8$Orq)U(Ty{{o$~k)k)_P+-gwz$D9-U!OTuq=0+4%7;lNu9=-! zurZNJOIp3C<(Rr_kMa;#``F9zT*J45@kS?zL6B}EOOok{8ny+K3GHabO-%FdjZ{*f zVE(AZbu%(uz-!z*Iindj3<`zlKD!2A!HA2gO19Xon-H{*~> zzRJOqXuKhW7&5+Ru1kSg7YyAqy;UPq#_Sp1d1IB}p`pe;8OBHApi90WQU}pd36wp( zLZfLHW zz(l%jxsOW`oiQ2Yi!xVFZ1Z|%g-Ds_Li}Bl?}tJm-Y^W^yDRq89L3A8fy)>1Ce*Oq zfL_s~PkNDJyei3Hl+6nh6x)921a^~0J$FY8&e~&UQsgTT>aOa zXjne(!iP5UrEi6g*{W|&98AI3R%JA%s%4#j8{KIne@QG%@u4I4kWG1NX1ZFZM3{{I znW54!$0>uc>V6v9;}5QiT>_;f_@urcus6?!1Gl{}p-u*j%SMsCDnmAJ&Aj3nCda=( zt8g~tWSk4HYt+pb$57MGg6h{(b_FNw&yOdJMwJf10&+bpmv0aOlPcd}NKC1#J2QaHmn%Mh zhJ{ODslR(d*E#3L8}2Gy!M&ZMc)&X*tCCJOy$h?dQ50(!n@oK6he%R=qw0}kliU?w z;6`!9U3Ed6Wq+f(*z|-2pB+v{IW}jp!Lh7k|2<3kA!h$6RxeTe&7{rDfw=&^wwa%6 zlpgZjAF0|H+%ufef)t(KV?>S&y)c8$!CigWhos?3c>-j6yY+=F0kP z*?=b+V-Qy`JRSowBvM;{jtlppw3A`0Yf7CdS@j?0nl!3#sz1<_Ze!IgokYGP(-RvtJyrIZg4Gc`a-`%69668Hlvt`Z?VE=GqyLUS${bBd5C##=cCw=N9(kI^=^z(_7TuTlhxhfrq4-@6*Bvg)9cODZz z$GkXFcPyYRvh<>uBO31#7O@bj=w6z`1Wc|vl4F{eFo%arQY#L0ioWc5USmqjQYLN~ zergGsnB*QiRws<%m#XP5?sxQ`UTREszu48J8miOw%KHlxQU}oRR(vj`J=mvo1dY~f z3GLIpU0As8T6^6zB4hD{;e*R!am=siiXI^=8yr1hXn6nIyWXbxq(2?cy|8I&Bu!I; zS^K9X`KKJ=U*AeF5IlFS0=FPkr+$*%Gcsv5QvwMKcDlv=iL-t$7hg3XiVKO0)2`ZK znXS{<&^1=whkW{iD7~Up=00`CbO;O^I900Mo{x1{tH&pqs*E1TXhG|@GU;Qf1MpGQa4&s94KJDwQmS2_YM2hwvSH9YK}rHM;Yja8eg@6&jwB~y_!SztfZ&t9ml9C~R zpnk8GR-`gjVne7768A5}C&G|+MOo=hhVf3RT%H68YKyXw=PKc*OLvxO`k)%|D0z*s z2DA`N|e7DpUgUcq^Bl{hYT=aUq8~n!HC6Z zN+39o`tAcyiosFjmBoB<&$yXCM6z$kjuVVnJ2omxG5f^-zG!}kmU!(;BFRkyAm070 zX1kKZQIEa&lf9R+2zk{tdx=@MyjV2o`x%7io7|~kp21Wz^{;UrhQr05m9|v3)Br`7 zRZyt(30ydl{&=5qk~-tp3tKa{DL$u6DGCxSeQa{_bKl_^Pfd0h?>VJK6l&F#`BD5B(*BCh(Z?l$fRKh(Mv&5|B5BGBp20N zajt2P#B^+@0o^4^ zlP)bw$EyyTjB4E&XqC#mC{DJ+Qk~v@hX9Mj{Cz1Cuv^$@EFmqMWdqT5?an96A3pz! zqVDKv4C`l7+7w{imECpDHLdIl#uk9o?i(YJPy(7x19dIp=P$ zis~kwlosXxxc52#=3ha$-}6zg(HX=f_&0e79KKc$yCFKZTM|zrf+MMS@ciA?W%(tb z7;giUO5U8VaPO$D(-+KJZXY&j$@w&h?D7^Aude{86ieyF;VkUiJ;C2zIZxf%!2*wgS@8F;edM|t}XDvOnoWyrv7P98d&VJuvO9%D!5;kmeaec<8jx# zF%<4qTvVsf&=E<~k-Z|@RGl-aNk=6yql0-l|B)xwCZq%M9dd;;%?ldGKF6=()4gV+ znC-Ued}@_j2`aT%74ftYiaJQ2UR@u6fk$vjNTd8A7rJ=O>qTPAeWNH>K%9L5q68f@ zDaY1NWf0qvUJIiT?McOR!!;R)4joFpFZWdnPP}c%(gdwC<;i)@&(6vm9Pw-s1vS0d zq~Nw_SGKMTLapx(;TG|B^Cw~Vc<9xt;kw{1Y7UOV3&DyP#Ub=A|k(-7bA zNtXl)$nq~J*rK>k3RW|1uue+8pY&C=GnLDRrnKN$`61n~j7YCio%ZMXq)yX&EEqCL(dS5<1;$Wj>C6 z4|akL*=RrE9;r&J(o5@VNP&dGs4mC;Ny9z4Kz?tKrI}TA=NcWS?UR{QdLLC(H(p9J zG4ejEdul<%YS*%KbL~Mz3)4~4s_vi$tL6s`_NunX=AvN=a28Wx;`aMGltSZTIXBzB z`5Pv@=#PD=a-yW`s?DTpNWRUbsz^F3fU0;9jo9FWnn~0x2T;N2dpS`moL1anT+7DH z7C|f;H@ZGE48t+^j;V=S>Q(o%?;XCeKMRK1XJG&81SW z_Dfv$JcllIQg|NREQMmXVMCWicoQ6jhKO@Uns$!$PzH;D;ca1Hyt-)*=A7(2U)^gn zCaj!xCS+^$GeZk_1Qfy*rS0oLYezktOa*$ql>L*!E(O~aq>H>hEiE3!OlLkdVe@a0 zG4`>0jsBedsC?xfIPGGST-9YWR%Arwwrfb@M)$cVVhfQyU;h-ScMtMCT~X06lS$)l zy^p}se4*Nkcfx1YYusg_=*HwX{({x3K%gIenhdXuGZ%m)$A zNZU>{wng4Jg`P;A-5L1E<9kT@6;mfkdH|`qrdQwmO}^1A_93!@j^c*Us9r4v`{y=7 z4EF2BalOU!z9D?SW_Eaw|3#Qb%M-sVXA2YsBYn)@6l$MIC>{rPO4oR*4mg67_ zKN(Y_nzU5goNr=Vwa(7Jf_f9LoBqqEMiJ!bY;Q>Ll|jG%I45=Wx#0Q`aO?ftG5|Qp6Q+eSz#L+4P~&8 z#l)leS3Esa1IH&4XsR#KuF~~1MY9kNs@CL$wD}{00>RSatH$CK|iO z%{Z%*(d@no3domscTPl5k8#@2NTrwSjYCv;6CiK^-SSDbUJC?220m**gvD99o8B}9z1-{Jmbbt8pyN!;G zBoZ}p?gSciS^09q{o`Aqq1XJ(z4_@nn3o)yi85Wv{ld^Qu0H=^Zui@$OARdpTh+;^ zXdU!@tYqlW=+2U09o6$btH@|44nqovrUSz%*t^!6s6Pl+?rzG>C6=tZr$!l1+MNm% zgZo)z!$?|&UiGC(e{?S}O85bkcMy_oz}qdK48E7_i$vl8Qi8*gOHuHvNiYuC`f5_L!z4@*6AH9)`~x!DZ=H_ds&0 zmq*Ibq`hJNGi1n<(j&(M_~)6l*376$NWq#9gb~5j0ceif5cCDY_S4p!M__CNiN`w_ z(O{DuEM%UimgIg)|DvlynEqu~2XQid#AfnKhS+~2NPf(u@vX72m zhY8bhbdBtgTr$!+VxnFaZ+dr>LCEXh%c9Jv`1QMP8)P){t+Q>GlHTiVCRI$>H(0v| zUZkeIU)F*G0EZn>CB=pj{~b;dLDAGTU{O1St0ZQahsyB-?SL4yxJGL9o-64WW2k7c zo=TXYy)SX|fvoTzR67NWys=M>wMQ^MB7n+(6r?Sy`xkiGPiq2&)2(PpK01R6P8DPQ}&lPCa;p4Xy7 zbCv?OLKEr?AN=aSiD;xqPjy*9T(HJHZl#x=by*0da-IY}Eg##iMlK*-p@d8USS@{%O&g)%)o04oFqC_N^_7$XkP z=g0`Uv5rv`YW_Qvl{rngQarC+<9DJ0j`^x=8r;*ti!VrimbonlP1h^y&ntEbbW544 zSFVQil%Wtb!i(ep<;x&3OnZP%Z4p^BLO=jyM@<*o936)`- zG75*i{eUc z`f_@cF>TVey|kY$gu_c31#tLc6T-u0o;c~jtzYGqka65Hq8B)E(QtR3)k)J52Xynb zVIJr9=RH!xsOLMXH?*a%ab)BGb?}^!v&+Q>5Z{6*aT+>EzJQNP z(ux1BMA85;Thd@Y5b=y6Q&S~Zc4yMzRm!D`Xqws0Slm0P!{y(Utan4%HOH)3s-lVX zm=ZU`y6Vo}10FHBM_UMvy=V+w2ktoO4iTkvNzEGOPrRfBBV7st@Qgi5E(dqO^Qq{u z;Vqz|0ozVFcQL8J3C)xttvAwG{bQ2HdnK5SG1F=BAoP`qO|UjWzCPK0`V%at&M=tv zegpS0V<+}b8<^DNLOnX?)fM@J%vU2wEZV5KZp#+NTM{Av_5zr(6)W7y2-iy8lZ-{Z z7H3vCI@6^rWj!p-$v(-nPm^k_a9PUoD{~s^@Q|u`5}u$6M=YX4~_nJj+Z=7 z1;nFdiD3TbrGad z-mC*IgumHRuN^D+2Q~D}v|aPML0FYeyfsnhB--^i&@CGVx@yxobB7Zvd#-tJ-SP=+ zto$m$!${z>B%^At^O@3cr+7}UPqh!Dx>gnLVhnmhIWf8iRtP%yU!+G6fc!p@(_FDN zb1o9kR4|yuyy}`7_Z2wa&Y@AClh}?-eaAEUYSkvW_FPB(i!R(dYQ|FzKxtp3Wxh3B zx_8%np+}h~R2U6=tyEZhneLf)0v{zj8q-E50hDKs zB_P9BrZZit`9NfJ6P4unXT6DcfufUBWfF_x^lP6J54KO}cs-cz_Ni-7n?kKChx_vy zq(NxR>q_K!`}Xa!l`9PxYE`Y6Rl?b+GM~QRGDXRb(q9&?)Qf~cv2`Eqlq;yt?H`(! zPW`kOPWGU6Rvgg09#&^cySdDamR7VZvL?ZPjfmx|sw7Hn{Z}sS5hlbdK|8v$OHb|j zZXyVH4bY^>%0S*tOnQvEJJc;gK08F=A~~CFM-`*_Xt2{f|lR@_y%dhg7+O z>B)#tSRm>qX+CrA5S1G*+L}+@R91S)y#W-`d%H~?KE16XzegMyA!$2Z%#o&wQB)0) zLo>!VUYjU}#2-cf2UITsM|P=Kp-P)mm&C9wctemw(hM3PVB~9Kk=5wpYqnUbZ2W+% zET6}aBkT#@3&bEtB~{w;gW*enZqlgGNkNIAgORV>;blqu6O`M|sOupr6kGK~j-n`5 zu3G6p@XQXb(XktDiszkoT!qUaareS@gS$wcm4-EgY+RT|6KW&1PSsV+Ya?hLpbN(I zxK3|c&U-Ol-XlX?{mhA)KB(|5ngGQt1Erbpb(L$leTSvpR;p)B8OItBcQP2p^aQA$ zeL0b7d2f;BgG+nc-uRU+n2VmX{UYZ+84FlVjtEjoiV~6?Q=#Puv8d?fCUDVRM}ONs zH8r(VDZ2PU*xYeo$R>ZOtAmoVOqdHMA0I%S$~R<75Mq|@;SEK0k6yh@x9uVXcrI1ZBA#%I07rk$Z^+1a@q%%-4r&!A$26vf+Zl#U*h%w3(w!xr`N ziHM9{o$QgCf)*^`!F<}n&ByQGZqPxOaii-=Ag=iXdPRLwkJ6(k$JWg0>P*CK+*rH& z`Sy=G5L@Ur3NW#wo7rLWn+6Qh;+3Rg-V^C0gbiHuCF2l(W$%|2ms?(Zz4m*$>! z4?&+|*vu$&OiD7*JFK1lPdq9r9b~k!WOfV<%0s2xyr9PmrVxXNcfPctSi-E zxAyPL#201k7;IsA*LZJvgt57H2n&0Vf2z;GhqD%QazFgnCE|4fa*@leLvVfJaui68 zo)K3gZHOT}G3f1~-1u3Gc?n#f0a3ps4*)d04kre<4qyhTn4+?dPxYsllRti%zrCQj z^JwuI`9IvPcVctBf28*^xgbLhd{p1Dv5i0eiqpszyqaASY(8tA?O&hm-*@-NR}wbh zcOI`-wO)gvOM_>3ke^98h6xLOmMx2ee*DP=hUD#ICq(||1@!$x^+=GFv{CY(tfX1D z_!kds1%{X0os;A&OTn&iu@kTfR)9FRLVc;)%GqOOD{tWOjRnxG`{jO{{dW!5;lu9u z7eo4dR_BnLq?fbhM@b`btsh&L0>rdER>(hIE$a~-C z#G4d;$XqvTl`p|;pa|)MQJ4PyZT|L7Z9$}xpQ}OPhhRFVG=^Me8M(J9VHw+JR?heL zy1NFqZJxreOscNFZEFV$zJoyhCpO^#F6u+F*|ODep|s>Qr(!K{~m z2xmWj&Od)fo`hBE&s)+l#f9QL_Xhlg(+Ih@lSMw>WaWH+N)nUg_Jw6^TlTLQ`u$)2 z`xoIm@IVb)xyeeuF!SD9Xz(W6(?8AnxZ%=x>n^&AF7{b3|Mj>3<}Wx=on%(SA;JB0vIrXOB8TjRxR=kdG2> zbraY_myvu1RZcQDFzXX4(W@TZnVZE^r7ubptU&xQ@2tKx`-E;F!&yaD&&@g~e!cqY zFX0~57u{lWy_cSLhs~9O;RG9*LAvL#1!hjZ0I2ltZcfY!ju)DcJABi@q1JAR2z=oN zW^VDPV%()2%dv))f@jo%ElPyR0QiX%dRMa-f9!250DMkHGCQaxiN+;n8ZKtq#^{tXD@YIaz=;hmDbLRmcL$) z)id)BuX5#H!YA{8j86uoFZYgm{ir>M2jK_s0uE)3ms*GO-@n4K^d!LS`+-@7v<PZY*p?HFQ1Z&$)t$WR;a~Pr^?f~y2(pvEP#vQ#o)sj>e z#R5vf7#aPo><&h;V$AzN_${+1ZT?;#i zDQ(78OG)_6%7&gUM(T9RJ=l7w+%MP5tW83XZL~S>Zc8FE0Ijs+N@O}#e0s~(Z+&~O zG5xX1B;|<1&NJ`QF)wPl7ChZ;)H6cptsh_@Z2{TSG~DT$WQxK76sq}rr8}3C!Fm|q z)8CSWnzulvUc$dwF8U-FgtGF6So(3bdgG|CU|Y$C*7;o>500^6L(S5Kjm^ z#6iD5-ZyeBls?#H#AAlzLrmZ+kfPzDPc9KLvd#s`@dEP@RvM_P94NRwZ+#;e zk@5;Hq{V?jw7O>}Ps z6FdZ%;CyJppfP}tkdKQG3p2eW5kr!Y6_&eZJ)xq@cvbg>@@Ucb6y$&WLgFDJo!0f9 zzH``1EpF`zlKu?NjD9WSeyJCQIIu}QtFkqJ8Do5yml`l(C@AX$9hLx=mmsS@Z-ru~C%(pBO z?a#7NA2>8t(93b2{dzCd21P*!3M^qZxqCY|7ci0w3~KUs53?`tPJRfqlktAxnTjVi zm|Uu3VqpB*4$o<;?V0-rpDpUnmUW_{cKTN+{UkYS2k`~scCIvexodWq`{ki7Pf7}f zXpsU|jCAFC#Jyze-P@lrx%`zwfY|#@@6#S!7G+&ySte<4Z1BsQlT+JMu^#MLc(R9% zPV|{NdX&rbfw8!tcA-1wn@zrGcO4}yGd*-&T#08Mh@Z-H^@kF2FcV`!vAG-uw~KPH ze85V&4gr{;eh4P%Wnrfcz?W7Ky1GmnuX!{#Z+MYM8(Q_{Hk3ewDX38BBMlZAtQ^UzPdWVvs1?=&d(Dx7~AZ^c> zz7-dKj6T;w=7eK-#_5C@ZNoVHk<}q~UtYh3DVv=FAiXyoXE27{;PdKOM}2W{PW!Zv zQz?*pb5ycscKEu6pmu6cuvO{7SvUWei=7@x-RA1MjX5~^PNd=dTYgB0odE%Jf}=cd zgnqFX!|kxMg&a2aDj!2jplLJKP^uM%5LMe-hJl0SB{Tqk;B#t5FKy2nELjBrR)Z5V zQybfQ4j67-x8?5&FM5U}XL;`U`~Jd|iIY|60bu~yq&tC1*Askw>ooJ!xg^L!j>FSK z7|vuX4ZJN?qQmkwbf6VsqMrV=8GI{csMR;$hM(R`ur()zu7Ls*BABqwsfFG3r&GHk zJv#bcV_Zgr_f+%wEin=EAyz7!Kd1cs&3?p3M!|Px(u%qDhH?4mSPX3H&*%*GfK*CI zbPBCbt=OSA(59(94hC1yq=2vdTv=i z5QIiH{#GP0R{&D;+K#lPygU0QAM+jMnY2jMG)G66P9MiLZ4%o^Dq(uqA|Q{Bex46C zQfP&;;aQJl+d91J|A*dtzFCj+*C&5IV%k-K`)NE>r?ylN!_p41R*zwiOuYL6YDJUccRnV{|0HL$t+F z4%TC`xC!%j9Q_~-E_hJPbLW>=lP+lEH4o>g1J7IZk^KG^!Uyo zwGPJ0dNVxr^Yu|w;TXXn%B)NwstAEk-c9K%MUgY>8E1CKdcRaS!P!))!y&H;W==U> zLgWrV)v1;jSImoe3tqr@Y1O-y%j-N}m2fFcwevV$q384}v~DnAB)Lcg2j;9)pKtTt z`=vFn%tz_+;hjZCv@y{i=DSI#Qt=Oe zGxW%LcWd^Vwxmar$f~n(*TPxn^)F9_ZDf{btWx5mUSy#aNsZ2Qnbv*GWF#n}a>rpL zdW5aX{0u5pV9;sp)o0zBASXb;BrPLhDgC;9ny&B)NdWt4Kd!ouD zPaRG2pjJ}cVPI*K@;0f6V&DG@IS-ALeymkC1$#W0F>+GzGuf-`44pc4)?69OWS!ea z`a)DN%P_^(sCgTign9zEeXx~2_%qVCcI2xmWmBY>Tg@*&6G=7?9ecgQO@L&@57DVd zX8$t3yH9ue0p^6~|FM_FJ1yqJWqP(FD%R**KB0YG;7d>5@Vyoca6cBEKjC(kEbDah zR_aT%sojlWx8C%Wubl=Z!ygod)ru{&^9;5HWevlcgYdvaO5y<>Pp2RMiqBqQ^165a zypNfmKw(XMI+yF=#;B2Av~Mb@2N}{8jII@-Y5bb2V!I&rumoM+P)5epS*ujnm{c+& z6SfzAzmj2tvUA@;^6BgMkBt@MJXnQ~)NaL^jR)HOD3-n`~5FS4@F>%Em>ysqP`ywUfB z)|Ibyr4H3>DN$yPaPn@s##eF~=jTIt9a+sxAVLQjgFI$MSxrhtI@fJ3xpP*B&3YuW ze(2{Y4NM^FTsW|oXgZgc2hJV-u^*gUD5l8p`9KThTb;KXlU^_1s^5jq#$fc((>l*p zIr{_>x1Abrjr@3%WX;v;=iX0z`F^;iKS+K$k7l>Z=aZZBQDK|k$g>Zs4+Ut$3#oB? zaoW4HvZOWVn|b%4ZvTG=Qq>Jqr_h#v8IJ9{`nP9`w>$H8U=%Q?SA?0?z>_1)B4$Xj zPd6`dvye@zpqAR#3D806>vK4=wxIWwd)4X(-LXL(l9b(R9${0w=SA1#zG2h^CXK@w z)!2%`^KWic9KwXWmOL7sqUWqf)i+>*@R$@_DvUTY+HO8X`dV;cYl6bvl2kl3^Q?iF zt7v;z==AR)6ZgF;{L>xX4O@4HUk2XU7#m;a)9G=?X&%*}Acyl}lXL9GWW}R3zVZ&Q ze19h)^dy~>=whkO>JO#})`s)DvQ6|6a${0ShNb1=(#-30{B#OpXg-n;Cj^PipaqR6 zIk*A*gqtz_d7md<%6w@h^>Ufd7XC*$kmBU}&GU3Lca#wx@VU(^h z@kSnZrn@QqW%F%l3b!OeW}kN|=e?E(m)0Auw4xiw%%rK!_QfEJN9)gac)YkzG#Yez zNiTWrynxyVfS}b*T!-6p<0r4ydYqoS$gMDC+fL!wN7X7u`G7rC^smBAf{#11D{?|; zrh4Xu{)o~F50BLLEkI9-lj;oaglOULEcJ8*h{74Z)^wsNBzvTOtD?G9RTlBfxJtqm zU^&eTWX0bIG@7-THTRGeAC)^d^rz?Zt4D(sAN1#nm+8c`dsFYWuIWWm={SDB7%dU~ z_`ojL^3K=B?##0>Lk{gF_fkILNb-cwxnOQFw0EnP?))s_pq7alu}8fmA`T)6FK-zl zap=NO*B_2!6=7Pw%DNo<1qitG(B|klWK|xO&4);AUCeFz1Lky6M(?7`nqpHCNiTc^ zmqi;07sOU3F}w3bG+UP(J#;&zOx$fT=aY|*zGZZ;Fd_!UHw^u zYu)xlZwF}fg8RwGWd>q2?bxBO7gv~57YTKRyHLy3B~8Y#xt_j#fSPAtzohxo-S>HD zrG$FplOq9u+~e4adR_@R=ejzk3ZV+7YQQH_76fZLGG-(4;o^KP%x-v7y5AZdXp#=b zm!1v*D)(P4P&4acKE1|Gsy4^@JH>xL3qtj`qhI0@wUoYW9=)?X%T4(#%`C2QuIzKU z4wEf+qdX1e?F%{X>{elFQrJ&3QX%yPN`a0$?~n%ao^5;e@w^9D>Sg-1N7P9CKMy}4 zEu`^R2%IZo)uZr^1^e$F($2TxF54FZA+U(YAa@;=wTPE@K7Kn;5OBx=W6E36#afbR zbe+xBGK$}mKeXlMyoJbJqWn=%Xu39K|eVoA4FTiZlRjyjmy+>=MG7nQX z?Tes^iNQ%mAs3x zqEdz3)qj8knJD~>Zq=xbynEtC! zp}r({2GM!g*vW2S5lQq(8JfhrO;aKs87MCfjdm-8fhlAz4CEY$9;BfeKp3EAOnJGB zdeqSH2@3LpjX}mYxn3T2TF_pI555vPyJ-}~Py%N9b|qti11T$a!?|T0g#i75v4t%p zm~@Q1TxCjsf6xSPR_+Ff&5>c7m(&t82i$CmLscf9Q6kd2yGPqoxMMTGH+1V1Afx(& zgj0+@PL)(`W^)rYM!D>r$3;!LFt3qwXKLVv;|qBFGv=S7kHLu@IJBBA7;#O{NER;t{KTrztVgd_y=?cIWYXN zCHUU=Zooo*p3nsv2J4uNHm=i}N;#hs6C?16H$lvHISUi?o!_xm*XRCH;}8+G=0v%}|aE2ON?lvoTPwzMBo1Qr(GT(#(1pHr+_h82r6byVb{mTO^ww^4}Km zc2eR0)<))odlujR;630^tqI+yF6W1Nz&`{Fi4ek{-nz1F@$c6F;kwu$hSEH^!B7eW zE^6n;?^crROC*Hp`Pv`eeU4Kmk-X!Rf4NMZ%yQ0HbGgutmVod38_ z9v!s~_(eB$RdS8`3-Q+jF{k^i`We=+UT4RFu=U-td` zbNgTR{pZ8+&mHq4`@WT|ECr$%^Lb{qch=9dO5xQ@{(F|rCJKJJ0Tc+;I4_Hu8)18H zsO*gFjVK%R#VvHAXZ@x;5&QJ$abI)&#TNSMpYC4A-l$Kf`6rUP|JW>lzkkE$Axf|K zaNG>z?x;Vj&B$T;h_YckVC%ZsS;-g?FNj;5T0iUad|!2c_l1NBLILC@|0|^W;qL#x zC8Rni_W^+HWm5Nou3AA(X>#21+I(pvvKK83P4WcnB}8f?ARncbXQHnEwETZO?`Hi| zA<21Nj=EvM>T!u`3bLguHL!O3I-gSgaKoWkdPLjU808p?hM8s-~@N@QGA83DF z^zG%?Y=>g{fF-A7KU_`zA$$qhOwZOc&71WmDWXmnmP&nv#zQONakb%!8dRj4h%})V zg*5W-)d^=yFXX%ypZ-?LgofKFb^^1TL+!cazG>W5uC#ZLjOp?&|FJF-$)-t_$&=iE z^wdK~Gpd-9Nl<)_at7%p-0cJ;cEt`GkGoD^!a`lo20NEjgnqBMZ#knSD)Z&)lF&)Tx zMUFLrTMFBm0I(Lx=eFF4+!`o{Dj(6c4x{t;D#UIzXYay!9f(+_< zPs4pJw4r&TSc!Yvhfh$_1tdCZY-L6Z>eMSuAWq0Wy|*2cnS?t~{&WGtyM~^Gz|K2C zAt)^$PL4Dj9?q%Kr+1a7)v=#-DYJI!Uke+L{3z}w*9xPMK@0)%jCw+TOCp3Q_y!kk z-$_!$?;HNEtkVdK>x05AaW4QERz4jjsXIz3Q4&fF9949jC>Sn-020I_PBjR*A0iP% zjaD}9RFIzgrg;I{f53e@hpnPLa#cnzmF=W!+%ErU$MvH1BW zFgF5EdVcSz+>Ifpa@TL1%6-CA&7ena;Q6P&wjsPr3x>g6gZ5-AsWUc~uENFyQO_%v zYQ!c_>jag}ixo<0M^fXU;mQY>&jj_0Qr(DDI}C@Cm@vEpGwB}6S80xWoSayT-n1S{ zt12-B3={LoSxUP9{tQ^~42q8!PFf(ovs83B!hZ1ZZo-&U9`4hGc4q+2hBG)koCt4#$QFgbC)6LyyI+MtUQp}0d!}E?YC6|P|@7={>f-1w}GOnKu&L< z0NtkFdJg*9cnl_s-@WLgVCSD36-b_!h%c6vr$AV!`>dyTf8Dlq3)t7cPBC-9gYX3R z70>x`W@+?ipQ}r4DV%|3P_HuypFM2{>NH=jZtAEk*NWV+swAyDA=ZJ3GOsuknoS+Y zRd)`RNzVwQ$|vaklyw6(FsNI;C1i~jFaZw;4ps;X)*jZ*20XE|Z9MSrx|V5ZLgSCv8szU9eYYImpL-3gCV)T`IWH-HvK?ZQkKc~f%9!sj z%_iaqOqyJ?HU5E=`7xRCd%5)1@`(g}H}AQ3$Jfa4(I+&*UKXEdUaHdom0*L=^u*w* zllFCebx^21#r-;M{ zU_h>}ePcz|PPFgFq`elq)14e5CB_XZH@!FU3G)KwXfNNPoCNIox={sls@E`jUg@W9 zt^CfiLT&&imV)W$sQdSYy`8^Ah>d2iewom9m(;1mpgp63zZH!X)NveCy-r^8Kg+qD zR&JnTm#fAh9?Dh1Eoe?Cay6Jzve>=7Qv zZ?eIFZ(^#v=P{PIi~^rsFNQn2r!Rj6$HkWPR!r}SHE`NaP(q6+@#*!wO3g|qzMzy^KjX!7&$5)5Z%u{$G`!4uDVEDZge>(d=fpD3?VJ_wX;$2ey$u)LUJT2EL4w10fE!EIgis3okfuMe%!yrZa# zL{tbKChP1+?i{~Ape~retN&XqD)Kal8IR>}Al&~?O-8zaNr#NO4Njd?F;i11Z}~hF z*Wb=imWxP?L}2gk`qb#?liF)w`Wp{H>alEN1aWVM&Xd4Wy+>44%9FC!*blwE&TV8s zC&khBi(5tlLmku?ARVeieuv0m5r;ga;2DH$?XLgt7kGi6Fq$&@)|Dj_7pW0uO4 z6v~{bGKNfw4**%ku4BD9P7*{%3%R{{#Tygkosm2E(+|Vh+H9H$YTY z(jM@2UH+jtfTXPis|^y9Ktk1hIPCKQcJ5inT3{wHLhv>ZnQbt~uC}WgLkzoPZ2<%# zP=->XNrcx7@gb-V6voe(weiGbOvN~~W0$+cFs zW;V48&?YV7zvZrfTIopwnkl3{GbM~{;XLBK0;83iKK5#lm0FEjw(5K}#IM2jM71<9 zed#iWRLbexcvXS%C|H#n4s_}RU^kt8%^d~SZ0Y9}iz|2AOn06u^Kv?y!^`DNh<(?j z{*8V|b!??5BPA{O2C{zpr3J`Kt9HMIgB$`^4mZ}z`K_a`5COaYM?HrL-Oyb zcP&70K(yF5U?A$K18)nWNyabw(j8(kP#!;p`as+OD**-cT?W)nfusK$>l-C#qR60Q z`BB|9^1+S6-cT1x-HM}xsiv!!bAs3Rq854js$+LjDS@YCT?Az8Md<9Rfd)M=*>@dL zUT&4sBnAMLnyPUIJ`l>KAHF|VuD&GLKxI|5C=b_Gh+m_)Q1G0(Se0k;P2brndre&% zxsy%z*?b-(OhiQ^gZpYQ=G6V!N|pXh_8?Ir4>Sx|M6j0CM8j`6qE8$=Q+hf;I#`~j zD*FJZXuQU9Lt81T2+I9$pEjW$8pBaP0HY6jG{Vd-P>iWUt^@U zW}5_l*Jk~jz2o78TI2{i%0CeYb6C8Af_?(A@Um<*3m;4Q(4cv6KqDi}YEYgDcC9MT zM`a}9Whr_PB_g|B)VsgXr~&dM1v*Ian~9+}PPZOk2iE}+Gi90mX#9v2`lQosM1cwu=+UW@n*3dSe?rKjhgnY|;ae_lHoO&v`YSX7RR0iWC zNz}Wtp&V1$dL~W!N$z%Pf`ciPhjndFDO9q1QVsynP?Y{K8APkvnaV`D9K676br8;7iMoCRjDSn4 zpgil2Ej%`8PbzBnuVBL86}rDc9f-7Oa_tv*_`hn?Jm`2Z!=Ql))O+wP@kd`Gg;&m7 ziI?A>QxhleWnR^VLtlal;(DRBOH~~ku0$9`8A3Gl)(?BIxi-%X<|IKm)&*BuM>Yp{ z<{W$~UBqDMeruu;rujfVZ-io(9&sXV)N@M_+X6@JS_jS2VD!QvbFK zK_luQ2bIVr@YA$tits#zXsjbTx3|noLaJ6m5$Bn>n4?(o;8k?1ZVNc=v?iG_TLG(V z5n{H8s2jM61)}@c9dX5nSaViQ*?fW%Vtrbl%W||%yFdsoxaW(xeL||LI-*4mv~l3W8z-y zhjIdXA<;BDN}Kp2yUD+pM7tMzFVcKN9UXYkYdGD=o!o#1^zL;7-C)=KB|_e@Fx^{( zK!WUlveY8zy`QNJAfy9s&Z*M7wZ++O2u!smJo-(@0B?)W9R-QX?UQS*XKsFe{EJ(> z19r2YAq>6*y2r%>Ohl_yy;N_W$&z2JWB_BZqsTgN@me>Po5^>QD5693*;#eOq)(FbTI4lZhO6xOXxh#0W4HhGT=qg zvzdJ#)J|2OjCnW~Ym$7Yj#Cd_S|%@Lt+1d*6h z)XK_$qVodQ6`cJ%wC>lk5&O0kTTavE!sQwAGNdqlzK;|rmw&#b9_7ofKZ9sh@;BB? zA-L8+tJ(W~ql&bFR94Zix(PbE5#{V1(BFw&Td0JA?Nvn?g2XYX^85j%mCCqx8e;?( z+49g|x|*N)jv|06_8A^WQeJ{7uO7caei!7f{<{+uXRCUJG=U>`869l+5LFVdK^2Wi!ibbm!%*dwiFU3I%R8mwH8aIVK)dA%8J)-YcvYmoboXxG1c zJNSRz*&w{dlY$q7n21*VwNZ}jtn07!Va2 zDiPog90pp0M#7NCMP)VO$gfb$?zx9hE4l&d(J=P_)K)<`v6B5(7Q+GW&SZouh} zAB?36L(mxX6HF+Q>G#921cDniN`!ajE6|8U!z5eU+Ucb zAg2q*_1oB#=6A>%Q}U%t`crQEb_fu*)Uq4MxTjV?>EuTuW)0koKTn||3x{jRG zj6wHd*{(Yk*$<_!%@ zZfZi=V?YWdTOEvSw1Gc13ZING-QvC!?j93RY2`sm!qWfg%4;H7B;ou4ht;R;n59~* z+%Z#gM?j$>NG<~s=v-IQ1nUlsm!>EXM*ace{r7wRH>on*n)YYb9l)SZ40m zJ0q0IclArbH1)y__rcd=6H<)nMwV zK^Pj?0M$ff(`U;(AP&s;Y=EHo8B%@AQ2RJgkg{q|Eh3-kd|}1}N2O)KwEM8GayQKM zZvcD5$d@rxQv@1O&;8e=rPUJCJSkA;r#LTPkOh?4YVcOCJ9{~M4ydL>xetOHR7X$KnR@{D05|)6tE7RbN6TnsMW(8M07(L#|1=`wThTBfc-B@YYYp`t!?CEo4z?7$niPP{+e!DS+Ea2=Unfio!KUp?S#$4yq8ZZ;%1?O_6v`Cmt&8985tD z38QGvk2fnL%ReFdaQnyR^9D!-I0HGk_C2aYU0MyymDZ-<6!-9>AwEs~3V353vP@<)yfjfPol$O*@gu zzJ;Rl06yF@|8JV|e{9^Rum8%Ne1T!e(~%*oR9Oc3jL-P)lFRL+BWs6I;2i5&vg zLuJ_UaO0&-i2PtyAPSdjJTuS)O%@5tFKBmO=`eGKmmu`I(ykTtgK(^@tX(AtSQGYx z!Qhhs>P8xZ0YIg(V=vT30Jp=%z5gNXLk?XSM|BXhK`su$%o9jmX;OCxQ{wXO^&e|b_5uw!Pb=P!)@!`jIO|3f{(V|R`t8)>PWSTWG|M8EH)6c&?;!;S zuwM^zcE{#iN((wbE}q#kvTKLC!GVy{-$Fk;ivj5XA@rNVO8bYXh`zJ#Hgkr_k1$4` zBk~!w8x3E#)jbN?LRWx98Y79;PT%c&rLM1|Z<^ydmkkh3D&>$Lwn6G&T z_MlKndf?O<>dDnw9B~>Zb~psE-i`qJ@bWsOJVrn6EJYV^qF96+#D}F1CH*U0=I>Ds^i5*unerrIy<9_c;@^3<_bkr{ry7!;KQYGe~2a(|b#amHG&~%H1r9SBXBeXq0#?O07u-W1b1CZVNM8H;$R! zNu$@=!LnSf63H3}9YG4^qz4!MdZ4W^YcxG=pYuO32rjq7G_koB=5JvKpQ3opnHq;A z3KJi4(ySvZu0r-G;ZAsSMYFr}4h*dfY{wH@=LXan{hOuU=ix+!AZ6`811W!I z@y^NIgMP;k4ph3fEgB~XK$?AR5~bsGjYtOR8gGK+m)o)~ND8DUio_j2e2D7$c*_)K zrbrJhRG0v3#d&KOO*2svXu-YK`2bq9TTMOSus{%ox{`z32@6jEJ1i~7y>@;kdl=!< zsG_RVzcvqx*bE*-k5Nd0dvmY+qQ_1Bw^Tma|S(QK0!Ug{}pF-NEUwQJI!JU{MZ?KsPu>qhSY0$dJq013-D~2{#9d856bp7OcZH+&Eu)=gnz%O_xb@|kBJoPZ=~-|e3fKXTh@W61 z_5>5qbds2Ezh4D4rVBE~`T&sL<<+8*YNSyiHZ)VAt$+^Z22My`y=X(-SD2q3u0Nt%a)7UoJ{A5ycJ_AQIMTU$xnN?Lxo-ZG`PdN6^JxA zYRPhd=O%dMtvcw1V2}N~E&ID|-LCbk;zIxV4-S}HRZEqFCSd zW;2O;!U5D9zxXJ&O%lc^n&xoeED}L}LlylC=m+B`RwfuruY&;(amVdEbFxld+lFq4 z2*%*?5uGGg5a9wt%wLWJKx?c!TZ2YpNWd9sT|tOUJrVNc2dOq725Pi?I3C%qP>l_~ z&44pO#GX5DnrPiLG7GgsHp^4k{^y*@{d$SEIQ>uJN*Un6$iIl@eMDcbFJzi^3zx35 zPZB)-6f7Qq2%H4^|M~U2U1RZfx)3eyct4@41$cQXE>IdG*)rPr#)uOM@IZBw>(A_` zzB^Fse@1p>NEzgUbTXdHh^5qOFdhG{+2g4gZ(%t~=pdLFDn`1H%c?x3ot`uU~-K(+C}3*{k;H0uq{ZRkgaJwKup2@s9f)# z?2v*J-!*=@*YTYkoDYu|dzsIL;D{s?aY#AT0{2~XP9FcH;PhyvB)N2@G11Tukh~h` zk@{2DilE89#SeJbkAApr^cwev&xgMa!q6J4XLKa(QCGFdd+0Ujr96B8REuYp3v+rC zwU5(Jz`y8aTLU^TvHEC=G*eGY^ZQeh4d3b%&1n2PgT~)|%RhBD{|zY=e!4Jw=l=iw z2ma%EzA}OIID#_B)bKCY&c7v>zg#>2^#=OOwez3X<^M<5&i|E)0*Uwk0^QKI+m9&X zz6TxQ3l1)UC(csJzS(^G=mMR^`kC|Ir|5*<$y}ylWO#G+*vNScT3?ylvZs`4Pev)k z`&V8PTz?vQaj`+wAfC?mRGdul;4YuuTB>QO^Pq3>+(g0rmg8R6{F?Y0Zho|9?_=jj zvaP~&w*7>P(s+lTx#OQ?@%To;Pf>9|M>U+`&X&pQL_7sJk?0Ouk345V}nO28rooJF-A5^buTXd{UiPD zhn8)lPqzKthcg&`(EsjHiiX1YB;Ne=a|E*Cqz?0^fBkE&OJ&j+E|R`pr9VFEJ&PfL zCBXrb-v9lRr11{Iqps}B7`lFdm8xv{`me>+V!$Ji)ru@SllaFq;g>?6Ov=&d;(z^1 z!N(3Kg?Cf`=#vM9NoD`1Uu#xIbOaWP=)l^8KRzn+G+JEsTk+(q|K;+b1(MzmkD@B$ z!gfew4lanR|JpIszOVzR*)uM^`{PR0lcP_jsvmy%|Lm?m|5TIn@NTk)@3DA)vtCR8 z^^0Uyz(QqKlodz)@lmNnXmO8zn>_zN`}og4>Esn@c+|lKB9*hS8^u*${yGL#tgr*B zYPr;Y+baLClFR6mEr-w~UHIFP`7a*z*YQFdsqC-g^)JHLU&rg$LHg@>{mR3?4=R6U zF9^ziWv_pgNdL-Szf#Iy#o@oG9{(y1QTOs!arh6_>)-$QSMP<=>|edt@9PW{O5O4Q z>b;F@7hwW ztEe@;+UFHPhcR-m;QMv{GhY(|4sdoNz3J2+-~U%R7Lss&_py1+(oOZ%?3kTYr)Dpv z9NoN?!oP=(f6-$@YrZ=wwHxpB!;um*mELh<6)zqW3Ud=@dvHFM8vMR?j@5eP348j>=RkyuF9cmlUgrZ5MZ?2*GjDj; zH=5j{H%S}{+oGb|Ka*Agkl-9?sd6my{t3Fmf?5+!`U9-oW5ay# z(y;pn9FcUn1BfTuldzud?g9W(cJDQ*=Kv9wKS^T%xPW>FgF=u)&<@^yNsShtZeo%J3Bg0j_csXi5 z73r#{*`+pWZ+xG7SR<3xL9Aq!TU^QT70ZY*3641s4Ib3_t9x2hy^yWj*G7zNW5NKQYYGW z9^4u*JbJIXBM7!7d*OEruEAw0%rH>oF4-2``htXI0{T%GlJscu^LCyp-5(OEfzz{V z`Vpji$;_ZbsE94O?3%bCW!x=Zxt;9lsKycTpoBoyY+^)%P>685bZ>3%J#reh-2I{; zd2JTB2@U5vpA3Q^`)iwSt%B5Mi+ZiQ_^AwJ$^X<;Pf7d5Ze8j2*V5}n*+cW;#(~5>=@!pLtF+M7gxd5UQ%Lz;23Oz(&F#tyL0oq=}uG12Cs9kx+1*-+ZN5n zA(fSwje67fs<>%2PKpW$U_YK3lE-ZIO^6;~rP%kqoZQvg=|{4}ta%5B#YzjLGkM2G zfmjymzuA1p?Wd`mM)7wxK5Z^?L@UT4Ev8oKvGkxg#d+XP|1D2ad|50IF52jTB#;JQ zH59S(m4{KG-oi?S_cZ)OpRp7LaL{!7;W-(IP)mhjU19T399Rm? ztCtgIgv-0kKeF2i;-Zu4b#{f?Cg!VHGhc7X>lG}38^QgdTME7O)vFteogX6Q*VamR zXG&EHUr35LIbGWr1b1Y1_7Th6Z>P>3RdsUhT}(8$_%vRaX?b1jlP*bUJPEhvjfttk zO1rhxr85)RJ@#hUla!cYaM-D3#+@2W)(d*{GUJu_&4SUt8Z6!c7U$=p3Iy7 zZnV+;`zbRd-*P6BJt%q#^6l*p)1J*c_v4+T=8`wNI4fh8nasY2Vdt4chQ8-`;l^5( z`O=Wbk&x-pdEZU_JNivq275DZ>WBokniW=@dc3>uV%_moP0aNjA3m2jQJ@aD;gOd= zi9L@`etsd0#q6;Mg=b*QZ)wS63W44$uL5o5AX}WTHU1SR4TsTw9nNk(^hZ#|gN{PW zTN-1q*&6m9u@(!#!TLxXoUn`@&>pva-TTx(d(XTVT;kh^Mrr-k&&`oJMIrafItVB;xA&%my`yZTFI^BhTaOV0{2f5hc==Rclf|1OY|;#`goQvBbJ{hOf;Nd5Lu3t1 zfMj(aS*y^#l$E~2#S5d%d-*-U9J+QGv$+6oD7Wyd-rTi*xNo!;`|QDiC#NrQcgM*i(l{My~v60QRS*+q$n? zey36AhmX&4?s3?Yxoq_g>f<1rryzaTbWWSfo#L7VdgV5usU3~4i}5|*#+(|*tZ(S0 z=QOt2`v%-GeHnHxrX&6Q1P?_;j{Q{T(#whEH?Dl7zc!QwkvIQrp)_5dfq>&>gOfEC zwJ~$0O|)m576uj4od<8VMNJUMPMVBHcPJRP_l;+=>wlNVxGmDSU5x^IM+c+>{hgh` zy`9XOAAM^OMc!|s|C?{7sp-Cqe5;Scj-DF>AOeN11P%zp}paNEp;F%qz~9aEDCYV=qRPkPz(s&-zh zwNb@2Z%-0dVz1%mjX{%_VQm-pj_aBZ;IVS!WjkIpHfQm6bP6?3xPA7ZY&b#C_}L$t zLQnj6i_`ICwLUvOYAFzjI&rJ5p+y?gf447t6Z4|pGJVE_q7kIR)0vfIDNH+)3YsWX zXc!FV?>vE}bL~8g@o>i=2Y-~HGVCEUbjpqp{8pCD(gmyh-3y?s9UaDL#hSucNFEj6 zWqwN@lPGyio-^D0HUImq1NrUnQsa+HP~dSfGJr~nkTk_YeBxXa-IFP`n9b{}b($q- z;8GWx8ucdJob90r_{nIkwZoz$;Y00Jt)u*cBt?zh$1rh60>na}locMv4DW5n>?JY{3X1H)}?Hy#)p~zf5T2i;&<(P~T5JD!El8W?Yj`RdQ{Cwg)yZA6+2SlQ- z2RC|t23WboZ+>T&(*9N5--D<)o#(cdmx7A_4rU0M8l_vGN_!od#C}!gSUcC*I|j-r z^~jZ(vp5I>PYOs^%+hT4;Gh?8qOvb%$Nd1A;?!o1+jh+~N|2kMdi&=>qc_02#c9#v z8)_-4rd9ceOUQAP=Z}O8ZWRwIH|1%JOp_v|GnZa z=|fLY$i}!N+|#%3Q11Zt{56zlkMiMvBTy}|0%35+3FeJ2(_p0JVhY+J$ljK^g21TW!DOa7ZUk!?+QWVRMSbU%=F_YGx7*bp(z?VcxUzvnQfCC zskijbHdH5idSDO4Ip1RRU7+xBq143^C{0c>5*=FMJq`GcrBa&vk@EV?snLPU=YTw@MmGRFQ?cHIOY5jc zZhZ$KPRAl+X{PxR4k}>P!r=MIw@`vfb{v7&Vb>tmKc%uUtX#4OlBbK2jwW_TCd!|b zHoyYbei+@QrN(&JwKm2&xAe1KRWKW50)<4)I9ts3DG2(5$(A`H4L_X@ld(B@+;;@R zvIcEaG&Gi+5|drd{WJPUXT_b4#Pv%DNuliK7%VKjn|47vo^jMMILPJui4N2iTn~d@ zAUVOZ{T)Yy-bM&n(GK&5^x&f+tS@ePak8|Gvi}qKNj+fd%8gfLel1C`L*!k;B=e}+(hJ41qDNaE(yjpo#Us zN#o+}KBY~P(cEmCo#%^pbWiLtuv5rR(lt6m4;Z;Qx^Y$>Hy?jTUeEUVPDrSc#`ehu zq^X!bgzo!Pv?X|Pwys`mU@`E$rLLH{{t`*Zi=%<$67H@}Eq?l+liD*Rfb6XH8eMQ@ z0sPTRJN>z?w?v13y5TlCxf0J0lUps#=?rda*mr#zIGa|eG>9n{R$=je$uR2Qni$gA zn+xR!)8&>Hy^_G5*!Iq_t+pPGtjY~PH2IY^`X3`-VK`qbvc zEE6s@sVqR4{>cY6`#{H&-UXj{a=YJ*==<}~wYB7)c{KYvk3pR#pLdy{-sjAzb?8x} z#`lMtnvlJqGtD>_=15s*ovm{4z_^7OI~}uHXgIl{xN_#TIm(?}tZVl~{xZqN z+0FV4m20K%RQ)*(Wxt&wH_M>iYpXGtGY?-e>UmHsd3ST=5Owh7g)P40$W^G}>t}|VleQ6h zQ@5Q3De!I|U_3tb8_QGWLYP_<8`OaI z!ZSGQKSE0!Ec{I#6eDbsL2K0_B_Et15la0G88P&?!SJ!%_kDx$wuTEh*++Lk(4M{e zn)bxd-DVSaAAz|$`pd5o*rGI3Kr3d=+bB_B82b=x*fgQ%eNf_9>)?M(Yb>ron^|E8 zl?S!uX0=MI;**aD9)3w(4z}~w#{%m=#8{}w{odU={^Dlw2klmP zZbKY7(6RAPI}Z~Zgfn=*ZmRt{h*W>)-scwYdo+V;gMK&XEj=@tsZ^{%w_D4%PE6ub`RLm*IJ9v;oy2Cp*4IL68}^l-yZh z^b(3JrNBGhOyE7#9hl9$S$Y}6=sSh)9JhVxbR{0E;X{98OjAJI z1I6}Wk)mPJG!F@EAj=U1;tI{Lm9M`f8sh_?=tpE^aJx zX?OD9V7Y9@_+WWg| zsx^PaQpg)V8sAlNtHCiZxF0&n{%(8&ThlTjW36IL(n?iLgJSzD{{BVHZ(iX}EiKAWPg4Odzx7|xdz*S{4!5167NH&&}W%&l`uS649gA@7 zqrt+ghMZ1g1x>hnJyCf(Y-15WBOSk{KM-z}l~(Z_9m>BfM%kLz=O52E!lW02!(+Xm z^YyIF=L*NOG$fVA>4y&8t-jH4P8}~qPLkrgciDAEG2)oKlGQYG9aqZ|hX$Po9X{9? z>6~_>I;Du_jH)NW8}FYz>@2}W<*W2g;}l`c>VXMo{~mI* zVi1g#YAi!tS|6NIs6HEhV3^N)DB-(-=FX`-%x(wCTcwToIZF5Z%i#`EVAFc&cJ6Gr zOD_cWNVPMiqW5-8B!dg?+Fgmb65Zl#ZFSKgsbS{xyi)gzdL8cL5r!A&PF-PNj%#ob zv8g}qa#;8A&=YJT0PLGb*j^Q2$8%}9J`&Cw&^n(vb?>4<@ryjZufHPwy)zcOb7D+& zy;40tcsIPH*1d?tEb-LOXbRT$nRK1~7JW!Iw)8T6qd^44m*|40xzb*^EiK$;3;yxR z=eaiLyFScAZQK^gC382zl4(D?-0QAO_qj{|Aw^+y@<8VB0Aa_{oy?=0T=C>VK-Ctyp?lrZ)@F`4G9~S3J#ibM@EH< z{_h3k%N1EQQi|7#=c7pImyRAoXz{Iu>H=C~qh|N3JSlBMIds*2sTNFYLt6O8hW_JU zxHP7#*Z0R8la%ulj2t8h41fmDxy|0qw)2`PuJ!2&x<{u{!#xj>$zR>xSqdw?Bwv*( zEvht7iEs>6`HOuaGdI^=05x{VynhiZ?_+d5A)txh$Z)BpX?i#ESg;Yn4pwj|CrC!9`gm$#MX}M77Ve_A zN3bh5X)l-fe6O~{b*r49z}pB~B&!~!#a&H$SNfvXgg?Nju_7B5<0vbwhmm*nN5cFH$9CJ2`159WvDV zoUFAZDSIc@p?!j1uX(JD+CD**#aoi$;!4H44P4h!1GWR>Z+I%U-<`XA) z`@o^YbwEFQ6pGhE^vFYGCS&D$d04W&%DU(x&O>+ObH#AP0O0B zRpwI;7Y$L03hpfyOWcVSQYS`6pT-Tp(se(L&sYs37iI18Ze07tc$?tol6Fe;7q-fn zAJrP!`JdNVaR9r!A(@4!vG>L;p%i!BvwUN{Cfizfo5PaRk5_glA2_uhc1SdKK$vvJ z0H8|JNTSJ%;9QgbB%U`>4ZW+)bSn~c%R{OBPZ}rhYjL-fCYm36bas9jmb;SBM4tJP z(>|SPDo^7hJNnhsD>}`5E~aidN|)mwG;+0g;eIs+Y@?ddDawU)`*x1wWktemkyF<< zu`Bkcf)DEn*5Y~sc{nSF`)Za)85lewXql07Ip<@oh&d(^J|(M|tO~~${TOfeBV40S z_&6E2s94NO42`<)nM2;jL}TOw?N>LA{23>?&M=op?lY#^9I+(3oJ~7w*AZW`nw#d5 z=%2pVkkxe9d~)-om6_L@3}x+;K^zfxcvJjPV3ZY=~l z6`^!iMFAOQ1jY*G)%P92-NHNB90an&W%=|smkX<-OgW+q7?WMws0C`O*hlRn+X#PD zXCJmZ7@Zj(m1MB;*(q8wfv*i)I%}&d9I120>ciu^o?V4Z7>_fK=wA3W)k(a~8#%Aq zZ&y$Ii%j`0>U;bYa*NS;6Snm8c0sjGc5}zo^g>DH>hmqTE$q=JDJp)|{wB^$7}fzP z{ye3v%kKLIn9tNGypjp$N-p(~Y)Z6ZPEnN-^`uf8nAGG~sMh7J5Wf>q=^Wj;UIO!z zL`jht|BU-_8Or+(4``oJIPVtrAoyqSu4X-ZOVh}X2`^6DI^enOvXD?Iq>R8jt7*=9 zJ4e%XS|2II9#}z6*VMHPE?N8V=08yOjG4sFBSa#WhHyb9+IJzExLAFR^|cx#lh&b4jMX;Rja~{zmhpcfVkZf#DWiy|_dm>ER6fNbQa?gVV#V)T z{*XBSh`*{Vzx9wDAsHS%w;53&6Rq)0ibn@7V~>BRJF-^ge#}@~!~Zc(_rM8x5+42$ zAIj=jtRQPaIZdemMKvco4arr3Q*x*DjJ5$(Gd@E-u3M6AA;+7*cu3H{Q&CU_pO(+Z zyM?&aCjIjQmPCJ)HquXv)W67F@Ng}uiQ|LF2-~SMlgahQSH506P3u58xvwT)m;YJS zm7pSaJ=zJMmV2B!>2xV^MyabwBE_7gtL>%awywMlHT-u^wY-qgu&ywIkC4TGH;K$J zQn_Tz-brIa@tE?8?5=-^OO0W`=6o?&(-&L6Un9pN1V!j?UjRW1f z5M6q9@znYPlwavRU{)9sCoD?AUZJaX^v6NIhcag@?xu%6@o-KhQao4j7;8WmzUi-$ zoW>Hnuh9Meqs*JY=z@TRTg}PZ~XEnpY5;S zcGRg{9rikMTJ{P)UO3D5b7W_74osfZ@ISGjg4t@(jFZw*C#&4ExgE|sdEd}av=!hA z12S<{gW|G+g~~Wu*0OyBIR$orimPj%u!KDM*kA1`{@pKaeJ`aP#cIxC!(ydbvF_PC z8hod^4?oIgHJYrqB6)xu%h?s4b~mxx|74thsL*4#RLh=`IJ#`izMZ zYlK9hl#S$(CbZhATP%*RYBg<7?xQO=;y6SbYOK{ywdudY$ayEu_jQesTiDOIrgMYrc0&Q64ac)a% zUhLCrMEoo$cHeYwAmZb#X({R+8R z${WV{LKR!*cj@N(R;`0(L zX#DnFV;eJJzzHZy*Mv!WP~=~4x5aA^IMu)wne)b=rE@QEk*u*f12=o8ZOT#X>m#KJ zo=?+wjW1U8I1bd8HisFNoDFjsc;%QH9Q#40So!H~=j(^BbiMle<=}+WxNq}Vy=qI4^ilz}ozAj2!-J`>0!@7% zPusf2Y;V1FeAK$pVKeQ3?GTh|c$oT)kFA^eHgo^y>`E3CpxwGBID{R=+Dr#-27kK{ zEl{d3lp}Z4^WGJ=rE}g_n>_EyfWgPg($@|50Vi8U|(58>u z&b~2i)_Lk7M^7o#Lf_4wAwlk4CTT~v9K6B6-uo)Xe=Vh9$dL_~TC!u- zO11g&!-aa%OdNwz$xOJvStUb!qBcrE}l-eg}2rsBztb_41kV)5oLM0h9~i#O?FMw_OCPVkqm4|Ez*M)KS@?88RNYdNVSiB}43HXJ*509cP^vAO4mI8` zApfUP24<4i&!3rYoF%79+~uZ4?A}AL?p8)0jt6G)B@c7`q&k|FU63 z`OMvzUlc=VYUNMKZ(?@rTD1-K*oR|>`K0)rPMP76DZ1Qj_grQTWV~F?!p*>J(?>c% z=kEnxC@VQmN4eB(_L2Sd+(PZcMH6g> z+C6O^64To&94T#iO7{$d7LBk?vtZW2DP2KquwIe#)Ume!Kb>`fuyGN!J_NoO#M&WF zVn1db<7{emVQsYi@P@aL^1Q*yiHc>TvY=r0{rBGR(4L(B$%h|ccr?{$GtZH%^poBG zt%?sm6Y_&T7Z|6GVB+`=&Gl>YSsr9IV2S zgUmYG$6J1WBn+IOWU*iaN?0NJbNb0~6_V7*BAEWMT`v&S%B+0L#7J(Sk;!h>fIYn9 zEr~Nrk6E5>Bd{U0vy73(w7rEI`B|WeRH)?_aB`2ri&%`>o;qfl>2^5IO?j*PyZi!c zk2zj2Wzkb<&V~|gY=Yr;xh;mm#OtOx=eR==hE8hydTnD$r@6-LVov{ED`L^|pW;|z zaT{Kliz|kGc~&t-T4Ku4D~zQ{hv=6wvN#HKc89@^Iv@LoYkGnwYfm`5 z3>~(f8?AV~OaY`R8j41l_sTZl<~)I5EpI zCKy9*D774l|KOz5lK7Y2Z<5QQmi8W7ReiiWG?Aa*^xrnXn7?@$F~|c$y&}hPCwH*2`&m=sGPPg5i5{8vvmo2$A*Y5jpFeRA%uv`xI{E!$ z$PCe0cK8)C9Wmb0$4b_#_|lK!vqqom5eq!OH>wMnTvqj^znd}~T3eg?2L1s|?O-zH zi(m)Z%d9NSIIaQvHs0fG+!q@ylhS5IcJO*mCNzl+KQHX+FyOSTBuu{`71m^89Z0Ku zlg1isAT+@?-M-bT#me&lj-@(&Ln~xfQL@ui_XGIQ?3yU-3`%1TP`Un1=E_Zv%2xWG zI2vJ!iYwxCFMd_09f-b=!p4px`y)uLrG!U&c0nWv$O~~%K}$Cq*U(GzGVW+lUL>a^UomoWfqFd%cjbEd+2>%9;*086UoU* zoFKyRDJ;bD!OT0{?0wg0dC5n?j9dz%cf&HYT3z1G1nA9MFYeQ(4C|RWpS~wk?%tn1q;PJh*ITm-9Qk>NjUq~~{D%uSug{NvDPTKsG zw@#0bGOp^$bqXA2lsVSSSFn6w;?bx&L;~6jqtB0q?Di0Mhi)R7^!%dF=rNaaGz`=2o5a)n!?qZ zH$1G(42@Qno<}CYY3RiR$}2o2d5mJU!k)1o-ZL7Lk))f41REAY3&zHN4R2Yfmod`I z=J35h+(mo&h{~Jq0Q7C+PjZZ5X8Lf<*j0r#COhrxvlvmY%3~Gphf?qP1KQgvS^4%s z?)>^$iSB1^j&#VWxQ!??M{1=Fqw9747BgqZS==1m#Ea13=3@L~`QUOIiWT`R@n~x9 zS50_7xxep~SnJUk%bhQdU2&6=`I1BX$rX20*7FDh^V@fjC7!a~7$`{W z#X8b1Mg;@wKK?0s%<%h^^ov~1wwB{$uexMLUSaSQnZ0K5^^8C2R1g0mT{41aUk93j ze&*Q>b`Ic8?YB?Nfk2-|X^T&(low`0<8w|HmvSkt=SBHxJRe>WQP>7~%hXdcw&4%#XhO0YF~0`k^T_ms`?0OXWp9_e4O*Gnl=xnHDqp zqudnBUS*FB-FmL7dt|hVmo+Wbtg()n_Q~-A83BTz;g#+p`P2)WlL}IzbcAQu@^-2z z$$axoti5uLf0cbboLgFPY|$tD^&h3RGj&xy3GO)ax=|}WQnHX_)A;4XR`!rY)H--Vtn z7vB3U`2G$;)Y>#>-!X4zM;8Ak^q6*H2cg)0Iwsjq`)?ZK!fc!fljds6B`I z2t4$bfH#Oui>!C`EVQ1rNl>P-z87(TzBfK_h0wb>?7-S=3JumFoKkYD7bt33sliFm zHQlf2F`5N`U}2Cj?}A4Hu80=FzKS`KB$mubL$vx z(z<8Z71zVkI0J0CWA@y5tRyqGZ@A29C_HI0k1q*%|D>AGt3HekuaS5&Uv2TB&+h>t zqqHN&x9aV3gZe||e~4L~jxjJ$gWKmnb`G~6)ew*~`=n)`$GIU06y0kQT0N$;9gRQf zN`+%S%{sjB0JaJD!StIizf#nl#8oNXK2~Vb>O5XEvC*4cdTi6a`=Len9Mj7%w%crO zxp0F+T!m8n<(|#p<@ED0Xfk?^Ir@ny{i%9w{;=Rf0kz*!S7_O%TY$l$Hs(RG+1Z=E zbaqDaYo>T@n}3MJ>i@&uSH@M9wS6m~9HddYK?I})X-TD1q@)EzKuSuwK_n%lLs~$( zI|QU#Qb799-SMuCGjq?}&;360JiqtL`(eJ!oMFycd+)W^zV@}Q>mQlYJB7j<1W`*r z(-z{K`s)UQwE@s*7zkdeVk2?f^$cY@^ay{-ox5-tUor{q(cY7^Ppici6i9ja=ZFZo zwE$uwQ_c-+(!)gY&3yojd>cSLir!sgTf8qS4|9ZHE|b-OGG zOPpTvV(zjC)H7Q=GBA-AP0UT~Wqay*hpy?JxH`gf-IE$_y4i>y;%~HeVtSo39KVT@ zJ*ep7SX31s-UOoNoI%q+MM8@u(<0zmPQQmSe|t?NA`<09ajV1y*F|HLi{W@tf{z*B z%B@bGcduUMV=)KZ!6iK+s$7H%^_gsB?++}<5GZX*KWujarh@!Umq1Ih-ic9xU%S?4 z0C_lr+@C3;gQIpIAE5?^@x3c;6F;dLp$nC#4nM&EXqYmWdp~Kfbf~JXi>kZL{29~` zBaKUb>Zvw3xsAW_}z4!aE z2(WTlmdsxXVfsaSI5!DNZZni@Jqpx@ykJUj=q9S}#(#sMc~~iYqst7Lng9s4 z96-C^`BLU-y~(OqiV@$S76fZEMo?j-ozOFeSLb&gI}jZc^w{L4HLqAV-$h&DUIa~E z$LF7-H=)P|ZSl-?)Q5y%%k+B#tnI6<$bv_W23v{wQrv5k&N|#Qx3iFzZq7qcejm2Q zG*IDxq(al#_*tY}N-fiAC>`n9+{#dK`%MDZt`9()2IzG=>P90%y$tU*FphX?@v`;!36tq1Ut& z2)o!3d>y#Fx7vP6-ZdIi9g%rczgUTqAP;s2{D)BYF{If=ap^tSUVRN_kZ zsh70;X6a6q9RLqPeh!YB#KwNlo)vU>+wS3DVD=j)?V-OCe@^Yv zZG(BLm7U|KKDK;J`h_wq;&K&)swT+B-H`?&+ukI-c^F zva;#)O>gNHZB;j#@o!e+BYE~eYIK^&t`VaWJSe+_z_fSv+#4j36lO1wP^husz-#uy z6gxZT&vTRF5aP89fSY}^A9X}3Ecikv&8PCYrz^wn;YlV5aKtitZQ>b-V0t7{WYkv? z3soL$C{dGq1fcEZUt(C7JCu(d0T5||iug6@y6i#j=q7FqKY6q&(I)Pf1Ik~Tj{{Z< zJaKNuH{Vqe)Nf&k-;VVZWo*Q<6ll5@iW}XIiq!T1?Hzg!22hgRsP`-JQny7Ey`zHF zXz3EItLu54NychQyp=6uu7X+L?BGk94UeEaH92@R*|)?ec74LHwek>T?)rD#C$F@J zO8qW|ihu@$=ItCXoHCI}z7zs{C60|p+5`>?=M@6-l5;6@NgN1tES!EOAeY@gN0gOAJImorx z?ucdREypu+{H$laxlkei60&kW2t|3?$wq)Wn7I-F*F$)sYEf()iiIIYxz!rOSLP#sxBcR{h0h10$E2={;^BEfSV3-?C(j}B4aCQ{o<01OUQ!; z*AAL<+Q5U$dHIXGLH_FWvAC(UAB>k{B{xR+%SzDN&RWPXx5+U*g*i9bWb8vaI>U;> z_|^xa)^B+iYo13e41MC(2UM^9VW5i~LlO|%wR^>D%K=zPdr9yD2)0TgE4?A|&PM*J zMRmtW?kVFoqgm2Vj<0okhT-SOQrV#M>#LRe#o1bG{)&hDAGY@6Tjl5Vf^8BKfgxFt>sS=9$-Cq3St(C~tdHiCimx98*avJuOJ0IGqwLH* zOSfB%jU0mWDoe|%EP)XHvl1E!BqIsI*0b{X^Y>OZCjLD=22!g(sBcaUrClq06>hY>-Xao}gX7}>yl!YDSk@+^@8oIMA!SB^u) zU(f8xGmoCua>$(y*pswb_ll@u&OHj+?yFeW;pb~qhfH;7+KC>PSI*D0hVWyFkjd0q zsh#*2^E7HZWJ(Dp)DH-#xF$)S^vA0L3I)Ur@Cd8KaG{G|toA-8X>~0zDoF*jtsgUe zfZ|JE+kE$(6G}jsHL^e9PWoPgWkkKerd-tt!{DoChk1hP4dDJwUvXozDaNSNb_S?D zCr+`kPrnZiw7Tc=1HX3piRp*VRnAQnxSt;Zj8fu={#P_o6F?|wLAsS0(xOS=h9n#$ zl+|g!WP92H=*{K3)0t2=x1a}-h~o_(7RdVdASUzSDu}hqyN0P;YqUJNIIMSjum#J6 z>%q9m#0Aj=tTGztI1NaQdLUAcV+(`!2RX3wRQcSLjMFyk{BXF!`~pQu1@Ekd#Z_^= z9?%$ow`Sy~`FZe%4G8~eK+%0&?_F=H<>*3;n(z%Te@O!pFP6L!Lk0dd?cBG1KX0%& zz%a0Kf=Uu@W2miB%N9PcCaC4#jp@yuI_|MAOW+;#rNs0VkX;H@lq1&yP#u%Gf`t4R zTovkb(gX#e`4N}~JY$^Zf{{sDJ-vh9+5k9039SdQ8A;rjB*RLi9w4=m{d(?`OA6`K zvPw9Iu;{^V@u{e-;@C6*f&344eo9Y93Og$w#Vb@IAB$bsqQLoQ-%$^2Sl+7y7F`T0 zJWbgW1ZE)&4!S;&s_@LWA9eya-It|1s9Hn02~vz8gVYKi8hWOKVtPx=oOc4e11fcRiH4yr~xnMI{mbT7oHeo6ARrteMnz=4r zw;I6b9!Tc2TlGM-dbB+18MR!_3A}50zbgOBIs-bf_wxE_=Jt+HdHW((eyfZHpiES^ z<~R5FyC~jV&i@nwkyA?;;=djVC!s&$$deHr33SRYo0ICaT;wV&e(I2eJ)=x?M_>lGqL$SaMwSm2U%6v52fmPU~w}?>Ft;0ICod| zhGo_tlV-kL>%`r7j*AApQy|GNR~1xNVx~L>!dxu~ zb0l0cQV5iNc0c1g&L(xvhjr53F}p_CEUbWCSms0#6?2awkX?%eVaPQoL`X}=&)^#`Rfy)?fE+tq;Y z^I6`t35E6<#LPu@%r#4Y+nQtHvZ|p(A#mlE5Wz;RVs8Z(&SpvH{BWXGgUf>zoA7Nh~qiJUmPCpG389zr;AgejaM~ zuP}TB>6(4K&7U`yAf%#0Hl@P#+$Z^aG4{X@&3g&ZswJTL6TWq|!ReB;lQ~)JI}4SnFK^{E#qK-k;nm`7LldD8PZoEuP%>ocn_| zFaz_7T$>x;_HP~qZNNBJGT>9z&PtrA5byN?0-}ErMubhehvVE7oJ170@x~=vlf3)c8%*0>oYf^F>3m{6w?3i$ED+Im7$!ds&VSwF)LT)`-VR3L8m>HA~95D^oNM zmvmftByD{$rgD5(2qTQ}IZM|l1#PxOzfRV<)tdNR1CR$D3h$H&ZW1r>>-#)VITS4~ z%4W_fos|&GtMgxdGPXYGw@BmwP>yC;Bg9SHKvkNl;xAS3qp72f-WM(X@8sBS;rB)MR69J_s26ig|UsaZ7MMOl*=<2q@Bow08jZhaS`vyCK*L zsoijPZnkOR1HSCK zf}E=BJ^QbwkB76kx=-%Fg+o5|hDN)+cR4m9OWp(ibMn?tX=HXy?On)QUlN^rJb78n zj4blb{w7jihRY=2A3qOJK$3g8Cg~QgtRlTXz`ZWr&TWoYRfVfvR%pZjm_l(e8U^EV zf;p;laPdQZ&NQ<`*P+RmA16!e7Co@u`aO26x{LYk6wp3Ruw?2sPyNDNIgA5&R6PZ6 zBRS%<$8eJVFxH5U($k#8m5HN3FR>3)exc_ccJZ>ka*p4=#t(ifS7Gr(pSk#|a}aNo zsk1ZMCcqga4|^)?y4CZZzXk$OZ#{PE0@coFw}l_r>$Y*pe3cjj&h>^sQ{jbq_^+L) zOcbP3%rrw}P2n~3(exQI8;!CuwG1pnrrx+$;RX7vs>}R#C1Q>EwWe(Uf=S#tJZP~yyfyXz^*`r;K?jnJn=S~ z#yPU6cp(0pIY%@H%af*SYe4tj%r?s~T@@`d<8~&7S zh-6#t^U;mPoHUq>9zS)s6)iOhYPU#f$5m@rl%2Jx2)1;&$r!B)TGhGl+Ml?SPFlAI zsl720jQ%;=W{sxtiEC8XSz6nh+Lm6U<5jMJ*whQw`uKrgZG}{^fshYGH#N-U!t`W% zthysRjX*y%{V|KBD|yTl&{7!f`wU|+{i(~DH!qi!iy&?3{!(l1`4F28hZ*WVURwy3 zXEYX_eso>KHGw^$x@@Cmv4Jy)K*2dEo)z4mAeT)=1H86I2w69Iq+%XG>l9}`UU zaYu&v4r8x*PnYoI#)^|JoMl+w3BJg^7t%}?Mx5dYT*z=Gkf$y%X`cli^d~^BT+i9U z@mH4bjfdxz`8ozDtpbBNzVEjH3<4x$BI;@bhi?ofz1BR8w`Ja z5iWg8IrkuD_$_aR6b-2p?zC`a#MDVWh4<9@5(ERc4N#Ucq27#Ldan*3Bhu^MYR!@W zr9-_D7UMRfAIR_(Vj8USOVlL_o0})T!=15Jl!C6KhhYL7BMD-}5y&FT&y8IxR|qCq zZOFb)e^qBtq3oH!NxTF`thui&LZQ9D=WYqXdq;lkcy6D1L5*WGZ=sI_T#@Xl8+JTJ;gf9saA(q0Ze6TtCovP(V6S!P$v+c{(q#gMPgit4hW)Y^1iu2;yTPYqP1u8{n!O_b?EPuSKiqDmVo zdJ!4y7cCD|PR<8Os}^N0|}$G>n+=%Ruk-*)<$ zn^^#*M^-SJ$6|_nVROdsh6r8E#5T4!wcvw-2b!*n0aoM=0{?ak9`q zd_ST^>~uG5c%VzDwr-f5*rh&~gvN;Y@%nFnEI?Dc`Nw~Rz;Uzn{^+@wkb#|`R*HC z$l&rF!y7(1PG=}<_N*j>bAxCtAD!v@kZ-fsQZ70_@@a)d?Q>IJC`s26Ju#X4SW?d! zrmjRxk^fm$Px{oMZXCQmZ4amZlXt zFxzeK+j443e0}NqCSGL^)3~A>TMiqK(>~OEK`%n~8)}s?g=CN#+4ehLdbw<;bD9vZ z2?CAGxVS8!RocPcu#~U9?nRQ}A_D%Y|jDE(L=qEia)tjFYSjOuRF`J1G zHf1mZT^bzq6#Sc*JU^p={19cKdnfCs3vnLd%}5E-&0(_ZaLz>9`EtOxgkv(Yu~$}(t@}GLZ{ym{#eSMV zXTWPmDSxfPcL(RRKi$^d=OJjxD)W|eCI<|D9}+V%CN|DP@A$antsqb#|&en6ndJ-8?t>exaihBqV(y#1vaqH!+rO0okLGok zuQQdcZCaes9FNts|HL;to>qx5UobzZCg1Rs%g19l1dypY+-m1IO?L3pPjc+YSQ1-sJAmNtu<6vHPJ{O0KV z3TVkqj6xnNa+Mv0BNrhF?FUD!g))LMU|%Q>-zHp=`#~r4>{){eS+Pna+-Ld zIMUPQ)q@Xo`6a!Y0d{5drOhwK@y&Q_t7QSCr^G7I;tf2|iu!zjBF=|yEfyL7HHa-ebK zwbT0cx(i9uk&l@o+41Xx2|(7Qbor3f?Ko6Eg~6axyjJ{J+s4HeNbiyF9WIx%ar&1f zu%XnalHWf5#!Z=4;@oC?6j+(_&FiIldk7Of*W7ZznYP*Vs;>xTn;-?)Pdl}OcS*Ymwp^NxW) z2wC-jk^gURp$`pN77U+rqOO^o(UD@Z$w5@=*qv02JC(kN65ANz4i~)KYGAQAS-XbL z2gXjkzU$B~zvsNnB|v{05-&lvPUWA5`gR;i*lld}QPPs+4C5J+)6;J*c^l-V_|E85 z(^4@;Lut*H52LwKesuWQC$L4ypPTn|_Pe2wB8Jx_X*8wGPx7CeO{ZSsI*cwQSWZ`Q z<<>tP_iZa~<#!kg9|7C%LenjEWGbzvQL)Fo+yxgRbU$#*^Glr0-xdD5X;e^ zNkicZI^QbKc1ajMLpw)0r{!xcb!x%j;S>|<;u3nD;aK$C$D+I@sktRd90iWbX0T_& z!Mn!9iplEeKDgvZWKa2)(}y!m<|0b`hxybVhVtubBW}PLT1MpLq*d&WKovx3SZo+K zNn$ceS$>v(Lz#FrW4L`#c)xy}lIn|P&*nH?UN)(Z{zzEwxI)J)Y z*JgdOa&whx%I}n`O+-JJ1UbJj3|KVjDm)Qim(g?qI(j6m&}L|G-^43U_$g@fmzShW z{@Ac9Z{(~SVu{a&R5=?w%yNSpv)v>{I(*l1be<}ge(KY;6)*chyJcwj0ZYX>KjA|T zI_D?_CvI{2>){?MxTEIbPA3bwrV~$HK??ivHqeByDVVi%O$u`kRIW8ap1gyeaPnRO z50qA%(uY&}*d*3rI>WwkrtoO>1#08_!>F42Pd_E5vg@i6)7T~kyJiK^4_=IKATua^7kdF`Rq>@IZ;e!Qc{isXxi3n7qQDzDOag6DR=_?@TbVC5&1{}8M{HQk z3~qms&v_!-t4Z9Q(VeR+>QcWLYkKp<^Fi}1mDj!LoK(_P33j(WO)2Q~cYZ>aMCFAn z=H%NfU$3vlt1##zVxOAM6_hxVF+6H4=lm*Pg(3jsO>h*^Xu25xW|_RJFKCA0woJXZ z4;9K(Ru_r3Czl;Jw1|t+SKl!9BC*>L=U7r50-DpnIaSh_n2YX>%<*d>Ns`=AOYIYl z9Ni0i*LU-XGNCI(v5~)YjkIJXY_S=y{6avVWR23^Sc; zOtV){hcj6?bmG_*)0y6NS5A4wVBM~|v(iBxoKKp`pkftL2U`d%k~>fSBASJ7+m|Ig z5zhJjQc9Jdsh=tBlLfh-HN3o_3HJ@~uzXh9Xmvt%speCTVZxzC`e8j{dO2yRQT{1u zE+SLufydRGD9MoAKy8|Cber&8v~J{Pjr581>$t~KCw+q^UTXW1!#dWVrlkd_JC)m{ zRN0L*g%c?uM2b>exU0-j2yR?Ea++Na$sWq=gHlA{CkaAo-M)1^Io~(|PTuCrWS7gy zvQ7_!?Cp`|FsoLj+yikZ&w_EQV$9|P=Nqq7-az$$?!~(_jsQ?*2g>l5DgsLl3nN|IGJH1{0 z{#ZGr9q_$MT_5oza(I6A+I3}8wfsW+nxw*~tm5pgfpt>xvXy$J6VVI?xy_?h^m8S} z@wd+h7HbSuwPxbSvDt!dyjbg&f_KS(Z!Gv27#D5&+3SgwR2Wc)nO`u7mRrv$mTsM< zv8^@rS^_l95-ZBoBKVcxZNW=7ua5eWKmK0nx+WLfW^r;>qN9 ztY4ONLKJo6wy#ljGIM8ny;fJc0uSQG{Y!b*O9r2gK?KYytTOYZ^QWYD_|{j!>uSPs zaS^y`uYEUV+x*5)+oWa@F3V~BD9==%bdq|wmbalncdB%C)S1sZdGBZcAA4b?^eZfDy!^!Bz;<8U^x0x#jo^rp+%*@%^B3cDLb?`J( z!P^VHdvnl{c5>-Qd)9@NBr#cUdvzQnFh;zral*Du#vQCj#yi!$Ef8S!5-2ALZI%s} z)7cOC6_CDL4UFaUpF6t(?Snoh(EeS-Dqzub#dhMqAQ;@rWF&{s{p1??zxYkokKOTO z-v4{^63D8CV>cZ6*E;|XmlF2t8K|3pA+x_CYx;<;wFi<(4g0{*Q)>1A-OmW^7Ta>8 zT7`DHfhF-q2;vl^J!3#8IQqe*k@Dc{ZF!jYBt@^s?>5f(aqp(1vk7D11DHd z+HW9IdU6dh%q+wOBjKxXPEPNPp-Z z^%B&%pAW?~PM#6~;rRtxPFL%RvDSprZ0@*!CD*q zx~NEeTJv$tdW2*=9*ViwMwTiAd4xI|Z}V|@GWveUqjnfupfwwFGb{E|2m}S-37rI6 zY-PZxcAANB9gw6|2HKOY4GQ7wFqZCBTyCYRnN~jDTA}F1*yo ztj8h6Cx05OJrmq$)!2q$<#16?Z`cOy`N+`TTK>PCyjX|JY`mV)krgB{+vx~iF1=~g18rEKh znR$r5=t%@551?7UYE1+{(so@jjrH`9+V%Zb!@zwwgLp&JS;eoufd;V(K6gl^!GJHK z9g=|opFYBgNFY2;KMjiOlfLk01Mg(Ai+M5)&bp6XR!->JMDhYylO7jPdsDD;`-R{j zJZIJEI$}Vue1oB10Kp>YLsg6O6v_1t0V47)eE*EBYl)S-yRvIZhAMTDaQ3;&k}B=z z=@Q96Yvb~rV=7O_2lmbJ;v>$AP#Jc5XrDd}2>)-|E5G=E=8{`YU>!*+*$5icflv4@ z^%6Itev_Z_=r?NjX{g=qiP0q+y;FkHsL~fS1c#)y#vw0pl9v?TG~8#uIoqk>LAv*N zxzsEs6y6`+@&D4tR6)Fc?-2LD><8SD?oqq5p|}NL!6@Axpy64v>Iz)*Q&&N9m_a0u zMpNIN`*_L+Z@>y4&a#wgiGD-U$Qp-h!Ftx@5rxao+SQ6>Ptq6~b^79QAU2L%@GeCJ zwTf?B77)WM*Y0dcjcJ`+_7TE>wUY7^i>Y#F&1u#?_4F7RR@F%e+-1!&L7ggiY8-Rm z;>#n*wfWFk0JL9N4}fHV0WRqZ><|o|Zt!q{`h@U@XMxmD*3>?$<5}kr#7C{~(>;~w z8JvD{3(bTwQ?HhtZoNhd|9RtqFiM{xQUsxRA0~HovT0w!q+7&=fvp|_nQmz1u!_bP zLj?&6M6@4jk-5h4VzG3plebBIJoEH&epHVrHRh*2M;+H+K|W7?0+NZwl`)`M|Ma0e;5dy7-}?mG?#oH9Or^$?!)j(H zBlGmRHwv@gY}BZqpzXT4lArT!_Hvk?NbSvVoT526O1I@7m#XZX-mQ8$4v#&2P@`#R zND|EOMYK&)iNve!e37d@rZpeQFp!h>Aml_7&el_~$EaGH&?X>lsmttDhoCRmdY^$O z>5lR8uKH8+lSvEk7@thqe_vv~XB7DL3^8Z(L59{Hcxth9+w`u=h_NdCa!~$7VCSj3 z;x6_O(>TfE3v*zf&4J&1)_;@ubpe&SApFcE=`p}`Ub{Vyzx$?(D~Q1*I@oF5Dp+IV zqM@dM9>tp#qb-tm5$aIH;+vsGhei}S< z9=dzWy=4x2i!L8`xvD&Q9HxABdV+Ofb5hd+-{0(~`la(N(uN3}EZ?z7SyvkuI$=k8 zG@HQT5#Q#r`910e8~{kyd15D|rcn+*J9Tq#xaB`4o~kk0<=R9A zGLYZ0Q76kv^3sPh5Izl1Cn~_Ge0Kt4b+Yw+ zTJGJ>Y*PZpd`=$VGoKy6T$SYrqSJ9kAoVAtZt#?b!bABn#G#~Pce#VYNPQh46w=8v#@G!{I-7qm)h^9)%fsbh zER$-q5fY(;j2TR6CWK(7lvZB9#?xJas75?VpEr)2I|_WV^3 ztXIYTod5wMe#^H2r>oZQ_gTw^loMhs%}a4CceRi?srF`!=H4b>V!zOkWd z7rmCQkWYZ7Sz!wv+*jUt_I3^=GTXw%g(bq)RLZ;sBy{=BM8(O0el(nK0b{{HSF*YJuKPK|BXtL*w-EW}hm_>MfXYaw^1-}7PnDQ^ z!_CvpdbcMHUVsT(mU0fbg%JzG-b~Zpey{q= zJp*XBnxt4S?dt}9L5a2A?dDR=jDI8LFX0Ck#w`ICC6-`3UM80&SlD+QJls*s_^%LI~5K~V%h zk~b2z(B2;sMJxr9vlvfB1TTQ@zHEJd?ZNm8u)2`4_CYH7e*qo=#{IRbauO&`Tx%(E zLs?on6U$7nd%j=M_K10UXcZXKI_eQS4qRD!Tnq@oxDls+V%V##R++1n!#HdkK`-|C zm8|i`o2cr$SXVYAkQs$$dGb+7&c_CzJgn3&2Faqmc4>u#gNLuQnPmf*s;q+; zAzg;e0X%S}LyttSkXd(GA3_f{QHMV>fZq69Iusz?-MXBp#(c%oapHD{`NTvB!5dEs z2McW=2ln0@kA9#U`@_8_6ciNBKWUX6#id?J`8~ez;bqo)a zpBC8PoUT9c;%nkyQaEOOhp-LLh-2;s&$jWHVU%o6e%%Sj`rPb<{LJ~`v^=0MiW0HE zlyRI3;wn0IX>h-8Jk#J|oEpR_CCym)_*84}nRY*D@gzcCGkY!gI%zOj|Il|pKG*Vo z$am}NAYv|N;M`(1b{!K4{U-7iP-FjgDH*~Z_EQeDPgvnIjb2Jfa>ht7EQ&rS1jvg< zrOz1zy$niG-#u;dTIcy7t|{(XfPNiw(|`|V%Cj6UZXso8dBAe3&UQMB>oZ&2%7-!@ zd7Mpa*n`KpqyYgn;(85uXz39K1DKk6{V>V3H4S2aP2e)+bz#^eBpx3>Y;RT{T~1ms zvmW2?V0rh&&MoGmVEt*PlM4|%v4~dl?SC`7|Kkq)-#;X8LqB1^3H~vcrwaWptJs~w zo7ZbK_%A;i7XdEh8fd8je>&X1?(ko}3Z~`P%{Rfq@>W39Mz6jll6Ac|?`pny!Qq}8 z<;K(hzBsOa$`JyNxk!j=B=UD-{xLX=Lkyge{^Sixj#jOFXlw-|Fj2NQM@auNbcqib zx{N>!U-*AM^biGD#y4w->~O*PCu%`+oNSAPL|M|K#-sF?xqU?jj@iwQ*W>-4r{G_w z`}?H8uwDg%Git3s6?qj{t$j6i515n{v^>7Q4vh+iHe(B9_WYj@oh1zB1pV#9wfo@w z`KxijjSyOe!9-pq6u!xT=ID>7vX37eGuDVP9_25y^`~$A@zp;*^bvqF3bMlY?jx|T zy&5|KJlI2on)ZJk8V?LT{(?XY>3=@7f)|(*qAinAW$66vXuvT&zGH(m&a1y5^Vc=* z0B!_FuNwF5zs%OZuI!J~{nv+NHgHBnbIh<$Y#WYOWAmcIM6%c`HvT*%Ldi_fJ#JyG zg8eUsz6s{!;mmMB4s`x&QqUs%LJgLWZEHsiG)I5jJfU6aMkE$m-uugJ{plNjeD#kH zLi*6fwrW8OegA4~TRiYg8Cm}LJt|#YfRF|>bby`>_WxpNbTB6-4LN$M(D{!=LdSeA z4wlbqU?e*~U=k^d#% z`<2E2lac?|NdbTP|0E+%9`nM2s_}ck#n~1G@~unv!Fx^z*rL-?=O_ECZ%$uM&Lmx) z894%$YNwnT@F|vI?_w1lE86JU+uN?1u%Ir3*gONNAp)^tA!G@yLBvs0pi9VMHT!j_ z9+-~4>Pueh9XHKS_^AFeMl3#200nFLi3eab^8^vHXXN^US|6tiFu`Qjc$s03bWb)m z!W^*rio94V=fjMFgd>XvCsUVK zaNuqeOSM|(a+(pT@|>O&RIrWvpWr8?xDZ!vL#BA?kO}45oz`H|xR;>pUStSLly04i z)JRkp&&oE)^54{}#E}cSI*(h_pAYQz3JQ)XVWxf(^~->)n^DE0*IHF@DEb~C0FPzz z!A4|qO}jd_deDfCWMXGGL^z(t+^OX~{o-GcvgvwQef)B43DmnkLP7yWhJ#IAB|Fu8 zOo8d9cmMk>lZUYq*jwrUPxjRFKEaBb7-X z=FBxw5USHEcD5^b-+|n}PQV?O%B%&>t(g#MpCd`$=J4(D!Iz_Bpb0~nVA+HM2Uos% z0PkgOMuP*(A_++Csr;}I6nDEBzz)v7brCXUa@=Y}mPSqj7M9R@c^=zK3yzFKFN<1V zeR(+?OZDGh#-0VX$mVMisD4Ao)wdemSd(QigJE`sHcKdk?KiET&}O#Y(? zz5`0wr&NC$D7EVIg~~;i3R*aSR1csJdsRXVHz{*LRn!}o&IMUFtvFC3EhEecnA8DlsAZnbvV>*vv+F3S{H^tTJo4wP>CqWf|GzI^tDz}xa{ zyDbwCB0hP!X?6lE&j-laY7Zy@M}83mvQYy-qC&eYSJ|kF*t;)#WMtR@VDKl5zlBo5 z!{r6&Cu}@!;7NcM9Qo6uI~tStP*war!mwocJzUjvh`gErx`>9IU10W~gV}d9s)5Gg zt1Vwtyg^yASixiZH_?M46co_D(X5=(!#>qbIYLDpkDDl<XQX8m4eCE3yDY=ky%3Cw4R%MPJeoNah_w&M}s<7@$*g_dMeFFHL4aK+j7}xR!YA7iV>=_ zRGoU)u_Vw;;FksB+&>=4lxfKatDkwzR9MXoc%m{#-^3(~f0^j8NY5KJHFX3~7TrB8 zCoygp$Ak93^l}e!QOK_TVoS0ce7T!+nYKOGW~5KlNCsNTuMXDUIhjjo$ZP8JV?sKH zd!VanaHz!JHp}<@_Tfc@cJF-IB`^|=0F6SONV7K}Ze)T+TFz^AhOQbQ1vRz{^+kF` zv~HpkMZApG^Np2zw9$*N{g%>+tZjRiD~+!$R~$>kLeoOGrFa_{WT~D&fQ3h@b7R~z z>p$$LWw%Ko)X2bB|J#G{);%%jAKP|cmyNw#-Ba+y;!Q97+wydYH&pLN3;+9C;5&r& zqg`OR#&x<2b!OxRj_)!wnE9ek0^;-l2)NJe?n7-u$TGF#Bd*Z}c)eso)`k^yOx0^e za6ort)cDv7Vcy{2@$W>ynmq|%dQW>L0N;!$$lncUE-lKW8JpFcbvDDws_Ee0e9C0B zoWVlwP?PS;N0jK6C9v>Ke_QNO_-LyEQN4cwbVQ>QT~FYzhd~ciZSpR|Y>58SI&h-z ze$UCrH^o@o6$WyG+B-gF4goLvt2e50OtziR=6b+O@S{bn3z=oZbz{KPX4b%C2kyY) zFA0~3e2!c2p8SCN+V4$c#_?KepiZHBv@ppkpj%0Swy1fO-w%)*3`Vo*ca)t1yXDXz ztFflbZvOotB{)zJml)DJ|vEjj?_YtY<{0DK~v!1W5Y-FHk>3E>2W0YXqaS#%tf+_-fk?ckFAzzP% zac&M?Z$kLH=-Zb9H8j{Q|GwCpOzMS|Lh!a3or{q;iSBMKcuRDCe9{QNJaxOwZ{8^i zy5JfFQTO#k2i1o21l{{!gl}7G*-x-n(xbFvA>Gm%&QFd37~0Z=hl z0@R5fD&H7VOeV5$WGREGEi-=oRG}pUg}km?ngN}vTDHS?+}^K)DU}DX8@Z|(Pt=ZE z9sv{cgNiURpOw?~aveXalVz4$qXA5w_$d{a`y)Cm%*=5hvc?o&P#2_(reN{E-={|U z#K$ysLH3gbjO6Cm?ewNA5xnn8z++`cC%|k+B!_+9YWb5N9)9KvtS1liEAmsas-6d| zGL*rHctCFVKA>pRV6qvqX!f%VE<&$QR5wnK900E{Uhl+beEH8?**3Wnm9g)K`Nhw7 z=D08yG$5#76Pw(OWJ=^K)z&9rZ&GaHMG&eQoaG^&4u@4QcOL+(LBSb%B-^d&IX*&43WtDe{?g2qcasv<+g;}=XcL3mV|UQH z>s;N@`?lKd4hEja9i0o{(@l>m{H|#REJI!ftYE4okoJ{SNXG)tu0aT%fp?F!5}_jz zLjFlZJ91YT`TUi`>Y~V4_0CZP~1y>U2VcX z+{Bmit-h$QUOq{{cx$F{Y+@pnqDBpkv`y=UKTXk#WxC034f)_PAfO#VMR9kEY+5gfgG2HO%)|e|Ul?3AFPy4v3#l<~@K>BG`jK zdwGWoZo}Jz`C=_~|0PHWv@PtDa<(T(4wWZGTgm{8C-ZcpI=_N0E_g`@WJF5*OH^B* zidr_0o=P(*Kj*KU-X0K><@kV1c}JdJglX3GU1$Il`zty){*u@KYX|yAvFw!-)K?~a z@%KHqK67ChfC)W^;Cg&_VlN?M!e&2AmY^~E%=oZbv+pf))=%7Pl+jic*axYw>R8cRMF zepaLSmT*adQRdNJpXea;cG~=S4}?MR&WgJA4U%4b#-9n{wkqp`~zye+(h zv{H(idgzFPXMes3D38c58#gg*+4m#0Q+wa%T>}i=>!l$el0ckGYg{@I)$oG${Cg*> z`9{H!Z32LIJqQvBtuh@|_WsQT`ziIZG2l(~0e3cvDOc~_d%aY;veA=+^|)E|B|Yrv z7&iS@0}I)F=YUfvSi6F3|D)X(6(Mp4edm-u8y{R132X%{3(9(cmytSMxUCpUJ{M6= z7w-l#hn=yKt_Ph4KC@8XT*kPO-^o(X?_*YYe%$LO2R=I+D}oHRM(bSO?L-Ma%7%U8 zRPc1Hcc6nIKOU-CtnuBxu|E9V;wB~k$#Uu#agTo2PFctO9E0gy*!^Rm=rsU|XV`!h z82Mw)>avxc$^u&BlO{L5fdDIq7mU@2xP9io^bKUlJA>Z@%12*-psOLTrSFaM^;`{& zf8XZ=Hb1pCa@#U!Np!56{+xPE-Zo%kn!cJ}U)OBSFX(EBCBmo! z1!-h*=TI}8CF1KG-I`y|L9UzzLLy5w^6qLZ$l!`MyJJoBViuF!F7`(CLky=kD?Yvm zm<~ERrz`8A@OJ(|WSaY7*7X9AAH!Qi$dhK(vFgQJI6>ZR*xAJJ{(N`oIsfV<5U-Bp zOaR4>qTP1<$3j9#g53M@-p%I47I^F4AE7Wg$>A?qO0NXbfd~>(+VUE2`oKn!OO0$)+gVn%)fE{ zI`%G0zFHmbbcuRqBKa=JT2__tex1gCgG!wv1mM=39#9hqeN_?%Zbr`g0dbx0k{G~; zz@pFu;;ng}IF=!!3gz?f9|wMOy3V1?AEatzKD(>ua+~5PR{m9X)&6D`SRc`WUZm>B}$e zwlLqMee!r8Fi5?j-dIPR0mADPMeRlHa6#-#O`3o-OvryS`oU6zjlLQ^qZ3G-$K4p^ zy0$|DOTG$9%kF0{}A;#KC!-qoBqPCEY%q-DC88|>^yyZo6t9v#u*`NdnYl0MMHmYJYyNs;5+g{j{`Vsze z1covFzL9S&#M!bI4YW@kD_n&Z!!~xRqj_n1IIXPp5DLO4+(>Ki)p@LEb-Ymjfr1Q& zvjppohSimx+O^WjL;xF@riepHFv+xB@{wq+7<2kz-@U=xGw?ON`$@y20Cpz_4qW8! z?Eh8sanm;thw>>i=jh+}hrD#K4&Q4PNGE5tivIPvVkr7RYm-)mJM3H|ycU(*lUhd> z&H(hLZVjA0YpQa&U&_6A4>uPp_aGm=pF}Nbv-sYqBU~R7{55lO=1hvai{ejj5$}y# zMB^XaB18=~WA<8V@Cw16bt#x@7ltJV=-4&#r5m)$7Wwkyur6GB*y9-0t+=%VudHUjJ0-7-VZC4}g1zze} z4Z4NY*XS`>-*VD|{Y?%f9gNT%!Jm`1F|Cmva6@JJb1}sQn|@p*$j7oeE1=`i2|{wy z(v1^_CHO-zniCErrh!G{yt7paqH-c3%KoKH%f7M!1g^^hRUdpOp`J(#v89HV zpSmUz;$IC64;c6G4N7^ol5r2E5ihs6(t3nMQfB69cyVNJsQ6MHS}1_k5EnZheUe-J zWHWC=EbT$;=G6lWMd)U3(n|HVgMz0B~ZbZqMe9b^9obgch6h9)(!FD>vgF^pcVeN3ZT zU)h7cFuO(2H@#DHz$jBEi;WFm=0Fd^vfEyMwU^vQ@xo>wA6!2FG%udVA-||)zbh2Z z$!FFz=~XQE;#dld`NJ`eLLSL64#U+v*EyltwHV7nrkgBR?}kAa<1kFxPc3-?hJ?xa ze;w-xv>Jl1FitvXpcMjm&Vxc|W`pFW9&Ibv(A;#psQYBVR~HMUBP8E14DO8A#-5{k-}{rb$2| z|2bdFodQxjG-VuEF}CW4a~kL2w>`7v?M<5B17LCE^d_N$QWh{CxnrCB$2+ZzuL}8v zjl2Fd^L>GOje+sizW4DIt&t~(eKX^&F?!S=+r#H^GbW7Q@+^MrVCr2X1)=uqi^cCx z>v=C%M^06pXHY{zu1*_0w#}>U4FPEUO7jHLBHkC+*5-320=1|(t>GWudFE!nmV!Rk z-=|AdQjC2qQ(Hk>CA0FpXEfby@?roqM|1#=vn^Ztb>D-xBH>vT8Y)k1;VE@wu<_r1 zd$;=RnzYt4L+0;Z-NZVs!d56P@nDo#miZY%8f?fv!RqoWFVHaJQbN?YsRg5{0n%yu z9MTnb3(2+?hZ1iuPLpeu8;V7OM@db$`~Ah(M8d>qRlR5V6)xG0@8sz-XjQezi@D9c z&sl@Zb6o|7YkTt#&p$AOs-W6gJ_MZ7`@|!=K$7_2 zV{(P#ou@CNl-Zw%T@$vbwpJc6u`w4;%#-|XSWQt0+vtVTOkx>$B@ZL!UF(aorS4Dj%5+gjLb*?YWOdB$pl_X|vptwZy} zeiV;i`kd8{XR`%Gr#b}|B z@1DdvHylVS{-7q2wfmE%UtNgge997fM)@wAxS7X`Z$-lQw0W&dK8VL!;~2B>C%v~% zX7i1>b`8xxstTE(A>7*bRI*~S=(R4jip@$9M99}=M3)A1l@t-WoEsx|#(oBN;MN6p z$bHeR=}%3*xA~O1=hgz$Rc3C~dgnLdQ|gyEesd;!ojlf2$db3wd$UAb@>;|5|N`q1brD!*gAyS(`u_T?EB6cJ*`9m8p>g zTLUQKV{*A-3+M^(wda38fE1@CcZA_<8uWdIy57cgg!bHKt9A>6RJ*-_q4h)7^Y8BO zDN*E7iGhjmGndLj29`Q&3b0%w<5-I6@uR-Re%NeOkN!M-PME4jEZql6Lc6p5uVncP z2`1k?XwX7$h(uKi4W5z$nZI;?0Tf$;b`}6F_b!LJz^d=EM1jmPg@YAQBT;Oc5%Ske zYg(6(w2GU&1foJtMQU{(l-qH5t=nCSY3sAolTp)I+xE#CnQJK}>KC5{;p8eB`}X>1 z@*kqZXi-=J1^jf3N#38En-D)T2V_89b#8TRd}j5pn;9LE!r zMCk+UniaG49GxJQoVhB6+><0LdH{j#%}LqTdq9(Hm2?Q0dbDD~3wDOy>ozsmP;Zfn zOrb$blMGVlvk0n?rjMCeg{ds}lvZ|AVe?<{wY2Z`NZ=}3G80@w5W*i^zWG+Azy&b$ zg1{mo)XB%y+V`*Sp1CwzALeUdIBnA`p9g-$fNA(l19gjN#TZolc3zjd-@`Dv0^)xg zcl`Itm%eSI&SCyRodfextI(lZCh)vv^{ek-M@UZ9H14|K^pH7=g@+sJpVgi&$C<-Dw1mH*NA?sI?&$APmk^q}8`<<-3FI9q;GX zH5#Szq;}ZpMB)Dv{=BxpVgvOUQ0Kki!6oD!#Oa&n$7s&L$vo=4;Jm!J76^F(0~iUX zJ$~QlfuQ}4cm74!YTnnai^JCTJg@athD(p&=3fe`=X6KJvzDNYsU9$kVNq3d<|?{# zi>0A30ji!CsK*UXU00iS`#7=8kmDe~e5Pu~VIBWQ3g_Nbgq)KU(B)(jZ$jV7!Yb0} zj6e1ncZeRN@lzLdVxk?f7VDq3sNhAaMikSRm*`QDtSyiH3e*ys~~&C z==SMz0FGwd2Q5H6pv>@rLZR1`Od+)MIMr$pI9mTk>-vA97y6e_+=eAw$Nh6lxYGes z5A`brStlKfQbo<86ePx+S(L8axNkc29GbU}TRf#=5WY{Wygf8`c; zs$nAhu*lm47Vqs=glq7%qcuCb%wj35;$T^YdikaCrOG0|NYN z4l`{NEfJ}g$}agftk5VcU$3dQwm1YB<477z+00s^H6Udu%GJ~SV-we3@8IaE1dn(< zxYD}{H>9474Ow%x_iAzLQ9Z6*@A`4nyKH-I4}nRRy@DU!o&bg1q|b?%p#8hP%R@Qx z^;Uq;Su65kENXzWXkVUmdU|Nz`OU{N{OQ)+N+oXdeCsU%wEzGaG@%dkWp%9lj{wOD zr%hqPG1@D1$+29r>=m#@vbtp36dZ|%Zqpc5|)e=Co z@$nhO9&%xlEr@Ze6sg*P3BsOh(irXJFAH}e1b4TG0uJIUg5je1x%DtJ5 zZZ)0j?VaXbmNxRA)2l!JmvnQ~oagMc(P#3nKB~|~b@dBBe%ZCZ?)`d_q`_wNiO=Ju zbea0)uqIBraxB9OM*d^v+Xr;eG%n}YP!WUQ+?O%u(;hI#PMC0nK;GwI z2b9>@RA1Wdz|M~64U1og?~_+8&Hoaz-*F+Y)Wn>+^ahmL6f~PY@aT#p6e#sQI`*E0 zC_+OBWnHR7*WNZEH5G_Ez*9rE?*~{x*V29b+{?qSC5_7@)BJ##zGiP71!|pJq0-HO zV@uz^`!m$^$!*`dh~puQDry$8BCj4OttivD&YA@RkS}WuvWACI=$@SdYtsTZG?_A7lhL2~~5H$zt#nraRAT(*f<8+@e#!Chi!#C6u~5N3ch^ zRD;c)Ymn7*`-nSSD3i1N+!LakM9QSfd~LqzU^EM3{0*9@?)i{mz_$0a)$?so#u$Jn z);aB+{;9<^Ke^+t9W!KS(;Pd|IxVD!(PZSgoj@9?6ly=Zv8DabA3IZDGG{{(!SC;f z3fVHiDX9I>=#80qL?F=DZ2XucE?0+Z77gi)GOs?O$b=VX-JuqLRGL-jjNk+?>?sTe)29{c8@?S&ofITL zH+p1AK}KqBy5d2zREQ&WfUA|nV`O?!`S}tb37OSjmKx2pHQcaOqxM@5)+{;@<=>jh zJ_+Oqh#ZCIoSf0C>@mo1&&&1UlpFNGp1(Q;@Ek8S-BVy|a#Fw}E~Yz{ir^5Y8YG$3i0`KgEfqpPpEbw~2msi)Q)J(OQOW5Ta_jzunw=0b=QI14MU+&5CWTMXbbE)UXygVg*;Hxq({&Q5h_=QS zhi7Gx1Yn!zZ6Z4W7EQy zRrH8OjzZi}QYzZTh1paRh)@>4Pu6o?du!(8jQI#vykd{PNyGI4yt%XWRNjOtQGR^rcnf` zb&EBoYE*6$K;kQ^#t=CUheQ5fx&& z`KUW&r}PniH>dkyS)+H#ic|M|o9dId_Ijrc=84IEDU#+ph_H^115bosOlAC~&K_jz{f^YtP1a zM2UW5`#r+p3zQnQ1F2E<{dk4;J^-ExI+1*L+YR200vN+lnO*!IE+=h}gJ$nSSY>nqnh z@EjWpyHJ)n=}xG%@%KY@b% zMSJdw1QhV17SR>6vf)4UoI^P{q)JW^*I9ibBNP{u;E;R{iUjBh6#{T#oFeM!V9N;i z19Ba|$$znVy0drR2gn;Gr(6+??1&xWYl@+*rY z{>?0iiq%*ym`lM%l7=f+0YmChVZ&2Vz!&)1HqCuR<)+0(AGzRIqC33*`j95l^E9#m zY}maJa9y_9X*mgJE|tG+I-4a|y?mLpn+!fHi3D z)xM>SNzj6O-ZbK2#b#~Ql3LXFNNO(IF^Pd&ILN z;_WVhWP+FfAk3QG1=ZZy3Up^>sj?}zOK2Bx2^6rnylBmL_&*8)WBst(bTkOqN5@6H zvFf~i$lK)vm$xHh8h1)3)DP?7)1Bdal*n5ZP_1C_-6sxu`p>935gxjX=%A`*;>NE% z((i7h#m~}i^hvFBDm(e2E>hh;D`z#Cftg{9Wo`!{^Q=!^V1Qp&)PCGeDv(F3vXUH* zv5omSb(_gJ4IaAlB7|27b=v_l9msDRU=<4GCewlElP<-eHNa;%6!FS;3tVVc2g;%1 zRKU6H0Oiy6`Gs3c3MP@Z^cqx$MlG?kFmoq!_ri>u2D2X;C~saERHJVg<0v4{bU;+{ z(cJU94D+cgD73|7Mf)({4JR)2AR2ys>lA4*Ux#ZImT{&cue0CLk4oQ3o~K(!-XW%* z_l#+fmDc1%iFZ!MN#+o(Q~Co)glStv!#d#RwhG?azx)7Y7$JvcoTe7kQdY24^FFw& zRY4xwpXx%l2%253zW@AR%E5bkznV|5BBZ?@Q^_5US^4_;n}It<^Fa?v*NKj$_d=pJ zz68Kc4qJ{d9HCC&gqBv;Nj9ML7751%*4_I){dq-hPPX1qlsT(N+wLUu!|)4&Y{t){ z{C-+Tqc`g4lYdf2w`oSykwQuoKqPsB+ib#lv07&3&TpKr1{!v=WXDMj*a<#l9i*g` z!H4AJAs3S|ff)WAZ0*wJ$~a|yDpknkd>F=oiUt+$CZ;CBb99B3+N6<*Icpu zeV;P@8Wqi5G^tTKZrZ}KnxMk&+Z4I8bLuy=!*LwUH}51EHlf_VZy1z8Dib zF)yb{MtuRw^PQ+spu6!0zkI!dvM#H9b-%>r?aP;mUIIjy4chX!Z0**?%ELgWTF*m#!h7jg}OSN z;}{M;Ax(N)&dqAU@l2KCx>s+z}etI_kW~f2svik9!B`>cZTfUhsG=oSFlEgllYq#v6-N?-`xcu&u!rJje4gVw~bHu%7@etQ>yEh_-Gc)VFG zW^yiSlzx)|Mzm5t#8X|t>N{)b0h&!aackyS(cx3}y6kwdt%HEzPsFIq{eG)F*bv^1 z((;g|O2gSpYBuZ6Jk(g!FPkKe?{~jXIW$`~-2^H%!_@ z{xfiSR))c!&Fc@4IuO2~HaO9`BNH4d0;0@I6O_+g_F zZFD8`n7;9m2wG@V_`D_NLe%^+7*Rd3afYqZ-ok?kjIn#{mB*a&dYlx3ges0qM&l=}fbP#8rOQ}sj8cUyWjjIgl~AzL4Q_hP*^!>O z7!|Q%4{68t)KGd=_79^T{-#4J)D=xAaMZE=`IHE`0O-EBn<=bFRD%f2k{qNua)90( z=1?EYoh>Q8LelJp89g#66EzNO;DnKuBFerD?w~J>rMkgy@$(1Cuy~dTu_PJgnX!U* zQp7*gfJD3z8Q3LMx8*wPHeCSR7Yb4>DvqDir~pMwMm8plicd|01YCCI48&{?bC^e5 zAg+i^M^&Wa(>@}*7cHRKlyP*0qPgcuf9Gr)lrwR5_S9T(t?ZKUBxxjjy8U;l{0 zr2Xug&4wyW+BR_6P8x>)kz3NC+s{7I%qUpcNljF6jwC!V{g@0qAa|*vYdNWdfJmq_ zZyLwJ>Px$Tqb9)*UJQ}?=q}@)Mc~0Xc#D|%CAbAoWA8Mjp@xtnMRrQl-+c2+EJ@TM zw!61C5fR>7nQmaXpxpc1X=M)0W}nE>1{5rp18kqgV`3)K3b+2!lZ!#Y@K#fNlqSW@ z#1~?YMM|s&NnSO1{S6n>8QVFCtrhcZZz`5cou@}Or`fAgOl1Y0TG#5e+D!=jgx97Y z*$`?z{{KP^Bp&{Yfj8-UnX~2C9`2QHIkDp$Qz*>KNcx0LVfs5G=0~w7eSG6vMf|tE z6^u@4IHdRrhb9w+UH^RVXECKsq1oK1Ax4Dj=j!Lb=E;P{qj4cSUJmcEJOxLdgEPta zr`VA>$pF0_H?@BLcKq866$>=$NN;OwteXZrU@3)j28n<3+Wq(#&ndx|M(y13^YjTo z*^Rj&=Y9=MzE~-NG9?nqJyZw>x&lhWTRPv|6e_`O=G}F+)6_QT><3r4s`ZfS;5zV6 z2I?H^0jyJb^h=Z!sM$B4IHDOe$2w6WtWv~N^M}v*EfajHh25P8qCfsDKWNnd;eWk- z3ctrcuDtU)hvwM5Ms{?)p4$gM`;=T#{*50V)0e&QquO*V|2JlsB%R%;WFQ0m@4TCT s11_QeJMZQ{oWcJ~7yqZvyIEJ)qn)(4c1pr)6Z~^R+dwN{(=P1)0Q9m1*8l(j literal 0 HcmV?d00001 diff --git a/plugins/adr/src/api/types.ts b/plugins/adr/src/api/types.ts index e4632e171a..0af35cc6df 100644 --- a/plugins/adr/src/api/types.ts +++ b/plugins/adr/src/api/types.ts @@ -30,6 +30,15 @@ export type AdrFileInfo = { /** The name of the ADR file. */ name: string; + + /** The title of the ADR. */ + title?: string; + + /** The status of the ADR. */ + status?: string; + + /** The date of the ADR. */ + date?: string; }; /** diff --git a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx index d1db286943..eb5b4aed21 100644 --- a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx +++ b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx @@ -35,6 +35,7 @@ import { } from '@backstage/plugin-adr-common'; import { useEntity } from '@backstage/plugin-catalog-react'; import { + Chip, Grid, List, ListItem, @@ -67,7 +68,9 @@ export const EntityAdrContent = (props: { const classes = useStyles(); const { entity } = useEntity(); const rootLink = useRouteRef(rootRouteRef); - const [adrList, setAdrList] = useState([]); + const [adrList, setAdrList] = useState< + { name: string; title?: string; status?: string; date?: string }[] + >([]); const [searchParams, setSearchParams] = useSearchParams(); const scmIntegrations = useApi(scmIntegrationsApiRef); const adrApi = useApi(adrApiRef); @@ -79,10 +82,10 @@ export const EntityAdrContent = (props: { }, [entity, scmIntegrations]); const selectedAdr = - adrList.find(adr => adr === searchParams.get('record')) ?? ''; + adrList.find(adr => adr.name === searchParams.get('record'))?.name ?? ''; useEffect(() => { if (adrList.length && !selectedAdr) { - searchParams.set('record', adrList[0]); + searchParams.set('record', adrList[0].name); setSearchParams(searchParams, { replace: true }); } }); @@ -100,11 +103,22 @@ export const EntityAdrContent = (props: { ? filePathFilterFn(item.name) : madrFilePathFilter(item.name)), ) - .map(({ name }: { name: string }) => name); + .map(({ name, title, status, date }) => ({ name, title, status, date })); setAdrList(adrs); }, [filePathFilterFn, value]); + const getChipColor = (status: string) => { + switch (status) { + case 'accepted': + return 'primary'; + case 'rejected' || 'deprecated': + return 'secondary'; + default: + return 'default'; + } + }; + return ( @@ -133,13 +147,24 @@ export const EntityAdrContent = (props: { key={idx} button component={Link} - to={`${rootLink()}?record=${adr}`} - selected={selectedAdr === adr} + to={`${rootLink()}?record=${adr.name}`} + selected={selectedAdr === adr.name} > + {adr.status && ( + + )} ))} From 7c0b64e8b9c84a51a2b9b3e7c66e64adb8bb8c0d Mon Sep 17 00:00:00 2001 From: bogdannechyporenko Date: Mon, 6 Feb 2023 23:27:00 +0100 Subject: [PATCH 079/417] Updated createValidator.test.ts Signed-off-by: bogdannechyporenko --- .../src/components/TemplatePage/createValidator.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index d9b9d1c0c3..777de0cc36 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -37,9 +37,6 @@ describe('createValidator', () => { _context: { apiHolder: ApiHolder }, ) => { const input = values as string[]; - if (input.length === 0) { - fieldValidation.addError('A tag name can not be empty'); - } for (const item of input) { if (!/^[a-z0-9-]+$/.test(item)) { fieldValidation.addError( From d19c77cc4140f774989a81a4ba78f78323e9db16 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Tue, 7 Feb 2023 08:55:10 +0100 Subject: [PATCH 080/417] fixed API report errors and regenerated the reports Signed-off-by: Katharina Sick --- packages/core-app-api/api-report.md | 20 +++++++++++++++++++ packages/core-plugin-api/api-report.md | 5 +++++ plugins/auth-backend/api-report.md | 9 +-------- .../src/providers/bitbucketServer/provider.ts | 18 +++++++++++------ 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 133ac22e5b..37f7a98de0 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -22,6 +22,7 @@ import { BackstageIdentityApi } from '@backstage/core-plugin-api'; import { BackstageIdentityResponse } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { bitbucketAuthApiRef } from '@backstage/core-plugin-api'; +import { bitbucketServerAuthApiRef } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { Config } from '@backstage/config'; import { ConfigReader } from '@backstage/config'; @@ -280,6 +281,25 @@ export class BitbucketAuth { static create(options: OAuthApiCreateOptions): typeof bitbucketAuthApiRef.T; } +// @public +export class BitbucketServerAuth { + // (undocumented) + static create( + options: OAuthApiCreateOptions, + ): typeof bitbucketServerAuthApiRef.T; +} + +// @public +export type BitbucketServerSession = { + providerInfo: { + accessToken: string; + scopes: Set; + expiresAt?: Date; + }; + profile: ProfileInfo; + backstageIdentity: BackstageIdentityResponse; +}; + // @public export type BitbucketSession = { providerInfo: { diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index dc7aa9eb5f..91f05921bf 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -241,6 +241,11 @@ export const bitbucketAuthApiRef: ApiRef< OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi >; +// @public +export const bitbucketServerAuthApiRef: ApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>; + // @public export type BootErrorPageProps = { step: 'load-config' | 'load-chunk'; diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index e25ed18dfe..8df6079b9f 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -16,7 +16,6 @@ import { GetEntitiesRequest } from '@backstage/catalog-client'; import { IncomingHttpHeaders } from 'http'; import { JsonValue } from '@backstage/types'; import { Logger } from 'winston'; -import passport from 'passport'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; @@ -133,11 +132,9 @@ export type BitbucketPassportProfile = Profile & { }; }; -// Warning: (ae-missing-release-tag) "BitbucketServerOAuthResult" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type BitbucketServerOAuthResult = { - fullProfile: PassportProfile; + fullProfile: Profile; params: { scope: string; access_token?: string; @@ -763,8 +760,4 @@ export type WebMessageResponse = type: 'authorization_response'; error: Error; }; - -// Warnings were encountered during analysis: -// -// src/providers/bitbucketServer/provider.d.ts:6:5 - (ae-forgotten-export) The symbol "PassportProfile" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts index 397f63733f..305f07c9d5 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -40,13 +40,14 @@ import { } from '../types'; import express from 'express'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { PassportProfile } from '../../lib/passport/types'; +import { Profile as PassportProfile } from 'passport'; import { commonByEmailResolver } from '../resolvers'; type PrivateInfo = { refreshToken: string; }; +/** @public */ export type BitbucketServerOAuthResult = { fullProfile: PassportProfile; params: { @@ -216,7 +217,7 @@ export class BitbucketServerAuthProvider implements OAuthHandlers { const user = await userResponse.json(); - return { + const passportProfile = { provider: 'bitbucketServer', id: user.id.toString(), displayName: user.displayName, @@ -226,10 +227,15 @@ export class BitbucketServerAuthProvider implements OAuthHandlers { value: user.emailAddress, }, ], - avatarUrl: user.avatarUrl - ? `https://${this.host}${user.avatarUrl}` - : undefined, - }; + } as PassportProfile; + + if (user.avatarUrl) { + passportProfile.photos = [ + { value: `https://${this.host}${user.avatarUrl}` }, + ]; + } + + return passportProfile; } } From 0a5b73b29265a8dd010348766a15bb002e441b36 Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Thu, 8 Dec 2022 15:37:35 +0100 Subject: [PATCH 081/417] Refactor entity picker, make it re-usable Signed-off-by: Ilya Savich --- .changeset/new-jobs-deny.md | 5 + plugins/catalog-react/api-report.md | 14 +- plugins/catalog-react/package.json | 1 + .../EntityAutocompletePicker.test.tsx | 272 ++++++++++++++++++ .../EntityAutocompletePicker.tsx | 149 ++++++++++ .../EntityAutocompletePickerInput.tsx | 35 +++ .../EntityAutocompletePickerOption.tsx | 45 +++ .../EntityAutocompletePicker/index.ts | 18 ++ .../EntityTagPicker/EntityTagPicker.test.tsx | 10 +- .../EntityTagPicker/EntityTagPicker.tsx | 123 +------- .../catalog-react/src/testUtils/providers.tsx | 24 +- yarn.lock | 1 + 12 files changed, 556 insertions(+), 141 deletions(-) create mode 100644 .changeset/new-jobs-deny.md create mode 100644 plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx create mode 100644 plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx create mode 100644 plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx create mode 100644 plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerOption.tsx create mode 100644 plugins/catalog-react/src/components/EntityAutocompletePicker/index.ts diff --git a/.changeset/new-jobs-deny.md b/.changeset/new-jobs-deny.md new file mode 100644 index 0000000000..656d141330 --- /dev/null +++ b/.changeset/new-jobs-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Add possibility to re-use EntityPicker for filters with multiple select diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 095b6832a4..4756432857 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -393,9 +393,7 @@ export class EntityTagFilter implements EntityFilter { } // @public (undocumented) -export const EntityTagPicker: ( - props: EntityTagPickerProps, -) => JSX.Element | null; +export const EntityTagPicker: (props: EntityTagPickerProps) => JSX.Element; // @public (undocumented) export type EntityTagPickerProps = { @@ -480,12 +478,14 @@ export function InspectEntityDialog(props: { export function isOwnerOf(owner: Entity, entity: Entity): boolean; // @public (undocumented) -export const MockEntityListContextProvider: ({ +export function MockEntityListContextProvider< + T extends DefaultEntityFilters = DefaultEntityFilters, +>({ children, value, -}: React_2.PropsWithChildren<{ - value?: Partial> | undefined; -}>) => JSX.Element; +}: PropsWithChildren<{ + value?: Partial>; +}>): JSX.Element; // @public export class MockStarredEntitiesApi implements StarredEntitiesApi { diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 705c1b544a..2507e9bf8d 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -40,6 +40,7 @@ "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", "@backstage/theme": "workspace:^", diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx new file mode 100644 index 0000000000..3d23a9ec79 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx @@ -0,0 +1,272 @@ +/* + * Copyright 2021 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 { fireEvent, render, waitFor, screen } from '@testing-library/react'; +import React from 'react'; +import { MockEntityListContextProvider } from '../../testUtils/providers'; +import { EntityAutocompletePicker } from './EntityAutocompletePicker'; +import { TestApiProvider } from '@backstage/test-utils'; +import { catalogApiRef } from '../../api'; +import { CatalogApi } from '@backstage/catalog-client'; +import { DefaultEntityFilters } from '../../hooks'; +import { Entity } from '@backstage/catalog-model'; +import { EntityFilter } from '../../types'; + +interface EntityFilters extends DefaultEntityFilters { + options?: EntityOptionFilter; +} + +const options = ['option1', 'option2', 'option3', 'option4']; + +class EntityOptionFilter implements EntityFilter { + constructor(readonly values: string[]) {} + + filterEntity(entity: Entity): boolean { + return this.values.every(v => + ((entity.spec?.options ?? []) as string[]).includes(v), + ); + } + + toQueryValue(): string[] { + return this.values; + } +} + +describe('', () => { + const mockCatalogApiRef = { + getEntityFacets: async () => ({ + facets: { + 'spec.options': options.map((value, idx) => ({ value, count: idx })), + }, + }), + } as unknown as CatalogApi; + + it('renders all options', async () => { + render( + + + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + /> + + , + ); + await waitFor(() => + expect(screen.getByText('Options')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('options-picker-expand')); + options.forEach(option => { + expect(screen.getByText(option)).toBeInTheDocument(); + }); + }); + + it('renders unique options in alphabetical order', async () => { + render( + + + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + /> + + , + ); + await waitFor(() => + expect(screen.getByText('Options')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('options-picker-expand')); + + expect(screen.getAllByRole('option').map(o => o.textContent)).toEqual([ + 'option1', + 'option2', + 'option3', + 'option4', + ]); + }); + + it('renders options with counts', async () => { + render( + + + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + showCounts + /> + + , + ); + await waitFor(() => + expect(screen.getByText('Options')).toBeInTheDocument(), + ); + + fireEvent.click(screen.getByTestId('options-picker-expand')); + + expect(screen.getAllByRole('option').map(o => o.textContent)).toEqual([ + 'option1 (0)', + 'option2 (1)', + 'option3 (2)', + 'option4 (3)', + ]); + }); + + it('respects the query parameter filter value', async () => { + const updateFilters = jest.fn(); + const queryParameters = { options: ['option3'] }; + render( + + + value={{ + updateFilters, + queryParameters, + }} + > + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + /> + + , + ); + + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + options: new EntityOptionFilter(['option3']), + }), + ); + }); + + it('adds options to filters', async () => { + const updateFilters = jest.fn(); + render( + + + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + /> + + , + ); + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + options: undefined, + }), + ); + + fireEvent.click(screen.getByTestId('options-picker-expand')); + fireEvent.click(screen.getByText('option1')); + expect(updateFilters).toHaveBeenLastCalledWith({ + options: new EntityOptionFilter(['option1']), + }); + }); + + it('removes options from filters', async () => { + const updateFilters = jest.fn(); + render( + + + value={{ + updateFilters, + filters: { options: new EntityOptionFilter(['option1']) }, + }} + > + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + /> + + , + ); + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + options: new EntityOptionFilter(['option1']), + }), + ); + fireEvent.click(screen.getByTestId('options-picker-expand')); + expect(screen.getByLabelText('option1')).toBeChecked(); + + fireEvent.click(screen.getByLabelText('option1')); + expect(updateFilters).toHaveBeenLastCalledWith({ + options: undefined, + }); + }); + + it('responds to external queryParameters changes', async () => { + const updateFilters = jest.fn(); + const rendered = render( + + + value={{ + updateFilters, + queryParameters: { options: ['option1'] }, + }} + > + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + /> + + , + ); + await waitFor(() => + expect(updateFilters).toHaveBeenLastCalledWith({ + options: new EntityOptionFilter(['option1']), + }), + ); + rendered.rerender( + + + value={{ + updateFilters, + queryParameters: { options: ['option2'] }, + }} + > + + label="Options" + path="spec.options" + name="options" + Filter={EntityOptionFilter} + /> + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + options: new EntityOptionFilter(['option2']), + }); + }); +}); diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx new file mode 100644 index 0000000000..f3cb589c50 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx @@ -0,0 +1,149 @@ +/* + * Copyright 2021 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 { Box, Typography } from '@material-ui/core'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { Autocomplete } from '@material-ui/lab'; +import React, { useEffect, useMemo, useState } from 'react'; +import { + DefaultEntityFilters, + useEntityList, +} from '../../hooks/useEntityListProvider'; +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; +import { catalogApiRef } from '../../api'; +import { EntityAutocompletePickerOption } from './EntityAutocompletePickerOption'; +import { EntityAutocompletePickerInput } from './EntityAutocompletePickerInput'; +import { EntityFilter } from '@backstage/plugin-catalog-react'; + +type KeysMatchingCondition = T extends V ? K : never; +type KeysMatching = { + [K in keyof T]-?: KeysMatchingCondition; +}[keyof T]; + +type AllowedEntityFilters = KeysMatching< + T, + EntityFilter & { values: string[] } +>; + +interface ConstructableFilter { + new (values: string[]): T; +} + +/** @public */ +export type EntityAutocompletePickerProps< + T extends DefaultEntityFilters = DefaultEntityFilters, + Name extends AllowedEntityFilters = AllowedEntityFilters, +> = { + label: string; + name: Name; + path: string; + showCounts?: boolean; + Filter: ConstructableFilter>; +}; + +/** @public */ +export function EntityAutocompletePicker< + T extends DefaultEntityFilters = DefaultEntityFilters, + Name extends AllowedEntityFilters = AllowedEntityFilters, +>(props: EntityAutocompletePickerProps) { + const { label, name, path, showCounts, Filter } = props; + + const { + updateFilters, + filters, + queryParameters: { [name]: queryParameter }, + } = useEntityList(); + + const catalogApi = useApi(catalogApiRef); + const { value: availableValues } = useAsync(async () => { + const facet = path; + const { facets } = await catalogApi.getEntityFacets({ + facets: [facet], + filter: filters.kind?.getCatalogFilters(), + }); + + return Object.fromEntries( + facets[facet].map(({ value, count }) => [value, count]), + ); + }, [filters.kind]); + + const queryParameters = useMemo( + () => [queryParameter].flat().filter(Boolean) as string[], + [queryParameter], + ); + + const [selectedOptions, setSelectedOptions] = useState( + queryParameters.length + ? queryParameters + : (filters[name] as unknown as { values: string[] })?.values ?? [], + ); + + // Set selected options on query parameter updates; this happens at initial page load and from + // external updates to the page location + useEffect(() => { + if (queryParameters.length) { + setSelectedOptions(queryParameters); + } + }, [queryParameters]); + + const availableOptions = Object.keys(availableValues ?? {}); + + useEffect(() => { + updateFilters({ + [name]: + selectedOptions.length && availableOptions.length + ? new Filter(selectedOptions) + : undefined, + } as Partial); + }, [name, Filter, selectedOptions, availableOptions, updateFilters]); + + if ( + (filters[name] && !('values' in filters[name])) || + !availableOptions.length + ) { + return null; + } + + return ( + + + {label} + + setSelectedOptions(options) + } + renderOption={(option, { selected }) => ( + + )} + size="small" + popupIcon={ + + } + renderInput={EntityAutocompletePickerInput} + /> + + + ); +} diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx new file mode 100644 index 0000000000..586485fab1 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx @@ -0,0 +1,35 @@ +/* + * Copyright 2022 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 { makeStyles, TextField } from '@material-ui/core'; +import { AutocompleteRenderInputParams } from '@material-ui/lab'; +import React from 'react'; + +const useStyles = makeStyles( + { + input: {}, + }, + { + name: 'CatalogReactEntityTagPicker', + }, +); + +export function EntityAutocompletePickerInput( + params: AutocompleteRenderInputParams, +) { + const classes = useStyles(); + + return ; +} diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerOption.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerOption.tsx new file mode 100644 index 0000000000..51b57257a9 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerOption.tsx @@ -0,0 +1,45 @@ +/* + * Copyright 2022 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 { Checkbox, FormControlLabel } from '@material-ui/core'; +import CheckBoxIcon from '@material-ui/icons/CheckBox'; +import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; +import React, { memo } from 'react'; + +interface Props { + selected: boolean; + value: string; + availableOptions?: Record; + showCounts: boolean; +} + +const icon = ; +const checkedIcon = ; + +function OptionCheckbox({ selected }: { selected: boolean }) { + return ; +} + +export const EntityAutocompletePickerOption = memo((props: Props) => { + const { selected, value, availableOptions, showCounts } = props; + const label = showCounts ? `${value} (${availableOptions?.[value]})` : value; + + return ( + } + label={label} + /> + ); +}); diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/index.ts b/plugins/catalog-react/src/components/EntityAutocompletePicker/index.ts new file mode 100644 index 0000000000..10ce0123b7 --- /dev/null +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 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 { EntityAutocompletePicker } from './EntityAutocompletePicker'; +export type { EntityAutocompletePickerProps } from './EntityAutocompletePicker'; diff --git a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx index de7bbb89be..c70217f3a4 100644 --- a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx @@ -44,7 +44,7 @@ describe('', () => { ); await waitFor(() => expect(screen.getByText('Tags')).toBeInTheDocument()); - fireEvent.click(screen.getByTestId('tag-picker-expand')); + fireEvent.click(screen.getByTestId('tags-picker-expand')); tags.forEach(tag => { expect(screen.getByText(tag)).toBeInTheDocument(); }); @@ -60,7 +60,7 @@ describe('', () => { ); await waitFor(() => expect(screen.getByText('Tags')).toBeInTheDocument()); - fireEvent.click(screen.getByTestId('tag-picker-expand')); + fireEvent.click(screen.getByTestId('tags-picker-expand')); expect(screen.getAllByRole('option').map(o => o.textContent)).toEqual([ 'tag1', @@ -80,7 +80,7 @@ describe('', () => { ); await waitFor(() => expect(screen.getByText('Tags')).toBeInTheDocument()); - fireEvent.click(screen.getByTestId('tag-picker-expand')); + fireEvent.click(screen.getByTestId('tags-picker-expand')); expect(screen.getAllByRole('option').map(o => o.textContent)).toEqual([ 'tag1 (0)', @@ -132,7 +132,7 @@ describe('', () => { }), ); - fireEvent.click(screen.getByTestId('tag-picker-expand')); + fireEvent.click(screen.getByTestId('tags-picker-expand')); fireEvent.click(screen.getByText('tag1')); expect(updateFilters).toHaveBeenLastCalledWith({ tags: new EntityTagFilter(['tag1']), @@ -158,7 +158,7 @@ describe('', () => { tags: new EntityTagFilter(['tag1']), }), ); - fireEvent.click(screen.getByTestId('tag-picker-expand')); + fireEvent.click(screen.getByTestId('tags-picker-expand')); expect(screen.getByLabelText('tag1')).toBeChecked(); fireEvent.click(screen.getByLabelText('tag1')); diff --git a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx index 4a1dc03e96..7b08ddf745 100644 --- a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx +++ b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx @@ -14,40 +14,13 @@ * limitations under the License. */ -import { - Box, - Checkbox, - FormControlLabel, - makeStyles, - TextField, - Typography, -} from '@material-ui/core'; -import CheckBoxIcon from '@material-ui/icons/CheckBox'; -import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import { Autocomplete } from '@material-ui/lab'; -import React, { useEffect, useMemo, useState } from 'react'; -import { useEntityList } from '../../hooks/useEntityListProvider'; +import React from 'react'; import { EntityTagFilter } from '../../filters'; -import { useApi } from '@backstage/core-plugin-api'; -import useAsync from 'react-use/lib/useAsync'; -import { catalogApiRef } from '../../api'; +import { EntityAutocompletePicker } from '../EntityAutocompletePicker/EntityAutocompletePicker'; /** @public */ export type CatalogReactEntityTagPickerClassKey = 'input'; -const useStyles = makeStyles( - { - input: {}, - }, - { - name: 'CatalogReactEntityTagPicker', - }, -); - -const icon = ; -const checkedIcon = ; - /** @public */ export type EntityTagPickerProps = { showCounts?: boolean; @@ -55,91 +28,13 @@ export type EntityTagPickerProps = { /** @public */ export const EntityTagPicker = (props: EntityTagPickerProps) => { - const classes = useStyles(); - const { - updateFilters, - filters, - queryParameters: { tags: tagsParameter }, - } = useEntityList(); - - const catalogApi = useApi(catalogApiRef); - const { value: availableTags } = useAsync(async () => { - const facet = 'metadata.tags'; - const { facets } = await catalogApi.getEntityFacets({ - facets: [facet], - filter: filters.kind?.getCatalogFilters(), - }); - - return Object.fromEntries( - facets[facet].map(({ value, count }) => [value, count]), - ); - }, [filters.kind]); - - const queryParamTags = useMemo( - () => [tagsParameter].flat().filter(Boolean) as string[], - [tagsParameter], - ); - - const [selectedTags, setSelectedTags] = useState( - queryParamTags.length ? queryParamTags : filters.tags?.values ?? [], - ); - - // Set selected tags on query parameter updates; this happens at initial page load and from - // external updates to the page location. - useEffect(() => { - if (queryParamTags.length) { - setSelectedTags(queryParamTags); - } - }, [queryParamTags]); - - useEffect(() => { - const tags = Object.keys(availableTags ?? {}); - updateFilters({ - tags: - selectedTags.length && tags.length - ? new EntityTagFilter(selectedTags) - : undefined, - }); - }, [selectedTags, updateFilters, availableTags]); - - if (!Object.keys(availableTags ?? {}).length) return null; - return ( - - - Tags - setSelectedTags(value)} - renderOption={(option, { selected }) => ( - - } - label={ - props.showCounts - ? `${option} (${availableTags?.[option]})` - : option - } - /> - )} - size="small" - popupIcon={} - renderInput={params => ( - - )} - /> - - + ); }; diff --git a/plugins/catalog-react/src/testUtils/providers.tsx b/plugins/catalog-react/src/testUtils/providers.tsx index 5867026a8c..9bf5b21f94 100644 --- a/plugins/catalog-react/src/testUtils/providers.tsx +++ b/plugins/catalog-react/src/testUtils/providers.tsx @@ -27,26 +27,20 @@ import { } from '../hooks/useEntityListProvider'; /** @public */ -export const MockEntityListContextProvider = ({ +export function MockEntityListContextProvider< + T extends DefaultEntityFilters = DefaultEntityFilters, +>({ children, value, }: PropsWithChildren<{ - value?: Partial; -}>) => { + value?: Partial>; +}>) { // Provides a default implementation that stores filter state, for testing components that // reflect filter state. - const [filters, setFilters] = useState( - value?.filters ?? {}, - ); + const [filters, setFilters] = useState(value?.filters ?? ({} as T)); const updateFilters = useCallback( - ( - update: - | Partial - | (( - prevFilters: DefaultEntityFilters, - ) => Partial), - ) => { + (update: Partial | ((prevFilters: T) => Partial)) => { setFilters(prevFilters => { const newFilters = typeof update === 'function' ? update(prevFilters) : update; @@ -67,7 +61,7 @@ export const MockEntityListContextProvider = ({ [], ); - const resolvedValue: EntityListContextProps = useMemo( + const resolvedValue: EntityListContextProps = useMemo( () => ({ entities: value?.entities ?? defaultValues.entities, backendEntities: value?.backendEntities ?? defaultValues.backendEntities, @@ -85,4 +79,4 @@ export const MockEntityListContextProvider = ({ {children} ); -}; +} diff --git a/yarn.lock b/yarn.lock index 6e252cb1c2..1988f9bcf0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5425,6 +5425,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" From 0dd9b5ef072a2d12199ec62d353159e7379a3223 Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Tue, 20 Dec 2022 12:56:22 +0100 Subject: [PATCH 082/417] Rename EntityAutocompletePickerInput styling name Signed-off-by: Ilya Savich --- .changeset/new-jobs-deny.md | 5 +++-- plugins/catalog-react/package.json | 1 - .../EntityAutocompletePicker.test.tsx | 18 +++++++++--------- .../EntityAutocompletePicker.tsx | 2 +- .../EntityAutocompletePickerInput.tsx | 2 +- yarn.lock | 1 - 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.changeset/new-jobs-deny.md b/.changeset/new-jobs-deny.md index 656d141330..ff656adfc3 100644 --- a/.changeset/new-jobs-deny.md +++ b/.changeset/new-jobs-deny.md @@ -1,5 +1,6 @@ --- -'@backstage/plugin-catalog-react': patch +'@backstage/plugin-catalog-react': minor --- -Add possibility to re-use EntityPicker for filters with multiple select +Add possibility to re-use EntityPicker for filters with multiple select. +**BREAKING** Style name `CatalogReactEntityTagPicker` was changed to `EntityAutocompletePickerInput` diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 2507e9bf8d..705c1b544a 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -40,7 +40,6 @@ "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", - "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", "@backstage/theme": "workspace:^", diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx index 3d23a9ec79..38edb9b064 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx @@ -46,7 +46,7 @@ class EntityOptionFilter implements EntityFilter { } describe('', () => { - const mockCatalogApiRef = { + const mockCatalogApi = { getEntityFacets: async () => ({ facets: { 'spec.options': options.map((value, idx) => ({ value, count: idx })), @@ -56,7 +56,7 @@ describe('', () => { it('renders all options', async () => { render( - + label="Options" @@ -79,7 +79,7 @@ describe('', () => { it('renders unique options in alphabetical order', async () => { render( - + label="Options" @@ -106,7 +106,7 @@ describe('', () => { it('renders options with counts', async () => { render( - + label="Options" @@ -136,7 +136,7 @@ describe('', () => { const updateFilters = jest.fn(); const queryParameters = { options: ['option3'] }; render( - + value={{ updateFilters, @@ -163,7 +163,7 @@ describe('', () => { it('adds options to filters', async () => { const updateFilters = jest.fn(); render( - + ', () => { it('removes options from filters', async () => { const updateFilters = jest.fn(); render( - + value={{ updateFilters, @@ -227,7 +227,7 @@ describe('', () => { it('responds to external queryParameters changes', async () => { const updateFilters = jest.fn(); const rendered = render( - + value={{ updateFilters, @@ -249,7 +249,7 @@ describe('', () => { }), ); rendered.rerender( - + value={{ updateFilters, diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx index f3cb589c50..7994571e8f 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx @@ -27,7 +27,7 @@ import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; import { EntityAutocompletePickerOption } from './EntityAutocompletePickerOption'; import { EntityAutocompletePickerInput } from './EntityAutocompletePickerInput'; -import { EntityFilter } from '@backstage/plugin-catalog-react'; +import { EntityFilter } from '../../types'; type KeysMatchingCondition = T extends V ? K : never; type KeysMatching = { diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx index 586485fab1..8069f40871 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx @@ -22,7 +22,7 @@ const useStyles = makeStyles( input: {}, }, { - name: 'CatalogReactEntityTagPicker', + name: 'EntityAutocompletePickerInput', }, ); diff --git a/yarn.lock b/yarn.lock index 1988f9bcf0..6e252cb1c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5425,7 +5425,6 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" - "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" From 7c6a7b799ae6a1e3b7c5976ff7962ec0e1ab3fd8 Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Fri, 13 Jan 2023 18:00:10 +0100 Subject: [PATCH 083/417] add BC Signed-off-by: Ilya Savich --- .changeset/new-jobs-deny.md | 1 - .../EntityAutocompletePicker.tsx | 17 ++++++++++------- .../EntityAutocompletePickerInput.tsx | 18 +++++++++++------- .../EntityTagPicker/EntityTagPicker.tsx | 9 +++++++++ 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/.changeset/new-jobs-deny.md b/.changeset/new-jobs-deny.md index ff656adfc3..e7b5bff71a 100644 --- a/.changeset/new-jobs-deny.md +++ b/.changeset/new-jobs-deny.md @@ -3,4 +3,3 @@ --- Add possibility to re-use EntityPicker for filters with multiple select. -**BREAKING** Style name `CatalogReactEntityTagPicker` was changed to `EntityAutocompletePickerInput` diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx index 7994571e8f..6a1467f87d 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx @@ -14,19 +14,19 @@ * limitations under the License. */ -import { Box, Typography } from '@material-ui/core'; +import { Box, TextFieldProps, Typography } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { Autocomplete } from '@material-ui/lab'; import React, { useEffect, useMemo, useState } from 'react'; -import { - DefaultEntityFilters, - useEntityList, -} from '../../hooks/useEntityListProvider'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; import { EntityAutocompletePickerOption } from './EntityAutocompletePickerOption'; import { EntityAutocompletePickerInput } from './EntityAutocompletePickerInput'; +import { + DefaultEntityFilters, + useEntityList, +} from '../../hooks/useEntityListProvider'; import { EntityFilter } from '../../types'; type KeysMatchingCondition = T extends V ? K : never; @@ -53,6 +53,7 @@ export type EntityAutocompletePickerProps< path: string; showCounts?: boolean; Filter: ConstructableFilter>; + InputProps?: TextFieldProps; }; /** @public */ @@ -60,7 +61,7 @@ export function EntityAutocompletePicker< T extends DefaultEntityFilters = DefaultEntityFilters, Name extends AllowedEntityFilters = AllowedEntityFilters, >(props: EntityAutocompletePickerProps) { - const { label, name, path, showCounts, Filter } = props; + const { label, name, path, showCounts, Filter, InputProps } = props; const { updateFilters, @@ -141,7 +142,9 @@ export function EntityAutocompletePicker< popupIcon={ } - renderInput={EntityAutocompletePickerInput} + renderInput={params => ( + + )} /> diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx index 8069f40871..4140feae01 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerInput.tsx @@ -13,23 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { makeStyles, TextField } from '@material-ui/core'; -import { AutocompleteRenderInputParams } from '@material-ui/lab'; +import { makeStyles, TextField, TextFieldProps } from '@material-ui/core'; import React from 'react'; +import classnames from 'classnames'; const useStyles = makeStyles( { input: {}, }, { - name: 'EntityAutocompletePickerInput', + name: 'CatalogReactEntityAutocompletePickerInput', }, ); -export function EntityAutocompletePickerInput( - params: AutocompleteRenderInputParams, -) { +export function EntityAutocompletePickerInput(params: TextFieldProps) { const classes = useStyles(); - return ; + return ( + + ); } diff --git a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx index 7b08ddf745..0521bb49f8 100644 --- a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx +++ b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ +import { makeStyles } from '@material-ui/core'; import React from 'react'; import { EntityTagFilter } from '../../filters'; import { EntityAutocompletePicker } from '../EntityAutocompletePicker/EntityAutocompletePicker'; @@ -26,8 +27,15 @@ export type EntityTagPickerProps = { showCounts?: boolean; }; +const useStyles = makeStyles( + { input: {} }, + { name: 'CatalogReactEntityTagPicker' }, +); + /** @public */ export const EntityTagPicker = (props: EntityTagPickerProps) => { + const classes = useStyles(); + return ( { path="metadata.tags" Filter={EntityTagFilter} showCounts={props.showCounts} + InputProps={{ className: classes.input }} /> ); }; From f5a9b0ac7fc5db0d358519a55974b3a59fb8d375 Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Tue, 7 Feb 2023 11:26:10 +0100 Subject: [PATCH 084/417] Fix many re-renderings Signed-off-by: Ilya Savich --- .../EntityAutocompletePicker.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx index 6a1467f87d..09d5a45246 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx @@ -28,6 +28,7 @@ import { useEntityList, } from '../../hooks/useEntityListProvider'; import { EntityFilter } from '../../types'; +import _ from 'lodash'; type KeysMatchingCondition = T extends V ? K : never; type KeysMatching = { @@ -96,21 +97,22 @@ export function EntityAutocompletePicker< // Set selected options on query parameter updates; this happens at initial page load and from // external updates to the page location useEffect(() => { - if (queryParameters.length) { + if ( + queryParameters.length && + !_.isEqual(selectedOptions, queryParameters) + ) { setSelectedOptions(queryParameters); } - }, [queryParameters]); + }, [selectedOptions, queryParameters]); const availableOptions = Object.keys(availableValues ?? {}); + const shouldAddFilter = selectedOptions.length && availableOptions.length; useEffect(() => { updateFilters({ - [name]: - selectedOptions.length && availableOptions.length - ? new Filter(selectedOptions) - : undefined, + [name]: shouldAddFilter ? new Filter(selectedOptions) : undefined, } as Partial); - }, [name, Filter, selectedOptions, availableOptions, updateFilters]); + }, [name, shouldAddFilter, selectedOptions, Filter, updateFilters]); if ( (filters[name] && !('values' in filters[name])) || @@ -127,7 +129,7 @@ export function EntityAutocompletePicker< multiple options={availableOptions} value={selectedOptions} - onChange={(_: object, options: string[]) => + onChange={(_event: object, options: string[]) => setSelectedOptions(options) } renderOption={(option, { selected }) => ( From f49c61de9ab1fe5ad64c9dde88c7aa9806ae8805 Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Tue, 7 Feb 2023 15:26:32 +0100 Subject: [PATCH 085/417] Add types to package to fix build Signed-off-by: Ilya Savich --- packages/backend-common/package.json | 1 + yarn.lock | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 9f1069f322..9f77f82a49 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -114,6 +114,7 @@ "@types/stoppable": "^1.1.0", "@types/supertest": "^2.0.8", "@types/tar": "^6.1.1", + "@types/triple-beam": "^1.3.2", "@types/webpack-env": "^1.15.2", "@types/yauzl": "^2.10.0", "aws-sdk-mock": "^5.2.1", diff --git a/yarn.lock b/yarn.lock index 6e252cb1c2..adcc15e13b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3457,6 +3457,7 @@ __metadata: "@types/stoppable": ^1.1.0 "@types/supertest": ^2.0.8 "@types/tar": ^6.1.1 + "@types/triple-beam": ^1.3.2 "@types/webpack-env": ^1.15.2 "@types/yauzl": ^2.10.0 archiver: ^5.0.2 @@ -15443,6 +15444,13 @@ __metadata: languageName: node linkType: hard +"@types/triple-beam@npm:^1.3.2": + version: 1.3.2 + resolution: "@types/triple-beam@npm:1.3.2" + checksum: dd7b4a563fb710abc992e5d59eac481bed9e303fada2e276e37b00be31c392e03300ee468e57761e616512872e77935f92472877d0704a19688d15a726cee17b + languageName: node + linkType: hard + "@types/trusted-types@npm:*": version: 2.0.2 resolution: "@types/trusted-types@npm:2.0.2" From f5ff07e1eab265c8525cfb9f8e6b5555fa4a5de5 Mon Sep 17 00:00:00 2001 From: pamelin Date: Tue, 7 Feb 2023 14:47:46 +0000 Subject: [PATCH 086/417] fix: add ExecutionsTable and ExecutionPanel tests Signed-off-by: pamelin --- .../stackstorm/src/components/ActionsList/ActionsList.test.tsx | 2 -- .../stackstorm/src/components/PacksTable/PacksTable.test.tsx | 3 --- 2 files changed, 5 deletions(-) diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx index 9f57d76ef3..b59d2f4132 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx @@ -54,8 +54,6 @@ const actions: Action[] = [ describe('ActionsList', () => { const mockApi: jest.Mocked = { - getExecutions: jest.fn().mockResolvedValue([]), - getExecution: jest.fn().mockResolvedValue({}), getPacks: jest.fn().mockResolvedValue(packs), getActions: jest.fn().mockResolvedValue(actions), } as any; diff --git a/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx b/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx index e0f922d211..b45d460068 100644 --- a/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx +++ b/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx @@ -33,10 +33,7 @@ const packs: Pack[] = [ describe('PacksTable', () => { const mockApi: jest.Mocked = { - getExecutions: jest.fn().mockResolvedValue([]), - getExecution: jest.fn().mockResolvedValue({}), getPacks: jest.fn().mockResolvedValue(packs), - getActions: jest.fn().mockResolvedValue([]), } as any; it('should render all packs', async () => { From 9f71a2fd20442888ccae9ed5c2da05e7ebfd686d Mon Sep 17 00:00:00 2001 From: Justin De Burgo Date: Tue, 7 Feb 2023 10:22:10 -0600 Subject: [PATCH 087/417] adding changelog Signed-off-by: Justin De Burgo --- .changeset/famous-squids-wonder.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/famous-squids-wonder.md diff --git a/.changeset/famous-squids-wonder.md b/.changeset/famous-squids-wonder.md new file mode 100644 index 0000000000..11ca76ddc1 --- /dev/null +++ b/.changeset/famous-squids-wonder.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Adding dot option to mini match used in catalog rules to allow for catalog imports with hidden folders From bb3e4c3f8d89733097f0d4fbfb44cbbdb165d842 Mon Sep 17 00:00:00 2001 From: Katharina Sick Date: Tue, 7 Feb 2023 17:30:34 +0100 Subject: [PATCH 088/417] use msw for tests & fix resolver type Signed-off-by: Katharina Sick --- plugins/auth-backend/api-report.md | 2 +- plugins/auth-backend/package.json | 2 + .../bitbucketServer/provider.test.ts | 174 ++++++++++-------- .../src/providers/bitbucketServer/provider.ts | 3 +- plugins/auth-backend/src/setupTests.ts | 3 +- yarn.lock | 4 +- 6 files changed, 105 insertions(+), 83 deletions(-) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 8df6079b9f..032344a4f4 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -507,7 +507,7 @@ export const providers: Readonly<{ | undefined, ) => AuthProviderFactory; resolvers: Readonly<{ - emailMatchingUserEntityProfileEmail: () => SignInResolver; + emailMatchingUserEntityProfileEmail: () => SignInResolver; }>; }>; cfAccess: Readonly<{ diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index a95465dbad..91fb5bed5b 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -78,6 +78,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@testing-library/jest-dom": "^5.16.5", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", @@ -89,6 +90,7 @@ "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", + "cross-fetch": "^3.1.5", "msw": "^0.49.0", "supertest": "^6.1.3" }, diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts index 127ca71a17..3934cafd36 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.test.ts @@ -18,10 +18,16 @@ import * as helpers from '../../lib/passport/PassportStrategyHelper'; import { makeProfileInfo } from '../../lib/passport/PassportStrategyHelper'; import { AuthResolverContext } from '../types'; import { + bitbucketServer, BitbucketServerAuthProvider, BitbucketServerOAuthResult, } from './provider'; -import { commonByEmailResolver } from '../resolvers'; +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { fetch } from 'cross-fetch'; +import { rest } from 'msw'; + +global.fetch = fetch; jest.mock('../../lib/passport/PassportStrategyHelper', () => { return { @@ -51,60 +57,60 @@ const passportProfile = { photos: [{ value: 'https://bitbucket.org/user/123/avatar' }], }; -const mockFetchUserRequests = ( - failOnWhoAmI: boolean = false, - whoAmIValue: string = passportProfile.username, - failOnGetUser: boolean = false, - getUserOk: boolean = true, - avatarUrl: string = '/user/123/avatar', - setDisplayName: boolean = true, - setUserName: boolean = true, -) => { - const fetchMock = global.fetch as jest.Mock; - if (failOnWhoAmI) { - fetchMock.mockRejectedValueOnce(() => {}); - } else { - fetchMock.mockResolvedValueOnce({ - headers: { get: jest.fn(() => whoAmIValue) }, - }); - } - if (failOnGetUser) { - fetchMock.mockRejectedValueOnce(() => {}); - } else { - fetchMock.mockResolvedValueOnce({ - ok: getUserOk, - json: () => ({ - name: setUserName ? 'john.doe' : undefined, - emailAddress: 'john@doe.com', - id: 123, - displayName: setDisplayName ? 'John Doe' : undefined, - active: true, - slug: 'john.doe', - type: 'NORMAL', - links: { - self: [ - { - href: 'https://bitbucket.org/users/john.doe', - }, - ], - }, - avatarUrl: avatarUrl, - }), - }); - } -}; +const mockHost = 'bitbucket.org'; +const mockBaseUrl = `https://${mockHost}`; + +const whoAmIHandler = (options?: { fail?: boolean; value?: string }) => + rest.get( + `${mockBaseUrl}/plugins/servlet/applinks/whoami`, + (_req, res, ctx) => { + if (options?.fail) { + res.networkError('error'); + } + return res( + ctx.status(200), + ctx.set('X-Ausername', options?.value ?? passportProfile.username), + ); + }, + ); + +const getUserHandler = (options?: { + fail?: boolean; + status?: number; + avatarUrl?: string; + noDisplayName?: boolean; + noUserName?: boolean; +}) => + rest.get( + `${mockBaseUrl}/rest/api/latest/users/${passportProfile.username}`, + (_req, res, ctx) => { + if (options?.fail) { + res.networkError('error'); + } + return res( + ctx.status(options?.status ?? 200), + ctx.json({ + name: options?.noUserName ? undefined : 'john.doe', + emailAddress: 'john@doe.com', + id: 123, + displayName: options?.noDisplayName ? undefined : 'John Doe', + active: true, + slug: 'john.doe', + type: 'NORMAL', + links: { + self: [ + { + href: 'https://bitbucket.org/users/john.doe', + }, + ], + }, + avatarUrl: options?.avatarUrl ?? '/user/123/avatar', + }), + ); + }, + ); describe('BitbucketServerAuthProvider', () => { - const originalFetch = global.fetch; - - beforeEach(() => { - global.fetch = jest.fn(); - }); - - afterEach(() => { - global.fetch = originalFetch; - }); - const provider = new BitbucketServerAuthProvider({ resolverContext: { signInWithCatalogUser: jest.fn(info => { @@ -113,21 +119,26 @@ describe('BitbucketServerAuthProvider', () => { }; }), } as unknown as AuthResolverContext, - signInResolver: commonByEmailResolver, + signInResolver: + bitbucketServer.resolvers.emailMatchingUserEntityProfileEmail(), authHandler: async ({ fullProfile }) => ({ profile: makeProfileInfo(fullProfile), }), callbackUrl: 'mock', clientId: 'mock', clientSecret: 'mock', - host: 'bitbucket.org', + host: mockHost, authorizationUrl: 'mock', tokenUrl: 'mock', }); describe('when transforming to type OAuthResponse', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + it('should map to a valid response', async () => { - mockFetchUserRequests(); + server.use(whoAmIHandler(), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -153,8 +164,10 @@ describe('BitbucketServerAuthProvider', () => { const { response } = await provider.handler({} as any); expect(response).toEqual(expected); }); + it('should throw if whoami fails', async () => { - mockFetchUserRequests(true); + server.use(whoAmIHandler({ fail: true }), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -166,8 +179,10 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the username of the logged in user`, ); }); + it('should throw if whoami returns an invalid response', async () => { - mockFetchUserRequests(false, ''); + server.use(whoAmIHandler({ value: '' }), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -179,8 +194,9 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the username of the logged in user`, ); }); + it('should throw if get user fails', async () => { - mockFetchUserRequests(false, passportProfile.username, true); + server.use(whoAmIHandler(), getUserHandler({ fail: true })); const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -192,8 +208,9 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the user '${passportProfile.username}'`, ); }); + it('should throw if get user is not ok', async () => { - mockFetchUserRequests(false, passportProfile.username, false, false); + server.use(whoAmIHandler(), getUserHandler({ status: 500 })); const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -205,8 +222,9 @@ describe('BitbucketServerAuthProvider', () => { `Failed to retrieve the user '${passportProfile.username}'`, ); }); + it('should not set an avatar url if not given', async () => { - mockFetchUserRequests(false, passportProfile.username, false, true, ''); + server.use(whoAmIHandler(), getUserHandler({ avatarUrl: '' })); const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -231,15 +249,10 @@ describe('BitbucketServerAuthProvider', () => { const { response } = await provider.handler({} as any); expect(response).toEqual(expected); }); + it('should fallback to the username if no displayName is given', async () => { - mockFetchUserRequests( - false, - passportProfile.username, - false, - true, - '/user/123/avatar', - false, - ); + server.use(whoAmIHandler(), getUserHandler({ noDisplayName: true })); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -265,16 +278,13 @@ describe('BitbucketServerAuthProvider', () => { const { response } = await provider.handler({} as any); expect(response).toEqual(expected); }); + it('should fallback to the user id if no name is given', async () => { - mockFetchUserRequests( - false, - passportProfile.username, - false, - true, - '/user/123/avatar', - false, - false, + server.use( + whoAmIHandler(), + getUserHandler({ noDisplayName: true, noUserName: true }), ); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; @@ -303,8 +313,12 @@ describe('BitbucketServerAuthProvider', () => { }); describe('when authenticating', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + it('should forward the refresh token', async () => { - mockFetchUserRequests(); + server.use(whoAmIHandler(), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; mockFrameHandler.mockResolvedValueOnce({ @@ -334,8 +348,10 @@ describe('BitbucketServerAuthProvider', () => { expect(response).toEqual(expected); }); + it('should forward a new refresh token on refresh', async () => { - mockFetchUserRequests(); + server.use(whoAmIHandler(), getUserHandler()); + const accessToken = '19xasczxcm9n7gacn9jdgm19me'; const params = { scope: 'REPO_READ' }; const mockRefreshToken = jest.spyOn( diff --git a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts index 305f07c9d5..cd082ee953 100644 --- a/plugins/auth-backend/src/providers/bitbucketServer/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucketServer/provider.ts @@ -298,6 +298,7 @@ export const bitbucketServer = createAuthProviderIntegration({ /** * Looks up the user by matching their email to the entity email. */ - emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, + emailMatchingUserEntityProfileEmail: + (): SignInResolver => commonByEmailResolver, }, }); diff --git a/plugins/auth-backend/src/setupTests.ts b/plugins/auth-backend/src/setupTests.ts index d3232290a7..c1d649f2ad 100644 --- a/plugins/auth-backend/src/setupTests.ts +++ b/plugins/auth-backend/src/setupTests.ts @@ -14,4 +14,5 @@ * limitations under the License. */ -export {}; +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/yarn.lock b/yarn.lock index 1621cdc5b1..7bfbb5ea1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4537,6 +4537,7 @@ __metadata: "@backstage/types": "workspace:^" "@davidzemon/passport-okta-oauth": ^0.0.5 "@google-cloud/firestore": ^6.0.0 + "@testing-library/jest-dom": ^5.16.5 "@types/body-parser": ^1.19.0 "@types/cookie-parser": ^1.4.2 "@types/express": ^4.17.6 @@ -4553,6 +4554,7 @@ __metadata: compression: ^1.7.4 cookie-parser: ^1.4.5 cors: ^2.8.5 + cross-fetch: ^3.1.5 express: ^4.17.1 express-promise-router: ^4.1.0 express-session: ^1.17.1 @@ -13578,7 +13580,7 @@ __metadata: languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4": +"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4, @testing-library/jest-dom@npm:^5.16.5": version: 5.16.5 resolution: "@testing-library/jest-dom@npm:5.16.5" dependencies: From d646a84f2f3f232693fb42d6199d46b5c2672bb3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 12:27:48 +0000 Subject: [PATCH 089/417] fix(deps): update dependency js-base64 to v3.7.5 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0e02029c72..f2d4931d11 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26600,9 +26600,9 @@ __metadata: linkType: hard "js-base64@npm:^3.6.0": - version: 3.7.4 - resolution: "js-base64@npm:3.7.4" - checksum: b8f6b10033b57bbb87fa34629f44bc665cb8b7bcba49610a29b296592616e633e9c186afaa02de5a54d60c08aaa36c8c8ad585db095a96fb331fe022f54792a2 + version: 3.7.5 + resolution: "js-base64@npm:3.7.5" + checksum: 67a78c8b1c47b73f1c6fba1957e9fe6fd9dc78ac93ac46cc2e43472dcb9cf150d126fb0e593192e88e0497354fa634d17d255add7cc6ee3c7b4d29870faa8e18 languageName: node linkType: hard From 45e5ea9d931b78a9c1f07511d44940c93c8489e8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 Feb 2023 20:09:58 +0000 Subject: [PATCH 090/417] chore(deps): update backstage/actions action to v0.6.2 Signed-off-by: Renovate Bot --- .github/workflows/automate_changeset_feedback.yml | 2 +- .github/workflows/ci.yml | 6 +++--- .github/workflows/cron.yml | 2 +- .github/workflows/deploy_docker-image.yml | 2 +- .github/workflows/deploy_nightly.yml | 2 +- .github/workflows/deploy_packages.yml | 4 ++-- .github/workflows/issue.yaml | 2 +- .github/workflows/pr-review-comment.yaml | 2 +- .github/workflows/sync_code-formatting.yml | 2 +- .github/workflows/sync_snyk-github-issues.yml | 2 +- .github/workflows/uffizzi-build.yml | 2 +- .github/workflows/verify_e2e-linux.yml | 2 +- .github/workflows/verify_kubernetes.yml | 2 +- .github/workflows/verify_storybook.yml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index aaf0bb1294..d1dcd97644 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -28,7 +28,7 @@ jobs: ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@v0.6.0 + - uses: backstage/actions/changeset-feedback@v0.6.2 name: Generate feedback with: diff-ref: 'origin/master' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16573cf5b8..18af36c8c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -63,7 +63,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -181,7 +181,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 2e6573ede8..be27a732d6 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,7 +8,7 @@ jobs: cron: runs-on: ubuntu-latest steps: - - uses: backstage/actions/cron@v0.6.0 + - uses: backstage/actions/cron@v0.6.2 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 909a36199c..d45cc557d5 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -26,7 +26,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index c9cd22640c..49907042b5 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -26,7 +26,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index fa43271a96..058f4f6089 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -68,7 +68,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -145,7 +145,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 9f2e5827be..e64f919bdb 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -10,4 +10,4 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Issue sync - uses: backstage/actions/issue-sync@v0.6.0 + uses: backstage/actions/issue-sync@v0.6.2 diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 261ce56177..52db29c699 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -35,7 +35,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@v0.6.0 + - uses: backstage/actions/re-review@v0.6.2 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index b84fe5c2e6..7b0cbbbb01 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -20,7 +20,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index dfd114c66a..a89b7c8e65 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -23,7 +23,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 714b108898..30a3489264 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -27,7 +27,7 @@ jobs: registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: linux-v16 diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 16ddb04086..4fda0749c0 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -52,7 +52,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_kubernetes.yml b/.github/workflows/verify_kubernetes.yml index 6d8a7682b5..83280f8e85 100644 --- a/.github/workflows/verify_kubernetes.yml +++ b/.github/workflows/verify_kubernetes.yml @@ -28,7 +28,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 38b685c539..8cde5b6e9b 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -35,7 +35,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.0 + uses: backstage/actions/yarn-install@v0.6.2 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install From a30d2e8df539223cedfbee780120d836b9489cdf Mon Sep 17 00:00:00 2001 From: Dan Hoizner Date: Wed, 8 Feb 2023 15:34:20 -0500 Subject: [PATCH 091/417] feat(plugin-proxy-backend): revive request bodies in order to support proxying requests with bodies that have previously been consumed in a middleware, the proxy config can now specify `reviveRequestBody: true` in order to propagate the previously consumed body to the proxied request. Signed-off-by: Dan Hoizner --- .changeset/shaggy-lies-know.md | 14 +++++++ plugins/proxy-backend/config.d.ts | 5 +++ .../proxy-backend/src/service/router.test.ts | 42 ++++++++++++++++++- plugins/proxy-backend/src/service/router.ts | 6 +++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 .changeset/shaggy-lies-know.md diff --git a/.changeset/shaggy-lies-know.md b/.changeset/shaggy-lies-know.md new file mode 100644 index 0000000000..cc016ed226 --- /dev/null +++ b/.changeset/shaggy-lies-know.md @@ -0,0 +1,14 @@ +--- +'@backstage/plugin-proxy-backend': minor +--- + +The proxy-backend plugin now supports reviving request bodies that have previously been consumed by an express middleware (e.g. `express.json()`). This is done by setting `reviveRequestBody: true` on the proxy configuration. In order to preserve the current behavior, the proxy will **not** revive request bodies by default. + +The following is an example of a proxy configuration that revives request bodies: + +```diff +proxy: + '/target': + target: 'http://proxy-route' ++ reviveRequestBody: true +``` diff --git a/plugins/proxy-backend/config.d.ts b/plugins/proxy-backend/config.d.ts index 59fc0dc5a6..d248845df1 100644 --- a/plugins/proxy-backend/config.d.ts +++ b/plugins/proxy-backend/config.d.ts @@ -50,6 +50,11 @@ export interface Config { * and headers that are set by the proxy will be forwarded. */ allowedHeaders?: string[]; + /** + * Revive request body if it was consumed by a middleware before reaching the proxy. By default, the request + * body is not revived. + */ + reviveRequestBody?: boolean; }; }; } diff --git a/plugins/proxy-backend/src/service/router.test.ts b/plugins/proxy-backend/src/service/router.test.ts index afe78aebeb..aa51fe5a08 100644 --- a/plugins/proxy-backend/src/service/router.test.ts +++ b/plugins/proxy-backend/src/service/router.test.ts @@ -18,11 +18,16 @@ import { getVoidLogger, SingleHostDiscovery } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { Request, Response } from 'express'; import * as http from 'http'; -import { createProxyMiddleware, Options } from 'http-proxy-middleware'; +import { + createProxyMiddleware, + fixRequestBody, + Options, +} from 'http-proxy-middleware'; import { buildMiddleware, createRouter } from './router'; jest.mock('http-proxy-middleware', () => ({ createProxyMiddleware: jest.fn(() => () => undefined), + fixRequestBody: jest.fn(), })); const mockCreateProxyMiddleware = createProxyMiddleware as jest.MockedFunction< @@ -389,6 +394,41 @@ describe('buildMiddleware', () => { expect(Object.keys(testClientResponse.headers!)).toEqual(['set-cookie']); }); + it('revives request body when configured', async () => { + buildMiddleware('/proxy', logger, '/test', { + target: 'http://mocked', + reviveRequestBody: true, + }); + + expect(createProxyMiddleware).toHaveBeenCalledTimes(1); + + const config = mockCreateProxyMiddleware.mock.calls[0][1] as Options; + + expect(config).toBeDefined(); + expect(config.onProxyReq).toBeDefined(); + + config.onProxyReq!( + {} as http.ClientRequest, + {} as Request, + {} as Response, + {}, + ); + expect(fixRequestBody).toHaveBeenCalledTimes(1); + }); + + it('does not revive request body when not configured', async () => { + buildMiddleware('/proxy', logger, '/test', { + target: 'http://mocked', + }); + + expect(createProxyMiddleware).toHaveBeenCalledTimes(1); + + const config = mockCreateProxyMiddleware.mock.calls[0][1] as Options; + + expect(config).toBeDefined(); + expect(config.onProxyReq).not.toBeDefined(); + }); + it('rejects malformed target URLs', async () => { expect(() => buildMiddleware('/proxy', logger, '/test', 'backstage.io'), diff --git a/plugins/proxy-backend/src/service/router.ts b/plugins/proxy-backend/src/service/router.ts index 224c2c6202..1f66bc7f6b 100644 --- a/plugins/proxy-backend/src/service/router.ts +++ b/plugins/proxy-backend/src/service/router.ts @@ -19,6 +19,7 @@ import express from 'express'; import Router from 'express-promise-router'; import { createProxyMiddleware, + fixRequestBody, Options, RequestHandler, } from 'http-proxy-middleware'; @@ -58,6 +59,7 @@ export interface RouterOptions { export interface ProxyConfig extends Options { allowedMethods?: string[]; allowedHeaders?: string[]; + reviveRequestBody?: boolean; } // Creates a proxy middleware, possibly with defaults added on top of the @@ -175,6 +177,10 @@ export function buildMiddleware( }); }; + if (fullConfig.reviveRequestBody) { + fullConfig.onProxyReq = fixRequestBody; + } + return createProxyMiddleware(filter, fullConfig); } From fb19c3fbe83a9a632013460c5b862e318d9d1240 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:32:25 +0000 Subject: [PATCH 092/417] chore(deps): update microsoft/setup-msbuild action to v1.3.1 Signed-off-by: Renovate Bot --- .github/workflows/verify_e2e-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index 8a49b8fe31..145eefbd26 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -49,7 +49,7 @@ jobs: with: node-version: ${{ matrix.node-version }} - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.1.3 + uses: microsoft/setup-msbuild@v1.3.1 - name: setup chrome uses: browser-actions/setup-chrome@latest - name: yarn install From 93f55b5ca08adecf94afbfbaefd6af5d55817491 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 9 Feb 2023 15:24:02 +0000 Subject: [PATCH 093/417] fix: add missing files for ExecutionsTable and ExecutionPanel tests Signed-off-by: pamelin --- .../ExecutionsTable/ExecutionPanel.test.tsx | 79 +++++++++++++ .../ExecutionsTable/ExecutionsTable.test.tsx | 109 ++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx create mode 100644 plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx new file mode 100644 index 0000000000..51adbe0371 --- /dev/null +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { configApiRef } from '@backstage/core-plugin-api'; +import { + MockConfigApi, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; +import React from 'react'; +import { Execution, StackStormApi, stackStormApiRef } from '../../api'; +import { ExecutionPanel } from './ExecutionPanel'; + +const execution: Execution = { + id: '63dcac3e18ba00e09e7bb3b6', + action: { + name: 'post_message', + ref: 'chatops.post_message', + description: 'Post a message to stream for chatops', + pack: 'chatops', + runner_type: 'announcement', + id: '62fe101b11935b6aaff4ff92', + }, + status: 'succeeded', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: { + output: { + result: 'hello world!', + }, + }, + parameters: { + var: 'my funky partameter', + }, + elapsed_seconds: 2.2, + log: [ + { status: 'requested', timestamp: new Date().toISOString() }, + { status: 'succeeded', timestamp: new Date().toISOString() }, + ], +}; + +describe('ExecutionPanel', () => { + const mockApi: jest.Mocked = { + getExecution: jest.fn().mockResolvedValue(execution), + } as any; + + it('should render execution details', async () => { + const { getByText } = await renderInTestApp( + + + , + ); + + expect(getByText(execution.id)).toBeInTheDocument(); + expect(getByText(execution.status)).toBeInTheDocument(); + expect(getByText('"hello world!"')).toBeInTheDocument(); + expect(getByText('"my funky partameter"')).toBeInTheDocument(); + }); +}); diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx new file mode 100644 index 0000000000..dc2bfa4db8 --- /dev/null +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx @@ -0,0 +1,109 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { configApiRef } from '@backstage/core-plugin-api'; +import { + MockConfigApi, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; +import React from 'react'; +import { Execution, StackStormApi, stackStormApiRef } from '../../api'; +import { ExecutionsTable } from './ExecutionsTable'; + +const executions: Execution[] = [ + { + id: '63dcac3e18ba00e09e7bb3b6', + action: { + name: 'post_message', + ref: 'chatops.post_message', + description: 'Post a message to stream for chatops', + pack: 'chatops', + runner_type: 'announcement', + id: '62fe101b11935b6aaff4ff92', + }, + status: 'processing', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: {}, + parameters: {}, + elapsed_seconds: 2.2, + log: [], + }, + { + id: '62fe101b11935b6aaff4ff93', + action: { + name: 'post_result', + ref: 'chatops.post_result', + description: 'Post an execution result to stream for chatops', + pack: 'chatops', + runner_type: 'orquesta', + id: '62fe101b11935b6aaff4ff93', + }, + status: 'succeeded', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: {}, + parameters: {}, + elapsed_seconds: 18.5, + log: [], + }, + { + id: '63dcac3c9e0b4fe98f46becc', + action: { + name: 'run', + ref: 'shell.run', + description: 'Run shell script', + pack: 'shell', + runner_type: 'shell', + id: '63736caac3d8557c4d61883a', + }, + status: 'failed', + start_timestamp: new Date().toISOString(), + end_timestamp: new Date().toISOString(), + result: {}, + parameters: {}, + elapsed_seconds: 5.0, + log: [], + }, +]; + +describe('ExecutionsTable', () => { + const mockApi: jest.Mocked = { + getExecutions: jest.fn().mockResolvedValue(executions), + } as any; + + it('should render all executions', async () => { + const { getByText } = await renderInTestApp( + + + , + ); + + executions.forEach(e => { + expect(getByText(e.id)).toBeInTheDocument(); + expect(getByText(e.action.ref)).toBeInTheDocument(); + expect(getByText(e.status)).toBeInTheDocument(); + }); + }); +}); From 36bccb5252f5671610d2b7a417dcc0802fa2b988 Mon Sep 17 00:00:00 2001 From: Gustaf Lundh Date: Thu, 9 Feb 2023 14:56:51 +0100 Subject: [PATCH 094/417] MemberListCard UI Fix When a description is provided and the user hovers over the email link, the description jumps a bit in the UI. Signed-off-by: Gustaf Lundh --- .changeset/polite-falcons-jump.md | 5 +++++ .../components/Cards/Group/MembersList/MembersListCard.tsx | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/polite-falcons-jump.md diff --git a/.changeset/polite-falcons-jump.md b/.changeset/polite-falcons-jump.md new file mode 100644 index 0000000000..ab9209913d --- /dev/null +++ b/.changeset/polite-falcons-jump.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Fix small UI-glitch in MemberListCard diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index 7e5b683bf1..c41a73ab9c 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -64,6 +64,7 @@ const useStyles = makeStyles((theme: Theme) => whiteSpace: 'nowrap', textOverflow: 'ellipsis', display: 'inline-block', + verticalAlign: 'middle', maxWidth: '100%', '&:hover': { overflow: 'visible', From 5a4fa8859b2e9f1049392f65457f9cac7f1d4ef5 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:29:00 -0600 Subject: [PATCH 095/417] Updated LinksGroup to use Link over ListItem Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/stale-houses-push.md | 5 +++++ .../Cards/Group/GroupProfile/GroupProfileCard.stories.tsx | 2 +- plugins/org/src/components/Cards/Meta/LinksGroup.tsx | 7 +++++-- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 .changeset/stale-houses-push.md diff --git a/.changeset/stale-houses-push.md b/.changeset/stale-houses-push.md new file mode 100644 index 0000000000..53296f3efe --- /dev/null +++ b/.changeset/stale-houses-push.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature whith this off there is no difference between it and the `default` story. diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx index cfb3d847a4..f183ab4d8e 100644 --- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx +++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.stories.tsx @@ -123,7 +123,7 @@ export const ExtraDetails = () => ( - + diff --git a/plugins/org/src/components/Cards/Meta/LinksGroup.tsx b/plugins/org/src/components/Cards/Meta/LinksGroup.tsx index eeade18411..dfc654c14b 100644 --- a/plugins/org/src/components/Cards/Meta/LinksGroup.tsx +++ b/plugins/org/src/components/Cards/Meta/LinksGroup.tsx @@ -23,6 +23,7 @@ import { Divider, } from '@material-ui/core'; import React from 'react'; +import { Link } from '@backstage/core-components'; const WebLink = ({ href, @@ -33,9 +34,11 @@ const WebLink = ({ text?: string; Icon?: IconComponent; }) => ( - + {Icon ? : } - {text} + + {text} + ); From b6f7c46c77d0ecb4863e8813c87eb66708944884 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:32:50 -0600 Subject: [PATCH 096/417] Fixed typo in changeset Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/stale-houses-push.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/stale-houses-push.md b/.changeset/stale-houses-push.md index 53296f3efe..ef2213ed7b 100644 --- a/.changeset/stale-houses-push.md +++ b/.changeset/stale-houses-push.md @@ -2,4 +2,4 @@ '@backstage/plugin-org': patch --- -Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature whith this off there is no difference between it and the `default` story. +Updated `LinksGroup` to use `Link` over `ListItem` as this makes the links more obvious and follows the pattern already used in the `GroupProfileCard`. Also updated the `GroupProfileCard` `ExtraDetails` story in Storybook to enable the `showLinks` feature with this off there is no difference between it and the `default` story. From b1d8ea5e6f324443d3856e0cdf524293311b9821 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Feb 2023 10:26:01 +0000 Subject: [PATCH 097/417] chore(deps): bump @sideway/formula in /microsite-next Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/sideway/formula/releases) - [Commits](https://github.com/sideway/formula/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: "@sideway/formula" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- microsite-next/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index e03c6d93c5..251ae303c0 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -2382,9 +2382,9 @@ __metadata: linkType: hard "@sideway/formula@npm:^3.0.0": - version: 3.0.0 - resolution: "@sideway/formula@npm:3.0.0" - checksum: 8ae26a0ed6bc84f7310be6aae6eb9d81e97f382619fc69025d346871a707eaab0fa38b8c857e3f0c35a19923de129f42d35c50b8010c928d64aab41578580ec4 + version: 3.0.1 + resolution: "@sideway/formula@npm:3.0.1" + checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a languageName: node linkType: hard From e81a6e0ab5964c8b1e58ce152180b73d2b0a9a4f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 10 Feb 2023 11:27:29 +0100 Subject: [PATCH 098/417] core-components: better URL validation in Link component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .changeset/red-pugs-tap.md | 5 +++++ .../core-components/src/components/Link/Link.test.tsx | 9 +++++++++ packages/core-components/src/components/Link/Link.tsx | 11 +++++++++++ 3 files changed, 25 insertions(+) create mode 100644 .changeset/red-pugs-tap.md diff --git a/.changeset/red-pugs-tap.md b/.changeset/red-pugs-tap.md new file mode 100644 index 0000000000..85da2b7990 --- /dev/null +++ b/.changeset/red-pugs-tap.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Updated Link URL validation to be more strict. diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index 3538b79052..09e1293726 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -173,4 +173,13 @@ describe('', () => { }); }); }); + + it('throws an error when attempting to link to script code', () => { + expect(() => + // eslint-disable-next-line no-script-url + render(wrapInTestApp(Script)), + ).toThrowErrorMatchingInlineSnapshot( + `"Link component rejected javascript: URL as a security precaution"`, + ); + }); }); diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index 440fcb811f..bb753e10bd 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -55,6 +55,11 @@ const useStyles = makeStyles( export const isExternalUri = (uri: string) => /^([a-z+.-]+):/.test(uri); +// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js +const scriptProtocolPattern = + // eslint-disable-next-line no-control-regex + /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; + export type LinkProps = Omit & Omit & { to: string; @@ -144,6 +149,12 @@ export const Link = React.forwardRef( const external = isExternalUri(to); const newWindow = external && !!/^https?:/.exec(to); + if (scriptProtocolPattern.test(to)) { + throw new Error( + 'Link component rejected javascript: URL as a security precaution', + ); + } + const handleClick = (event: React.MouseEvent) => { onClick?.(event); if (!noTrack) { From 3ab148535476554ee0e8f03efdb222df7c2dd982 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 12:56:15 +0100 Subject: [PATCH 099/417] chore: added FieldOverrides to the scaffolder form Signed-off-by: blam --- .../FieldOverrides/DescriptionField.tsx | 22 +++++++++++++++++++ .../Stepper/FieldOverrides/index.ts | 16 ++++++++++++++ .../src/next/components/Stepper/Stepper.tsx | 3 ++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx create mode 100644 plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts diff --git a/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx new file mode 100644 index 0000000000..eded38beee --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/DescriptionField.tsx @@ -0,0 +1,22 @@ +/* + * Copyright 2021 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 React from 'react'; +import { MarkdownContent } from '@backstage/core-components'; +import { FieldProps } from '@rjsf/utils'; + +export const DescriptionField = ({ description }: FieldProps) => + description && ; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts new file mode 100644 index 0000000000..d6d0bf3499 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/FieldOverrides/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 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 { DescriptionField } from './DescriptionField'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index f802121597..dc04bb1f47 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -39,6 +39,7 @@ import { FormProps } from '../../types'; import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; import { hasErrors } from './utils'; +import * as FieldOverrides from './FieldOverrides'; const useStyles = makeStyles(theme => ({ backButton: { @@ -175,7 +176,7 @@ export const Stepper = (stepperProps: StepperProps) => { schema={currentStep.schema} uiSchema={currentStep.uiSchema} onSubmit={handleNext} - fields={extensions} + fields={{ ...FieldOverrides, ...extensions }} showErrorList={false} onChange={handleChange} {...(props.FormProps ?? {})} From a07750745b9ab19054577bceff223b5d198558fa Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 12:57:34 +0100 Subject: [PATCH 100/417] chore: added changeset Signed-off-by: blam --- .changeset/heavy-comics-applaud.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/heavy-comics-applaud.md diff --git a/.changeset/heavy-comics-applaud.md b/.changeset/heavy-comics-applaud.md new file mode 100644 index 0000000000..faa0aabb4c --- /dev/null +++ b/.changeset/heavy-comics-applaud.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': minor +--- + +Added `DescriptionField` field override to the `next/scaffolder` From 71f8fc209f1dd1859f4eced426d36f3c47c4c685 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Fri, 10 Feb 2023 12:51:07 +0100 Subject: [PATCH 101/417] fix(techdocs-cli): Fix proxying to mkdocs The domain localhost may point to both 127.0.0.1 and ::1, ipv4 and ipv6 and when node tries to lookup localhost it might prefer ipv6 while mkdocs is only listening on ipv4. This tells node-proxy to target the ipv4 address instead of relying on localhost hostname lookup. Signed-off-by: Nikolai R Kristiansen --- packages/techdocs-cli/src/commands/serve/serve.ts | 2 +- packages/techdocs-cli/src/lib/httpServer.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 48e48d4f66..b779731fae 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -127,7 +127,7 @@ export default async function serve(opts: OptionValues) { const httpServer = new HTTPServer( previewAppPath, port, - opts.mkdocsPort, + mkdocsExpectedDevAddr, opts.verbose, ); diff --git a/packages/techdocs-cli/src/lib/httpServer.ts b/packages/techdocs-cli/src/lib/httpServer.ts index c4bd5b823a..08987f3f1d 100644 --- a/packages/techdocs-cli/src/lib/httpServer.ts +++ b/packages/techdocs-cli/src/lib/httpServer.ts @@ -23,26 +23,26 @@ export default class HTTPServer { private readonly proxyEndpoint: string; private readonly backstageBundleDir: string; private readonly backstagePort: number; - private readonly mkdocsPort: number; + private readonly mkdocsTargetAddress: string; private readonly verbose: boolean; constructor( backstageBundleDir: string, backstagePort: number, - mkdocsPort: number, + mkdocsTargetAddress: string, verbose: boolean, ) { this.proxyEndpoint = '/api/techdocs/'; this.backstageBundleDir = backstageBundleDir; this.backstagePort = backstagePort; - this.mkdocsPort = mkdocsPort; + this.mkdocsTargetAddress = mkdocsTargetAddress; this.verbose = verbose; } // Create a Proxy for mkdocs server private createProxy() { const proxy = httpProxy.createProxyServer({ - target: `http://localhost:${this.mkdocsPort}`, + target: this.mkdocsTargetAddress, }); return (request: http.IncomingMessage): [httpProxy, string] => { From dcacf94912bb733202eb945c66a802c12f800cb5 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Fri, 10 Feb 2023 13:09:50 +0100 Subject: [PATCH 102/417] docs: Add changeset Signed-off-by: Nikolai R Kristiansen --- .changeset/flat-lizards-poke.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/flat-lizards-poke.md diff --git a/.changeset/flat-lizards-poke.md b/.changeset/flat-lizards-poke.md new file mode 100644 index 0000000000..bc180836fa --- /dev/null +++ b/.changeset/flat-lizards-poke.md @@ -0,0 +1,10 @@ +--- +'@techdocs/cli': patch +--- + +Fix proxying to mkdocs + +The domain localhost may point to both 127.0.0.1 and ::1, ipv4 and ipv6 +and when node tries to lookup localhost it might prefer ipv6 while mkdocs +is only listening on ipv4. This tells node-proxy to target the ipv4 address +instead of relying on localhost hostname lookup. From 5637ebed924ef04c23cb7e8cfd67f79724d17053 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 10 Feb 2023 13:28:42 +0100 Subject: [PATCH 103/417] core-components: global override for window.open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .changeset/gorgeous-ligers-burn.md | 5 +++++ .../src/components/Link/Link.test.tsx | 11 ++++++++++ .../src/components/Link/Link.tsx | 21 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 .changeset/gorgeous-ligers-burn.md diff --git a/.changeset/gorgeous-ligers-burn.md b/.changeset/gorgeous-ligers-burn.md new file mode 100644 index 0000000000..f1d8f2cf5f --- /dev/null +++ b/.changeset/gorgeous-ligers-burn.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added a global override for `window.open` that helps prevent security vulnerabilities. diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index 09e1293726..682c4bea8a 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -183,3 +183,14 @@ describe('', () => { ); }); }); + +describe('window.open', () => { + it('throws an error when attempting to open script code', () => { + expect(() => + // eslint-disable-next-line no-script-url + window.open("javascript:alert('hello')"), + ).toThrowErrorMatchingInlineSnapshot( + `"Rejected window.open() with a javascript: URL as a security precaution"`, + ); + }); +}); diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index bb753e10bd..be91753ea3 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -60,6 +60,27 @@ const scriptProtocolPattern = // eslint-disable-next-line no-control-regex /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; +// We install this globally in order to prevent javascript: URL XSS attacks via window.open +const originalWindowOpen = window.open as typeof window.open & { + __backstage?: true; +}; +if (originalWindowOpen && !originalWindowOpen.__backstage) { + const newOpen = function open( + this: Window, + ...args: Parameters + ) { + const url = String(args[0]); + if (scriptProtocolPattern.test(url)) { + throw new Error( + 'Rejected window.open() with a javascript: URL as a security precaution', + ); + } + return originalWindowOpen.apply(this, args); + }; + newOpen.__backstage = true; + window.open = newOpen; +} + export type LinkProps = Omit & Omit & { to: string; From de908df2d054d483681a6ce4d424b5184ee67872 Mon Sep 17 00:00:00 2001 From: Mike Ball Date: Wed, 8 Feb 2023 15:23:07 -0500 Subject: [PATCH 104/417] dev environment now utilizes mock PagerDuty API By making use of a mock PagerDuty API to render the `EntityPagerDuty` component via a `yarn start`-created dev environment, this unblocks development for contributors who don't otherwise have access to the PagerDuty API. Signed-off-by: Mike Ball --- plugins/pagerduty/dev/index.tsx | 152 +++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 3 deletions(-) diff --git a/plugins/pagerduty/dev/index.tsx b/plugins/pagerduty/dev/index.tsx index 676eb687a4..e45e0ffd8f 100644 --- a/plugins/pagerduty/dev/index.tsx +++ b/plugins/pagerduty/dev/index.tsx @@ -13,7 +13,153 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { createDevApp } from '@backstage/dev-utils'; -import { pagerDutyPlugin } from '../src/plugin'; -createDevApp().registerPlugin(pagerDutyPlugin).render(); +import React from 'react'; +import { Entity } from '@backstage/catalog-model'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { createDevApp } from '@backstage/dev-utils'; +import { pagerDutyPlugin, EntityPagerDutyCard } from '../src/plugin'; +import { pagerDutyApiRef } from '../src/api'; +import { PagerDutyApi, PagerDutyTriggerAlarmRequest } from '../src/api/types'; +import { + PagerDutyIncident, + PagerDutyChangeEvent, +} from '../src/components/types'; + +const mockEntity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'backstage', + description: 'backstage.io', + annotations: { + 'github.com/project-slug': 'backstage/backstage', + 'pagerduty.com/service-id': 'foo', + 'pagerduty.com/integration-key': 'foo', + }, + }, + spec: { + lifecycle: 'production', + type: 'website', + owner: 'user:guest', + }, +}; + +const mockPagerDutyApi: PagerDutyApi = { + async getServiceByEntity(entity: Entity) { + return { + service: { + name: entity.metadata.name, + integrationKey: 'key', + id: '123', + html_url: 'http://service', + escalation_policy: { + id: '123', + html_url: 'http://escalationpolicy', + user: { + id: '123', + summary: 'summary', + email: 'email@email.com', + html_url: 'http://user', + name: 'some-user', + }, + }, + }, + }; + }, + + async getIncidentsByServiceId(serviceId: string) { + const incident = (title: string) => { + return { + id: '123', + title: title, + status: 'acknowledged', + html_url: 'http://incident', + assignments: [ + { + assignee: { + id: '123', + summary: 'Jane Doe', + html_url: 'http://assignee', + }, + }, + ], + serviceId: serviceId, + created_at: '2015-10-06T21:30:42Z', + } as PagerDutyIncident; + }; + + return { + incidents: [ + incident('Some Alerting Incident'), + incident('Another Alerting Incident'), + ], + }; + }, + + async getChangeEventsByServiceId(serviceId: string) { + const changeEvent = (description: string) => { + return { + id: serviceId, + source: 'some-source', + html_url: 'http://changeevent', + links: [ + { + href: 'http://link', + text: 'link text', + }, + ], + summary: description, + timestamp: '2018-10-06T21:30:42Z', + } as PagerDutyChangeEvent; + }; + + return { + change_events: [ + changeEvent('us-east-1 deployment'), + changeEvent('us-west-2 deployment'), + ], + }; + }, + + async getOnCallByPolicyId() { + const oncall = (name: string, escalation: number) => { + return { + user: { + id: '123', + name: name, + html_url: 'http://assignee', + summary: 'summary', + email: 'email@email.com', + }, + escalation_level: escalation, + }; + }; + + return { + oncalls: [oncall('Jane Doe', 1), oncall('John Doe', 2)], + }; + }, + + async triggerAlarm(request: PagerDutyTriggerAlarmRequest) { + return new Response(request.description); + }, +}; + +createDevApp() + .registerApi({ + api: pagerDutyApiRef, + deps: {}, + factory: () => mockPagerDutyApi, + }) + .registerPlugin(pagerDutyPlugin) + .addPage({ + path: '/pagerduty', + title: 'PagerDuty', + element: ( + + + + ), + }) + .render(); From 5a2faa801fd5d4ac8b9df68834c4cf8c86f12192 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Fri, 10 Feb 2023 14:29:04 +0100 Subject: [PATCH 105/417] Incorporated feedback Signed-off-by: bnechyporenko --- .../Stepper/createAsyncValidators.test.ts | 55 +++++++++++++++++++ .../Stepper/createAsyncValidators.ts | 38 +++++++++---- .../TemplatePage/createValidator.test.ts | 4 +- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index fe8b41a9f3..3c4442afea 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -272,4 +272,59 @@ describe('createAsyncValidators', () => { }, }); }); + + it('should call a validator for array property from a custom field extension', async () => { + const schema: JsonObject = { + type: 'object', + properties: { + tags: { + title: 'Tags', + type: 'array', + items: { + type: 'string', + 'ui:field': 'TagField', + }, + }, + }, + }; + + const validators = { TagField: jest.fn() }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await validate({ + tags: ['tag-1', 'tag-2'], + }); + + expect(validators.TagField).toHaveBeenCalled(); + }); + + it('should does not call a validator if no ui field specified', async () => { + const schema: JsonObject = { + type: 'object', + properties: { + tags: { + title: 'Tags', + type: 'array', + items: { + type: 'string', + }, + }, + }, + }; + + const validators = { TagField: jest.fn() }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await validate({ + tags: ['asd', 'asd$'], + }); + + expect(validators.TagField).not.toHaveBeenCalled(); + }); }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 86b7619b34..b524944719 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -15,7 +15,7 @@ */ import { FieldValidation } from '@rjsf/utils'; -import type { JsonObject } from '@backstage/types'; +import type { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation } from '../../lib'; @@ -44,20 +44,38 @@ export const createAsyncValidators = ( const parsedSchema = new JSONSchema(rootSchema); const formValidation: FormValidation = {}; + const validateForm = async ( + validatorName: string, + key: string, + value: JsonValue | undefined, + ) => { + const validator = validators[validatorName]; + if (validator) { + const fieldValidation = createFieldValidation(); + try { + await validator(value, fieldValidation, { ...context, formData }); + } catch (ex) { + fieldValidation.addError(ex.message); + } + formValidation[key] = fieldValidation; + } + }; + for (const [key, value] of Object.entries(current)) { const path = `${pathPrefix}/${key}`; const definitionInSchema = parsedSchema.getSchema(path, formData); if (definitionInSchema && 'ui:field' in definitionInSchema) { - const validator = validators[definitionInSchema['ui:field']]; - if (validator) { - const fieldValidation = createFieldValidation(); - try { - await validator(value, fieldValidation, { ...context, formData }); - } catch (ex) { - fieldValidation.addError(ex.message); - } - formValidation[key] = fieldValidation; + if ('ui:field' in definitionInSchema) { + await validateForm(definitionInSchema['ui:field'], key, value); + } + } else if ( + definitionInSchema && + definitionInSchema.items && + 'ui:field' in definitionInSchema.items + ) { + if ('ui:field' in definitionInSchema.items) { + await validateForm(definitionInSchema.items['ui:field'], key, value); } } else if (isObject(value)) { formValidation[key] = await validate(formData, path, value); diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index 777de0cc36..f5be77811a 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -57,7 +57,7 @@ describe('createValidator', () => { apiHolder: apiHolderMock, }; - it('Should call validator for object property from a custom field extension', () => { + it('should call validator for object property from a custom field extension', () => { /* GIVEN */ const rootSchema = { title: 'Title', @@ -89,7 +89,7 @@ describe('createValidator', () => { expect(result.p1.addError).toHaveBeenCalledTimes(1); }); - it('Should call validator for array property from a custom field extension', () => { + it('should call validator for array property from a custom field extension', () => { /* GIVEN */ const rootSchema = { title: 'My form', From 7c145f21ecb62e619823055fb0215c211312d12a Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 10 Feb 2023 14:38:39 +0100 Subject: [PATCH 106/417] chore: make the new TemplateEditor journey work with the new form work Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 7 +- .../src/next/components/Form/Form.tsx | 23 ++ .../src/next/components/Form/index.ts | 17 ++ .../src/next/components/Stepper/Stepper.tsx | 8 +- .../src/next/components/index.ts | 1 + plugins/scaffolder/package.json | 1 + plugins/scaffolder/src/next/Router/Router.tsx | 14 + .../CustomFieldExplorer.tsx | 196 ++++++++++++++ .../DirectoryEditorContext.tsx | 243 ++++++++++++++++++ .../TemplateEditorPage/DryRunContext.test.tsx | 44 ++++ .../next/TemplateEditorPage/DryRunContext.tsx | 179 +++++++++++++ .../DryRunResults/DryRunResults.test.tsx | 118 +++++++++ .../DryRunResults/DryRunResults.tsx | 91 +++++++ .../DryRunResults/DryRunResultsList.test.tsx | 95 +++++++ .../DryRunResults/DryRunResultsList.tsx | 83 ++++++ .../DryRunResults/DryRunResultsSplitView.tsx | 55 ++++ .../DryRunResults/DryRunResultsView.test.tsx | 99 +++++++ .../DryRunResults/DryRunResultsView.tsx | 195 ++++++++++++++ .../TemplateEditorPage/DryRunResults/index.ts | 17 ++ .../TemplateEditorPage/TemplateEditor.tsx | 94 +++++++ .../TemplateEditorBrowser.test.tsx | 55 ++++ .../TemplateEditorBrowser.tsx | 100 +++++++ .../TemplateEditorPage/TemplateEditorForm.tsx | 234 +++++++++++++++++ .../TemplateEditorIntro.tsx | 144 +++++++++++ .../TemplateEditorPage.test.tsx | 58 +++++ .../TemplateEditorPage/TemplateEditorPage.tsx | 107 ++++++++ .../TemplateEditorTextArea.tsx | 153 +++++++++++ .../TemplateFormPreviewer.tsx | 219 ++++++++++++++++ .../src/next/TemplateEditorPage/index.ts | 17 ++ yarn.lock | 1 + 30 files changed, 2661 insertions(+), 7 deletions(-) create mode 100644 plugins/scaffolder-react/src/next/components/Form/Form.tsx create mode 100644 plugins/scaffolder-react/src/next/components/Form/index.ts create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.test.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx create mode 100644 plugins/scaffolder/src/next/TemplateEditorPage/index.ts diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 72a0b92eef..33246d8bea 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -7,13 +7,14 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; import { FieldProps } from '@rjsf/core'; import { FieldProps as FieldProps_2 } from '@rjsf/utils'; import { FieldValidation } from '@rjsf/core'; import { FieldValidation as FieldValidation_2 } from '@rjsf/utils'; -import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { FormProps as FormProps_2 } from '@rjsf/core-v5'; import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; @@ -22,6 +23,7 @@ import { Observable } from '@backstage/types'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; +import { RJSFSchema } from '@rjsf/utils'; import { SetStateAction } from 'react'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; @@ -126,6 +128,9 @@ export type FieldExtensionOptions< schema?: CustomFieldExtensionSchema; }; +// @alpha (undocumented) +export const Form: ComponentType>; + // @public export type FormProps = Pick< FormProps_2, diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx new file mode 100644 index 0000000000..79bcaa8475 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -0,0 +1,23 @@ +/* + * Copyright 2022 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 { withTheme } from '@rjsf/core-v5'; + +// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly +// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because +// of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. +/** @alpha */ +export const Form = withTheme(require('@rjsf/material-ui-v5').Theme); diff --git a/plugins/scaffolder-react/src/next/components/Form/index.ts b/plugins/scaffolder-react/src/next/components/Form/index.ts new file mode 100644 index 0000000000..6f780e92a4 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Form/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 { Form } from './Form'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index dc04bb1f47..bb2844fd52 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -22,7 +22,7 @@ import { Button, makeStyles, } from '@material-ui/core'; -import { type IChangeEvent, withTheme } from '@rjsf/core-v5'; +import { type IChangeEvent } from '@rjsf/core-v5'; import { ErrorSchema } from '@rjsf/utils'; import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; import { NextFieldExtensionOptions } from '../../extensions'; @@ -40,6 +40,7 @@ import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; import { hasErrors } from './utils'; import * as FieldOverrides from './FieldOverrides'; +import { Form } from '../Form'; const useStyles = makeStyles(theme => ({ backButton: { @@ -75,11 +76,6 @@ export type StepperProps = { layouts?: LayoutOptions[]; }; -// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly -// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because -// of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. -const Form = withTheme(require('@rjsf/material-ui-v5').Theme); - /** * The `Stepper` component is the Wizard that is rendered when a user selects a template * @alpha diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index 05e5a1105a..60a8fd9a51 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -19,3 +19,4 @@ export * from './ReviewState'; export * from './TemplateGroup'; export * from './Workflow'; export * from './TemplateOutputs'; +export * from './Form'; diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 86f9100deb..08381732c2 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -58,6 +58,7 @@ "@rjsf/core": "^3.2.1", "@rjsf/material-ui": "^3.2.1", "@rjsf/utils": "5.1.0", + "@rjsf/validator-ajv8": "5.1.0", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", "git-url-parse": "^13.0.0", diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 049579e16c..ded344b048 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -32,6 +32,7 @@ import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; import { nextActionsRouteRef, + nextEditRouteRef, nextScaffolderListTaskRouteRef, nextScaffolderTaskRouteRef, nextSelectedTemplateRouteRef, @@ -40,6 +41,7 @@ import { ErrorPage } from '@backstage/core-components'; import { OngoingTask } from '../OngoingTask'; import { ActionsPage } from '../../components/ActionsPage'; import { ListTasksPage } from '../../components/ListTasksPage'; +import { TemplateEditorPage } from '../TemplateEditorPage'; /** * The Props for the Scaffolder Router @@ -130,6 +132,18 @@ export const Router = (props: PropsWithChildren) => { /> } /> + + + + } + /> + } /> ({ + root: { + gridArea: 'pageContent', + display: 'grid', + gridTemplateAreas: ` + "controls controls" + "fieldForm preview" + `, + gridTemplateRows: 'auto 1fr', + gridTemplateColumns: '1fr 1fr', + }, + controls: { + gridArea: 'controls', + display: 'flex', + flexFlow: 'row nowrap', + alignItems: 'center', + margin: theme.spacing(1), + }, + fieldForm: { + gridArea: 'fieldForm', + }, + preview: { + gridArea: 'preview', + }, +})); + +export const CustomFieldExplorer = ({ + customFieldExtensions = [], + onClose, +}: { + customFieldExtensions?: NextFieldExtensionOptions[]; + onClose?: () => void; +}) => { + const classes = useStyles(); + const fieldOptions = customFieldExtensions.filter(field => !!field.schema); + const [selectedField, setSelectedField] = useState(fieldOptions[0]); + const [fieldFormState, setFieldFormState] = useState({}); + const [refreshKey, setRefreshKey] = useState(Date.now()); + const sampleFieldTemplate = useMemo( + () => + yaml.stringify({ + parameters: [ + { + title: `${selectedField.name} Example`, + properties: { + [selectedField.name]: { + type: selectedField.schema?.returnValue?.type, + 'ui:field': selectedField.name, + 'ui:options': fieldFormState, + }, + }, + }, + ], + }), + [fieldFormState, selectedField], + ); + + const fieldComponents = useMemo(() => { + return Object.fromEntries( + customFieldExtensions.map(({ name, component }) => [name, component]), + ); + }, [customFieldExtensions]); + + const handleSelectionChange = useCallback( + selection => { + setSelectedField(selection); + setFieldFormState({}); + }, + [setFieldFormState, setSelectedField], + ); + + const handleFieldConfigChange = useCallback( + state => { + setFieldFormState(state); + // Force TemplateEditorForm to re-render since some fields + // may not be responsive to ui:option changes + setRefreshKey(Date.now()); + }, + [setFieldFormState, setRefreshKey], + ); + + return ( +

    + Octopus Deploy - Releases ({releases ? releases.length : 0}) + + } + data={releases ?? []} + /> + ) +} \ No newline at end of file diff --git a/plugins/octopus-deploy/src/components/ReleaseTable/index.ts b/plugins/octopus-deploy/src/components/ReleaseTable/index.ts new file mode 100644 index 0000000000..bd0b5bb6b1 --- /dev/null +++ b/plugins/octopus-deploy/src/components/ReleaseTable/index.ts @@ -0,0 +1 @@ +export { ReleaseTable } from './ReleaseTable'; \ No newline at end of file diff --git a/plugins/octopus-deploy/src/constants.ts b/plugins/octopus-deploy/src/constants.ts new file mode 100644 index 0000000000..cec3804d9d --- /dev/null +++ b/plugins/octopus-deploy/src/constants.ts @@ -0,0 +1 @@ +export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id'; \ No newline at end of file diff --git a/plugins/octopus-deploy/src/hooks/useReleases.ts b/plugins/octopus-deploy/src/hooks/useReleases.ts new file mode 100644 index 0000000000..ce38bfb286 --- /dev/null +++ b/plugins/octopus-deploy/src/hooks/useReleases.ts @@ -0,0 +1,26 @@ +import { useApi } from "@backstage/core-plugin-api"; +import useAsync from "react-use/lib/useAsync"; +import { octopusDeployApiRef, OctopusEnvironment, OctopusReleaseProgression } from "../api"; + +export function useReleases( + projectId: string, + releaseHistoryCount: number +): { + environments?: OctopusEnvironment[], + releases?: OctopusReleaseProgression[] + loading: boolean; + error?: Error; +} { + const api = useApi(octopusDeployApiRef); + + const { value, loading, error } = useAsync(() => { + return api.getReleaseProgression(projectId, releaseHistoryCount); + }, [ api, projectId, releaseHistoryCount ]); + + return { + environments: value?.Environments, + releases: value?.Releases, + loading, + error + }; +} \ No newline at end of file diff --git a/plugins/octopus-deploy/src/index.ts b/plugins/octopus-deploy/src/index.ts new file mode 100644 index 0000000000..9573438e87 --- /dev/null +++ b/plugins/octopus-deploy/src/index.ts @@ -0,0 +1,7 @@ +export { + octopusDeployPlugin, + EntityOctopusDeployContent, + isOctopusDeployAvailable + } from './plugin'; + + export * from './api'; diff --git a/plugins/octopus-deploy/src/plugin.test.ts b/plugins/octopus-deploy/src/plugin.test.ts new file mode 100644 index 0000000000..ec8e3f260d --- /dev/null +++ b/plugins/octopus-deploy/src/plugin.test.ts @@ -0,0 +1,7 @@ +import { octopusDeployPlugin } from './plugin'; + +describe('octopus-deploy', () => { + it('should export plugin', () => { + expect(octopusDeployPlugin).toBeDefined(); + }); +}); diff --git a/plugins/octopus-deploy/src/plugin.ts b/plugins/octopus-deploy/src/plugin.ts new file mode 100644 index 0000000000..c73f4b3aed --- /dev/null +++ b/plugins/octopus-deploy/src/plugin.ts @@ -0,0 +1,49 @@ +import { + OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION +} from './constants'; +import { + octopusDeployEntityContentRouteRef +} from './routes'; + +import { OctopusDeployClient, octopusDeployApiRef } from './api'; + +import { createApiFactory, createPlugin, createRoutableExtension, discoveryApiRef, identityApiRef } from '@backstage/core-plugin-api'; + +import { Entity } from '@backstage/catalog-model'; + +/** @public */ +export const isOctopusDeployAvailable = (entity: Entity) => + Boolean(entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION]); + +export const octopusDeployPlugin = createPlugin({ + id: 'octopus-deploy', + apis: [ + createApiFactory({ + api: octopusDeployApiRef, + deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, + factory: ({ discoveryApi, identityApi }) => new OctopusDeployClient({ discoveryApi, identityApi }) + }) + ] +}); + +/* +export const OctopusDeployPage = octopusDeployPlugin.provide( + createRoutableExtension({ + name: 'OctopusDeployPage', + component: () => + import('./components/ExampleComponent').then(m => m.ExampleComponent), + mountPoint: rootRouteRef, + }), +); +*/ + +export const EntityOctopusDeployContent = octopusDeployPlugin.provide( + createRoutableExtension({ + name: 'EntityOctopusDeployContent', + component: () => + import('./components/EntityPageOctopusDeploy').then( + m => m.EntityPageOctopusDeploy + ), + mountPoint: octopusDeployEntityContentRouteRef + }) +) \ No newline at end of file diff --git a/plugins/octopus-deploy/src/routes.ts b/plugins/octopus-deploy/src/routes.ts new file mode 100644 index 0000000000..772db37cb6 --- /dev/null +++ b/plugins/octopus-deploy/src/routes.ts @@ -0,0 +1,5 @@ +import { createRouteRef } from '@backstage/core-plugin-api'; + +export const octopusDeployEntityContentRouteRef = createRouteRef({ + id: 'octopus-deploy-entity-content' +}) diff --git a/plugins/octopus-deploy/src/setupTests.ts b/plugins/octopus-deploy/src/setupTests.ts new file mode 100644 index 0000000000..48c09b5346 --- /dev/null +++ b/plugins/octopus-deploy/src/setupTests.ts @@ -0,0 +1,2 @@ +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts new file mode 100644 index 0000000000..b1a8984163 --- /dev/null +++ b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts @@ -0,0 +1,14 @@ +import { + OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION +} from '../constants'; + +import { Entity } from '@backstage/catalog-model'; + +export function getAnnotationFromEntity(entity: Entity): string { + const annotation = entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION]; + if (!annotation) { + throw new Error('Value for annotation octopus.com/project-id was not found'); + } + + return annotation; +} \ No newline at end of file From 5e5df7135614ccc31ee306fbceb744169489ca6b Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 10:20:10 +0100 Subject: [PATCH 177/417] Some initial docs Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/README.md | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/plugins/octopus-deploy/README.md b/plugins/octopus-deploy/README.md index 26f8021283..a789bfabfb 100644 --- a/plugins/octopus-deploy/README.md +++ b/plugins/octopus-deploy/README.md @@ -8,4 +8,55 @@ Welcome to the octopus-deploy plugin! ## Getting started +This plugin (currently) uses the Backstage proxy to securely communicate with the Octopus Deploy API. + +To use it, you will need to generate an [API Key](https://octopus.com/docs/octopus-rest-api/how-to-create-an-api-key) within Octopus Deploy. + +1. Add the following to your app-config.yaml to enable the proxy: + +``` +// app-config.yaml +proxy: + '/octopus-deploy': + target: '' + headers: + X-Octopus-ApiKey: ${OCTOPUS_API_KEY} +``` + +2. Add the following to `EntityPage.tsx` to display Octopus Releases + +``` +// In packages/app/src/components/catalog/EntityPage.tsx +import { + isOctopusDeployAvailable + EntityOctopusDeployContent +} from '@backstage/plugin-octopus-deploy'; + +const cicdContent = ( + + {/* other components... */} + + + + +) +``` + +3. Add `octopus.com/project-id` annotation in catalog descriptor file + +To obtain a projects ID you will have to query the Octopus API. In the future we'll add support for using a projects slug as well. + +``` +// catalog-info.yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + # ... + annotations: + octopus.com/project-id: Projects-102 +spec: + type: service +``` + +All set , you will be able to see the plugin in action! From c3991a51c8a73b3dbf188698a79187c8cf98f7c6 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 10:40:05 +0100 Subject: [PATCH 178/417] Update yarn lock file Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/package.json | 4 ++-- yarn.lock | 34 +++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 8486ed1a32..0a3c37f0cc 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -43,8 +43,8 @@ "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/node": "*", - "msw": "^0.49.0", - "cross-fetch": "^3.1.5" + "cross-fetch": "^3.1.5", + "msw": "^0.49.0" }, "files": [ "dist" diff --git a/yarn.lock b/yarn.lock index 7e4005f2c1..1a9e8bcfdd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3630,7 +3630,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli@workspace:*, @backstage/cli@workspace:^, @backstage/cli@workspace:packages/cli": +"@backstage/cli@^0.22.1, @backstage/cli@workspace:*, @backstage/cli@workspace:^, @backstage/cli@workspace:packages/cli": version: 0.0.0-use.local resolution: "@backstage/cli@workspace:packages/cli" dependencies: @@ -3830,7 +3830,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-app-api@workspace:^, @backstage/core-app-api@workspace:packages/core-app-api": +"@backstage/core-app-api@^1.4.0, @backstage/core-app-api@workspace:^, @backstage/core-app-api@workspace:packages/core-app-api": version: 0.0.0-use.local resolution: "@backstage/core-app-api@workspace:packages/core-app-api" dependencies: @@ -3990,7 +3990,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/dev-utils@workspace:^, @backstage/dev-utils@workspace:packages/dev-utils": +"@backstage/dev-utils@^1.0.11, @backstage/dev-utils@workspace:^, @backstage/dev-utils@workspace:packages/dev-utils": version: 0.0.0-use.local resolution: "@backstage/dev-utils@workspace:packages/dev-utils" dependencies: @@ -6949,6 +6949,32 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-octopus-deploy@workspace:plugins/octopus-deploy": + version: 0.0.0-use.local + resolution: "@backstage/plugin-octopus-deploy@workspace:plugins/octopus-deploy" + dependencies: + "@backstage/cli": ^0.22.1 + "@backstage/core-app-api": ^1.4.0 + "@backstage/core-components": ^0.12.3 + "@backstage/core-plugin-api": ^1.3.0 + "@backstage/dev-utils": ^1.0.11 + "@backstage/test-utils": ^1.2.4 + "@backstage/theme": ^0.2.16 + "@material-ui/core": ^4.9.13 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + msw: ^0.49.0 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-org-react@workspace:plugins/org-react": version: 0.0.0-use.local resolution: "@backstage/plugin-org-react@workspace:plugins/org-react" @@ -8612,7 +8638,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/test-utils@workspace:^, @backstage/test-utils@workspace:packages/test-utils": +"@backstage/test-utils@^1.2.4, @backstage/test-utils@workspace:^, @backstage/test-utils@workspace:packages/test-utils": version: 0.0.0-use.local resolution: "@backstage/test-utils@workspace:packages/test-utils" dependencies: From b7fff1171f071352a7b2bf986b8143b3647eba65 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 10:41:21 +0100 Subject: [PATCH 179/417] Add changeset Signed-off-by: Jonathan Mezach --- .changeset/honest-nails-bake.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/honest-nails-bake.md diff --git a/.changeset/honest-nails-bake.md b/.changeset/honest-nails-bake.md new file mode 100644 index 0000000000..03d5a080c9 --- /dev/null +++ b/.changeset/honest-nails-bake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-octopus-deploy': minor +--- + +Initial version From e671c20c61515b5268443256cc12fa9c12f23a42 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 10:54:39 +0100 Subject: [PATCH 180/417] Fix errors Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/dev/index.tsx | 22 +- .../components/ReleaseTable/ReleaseTable.tsx | 259 ++++++++++-------- 2 files changed, 164 insertions(+), 117 deletions(-) diff --git a/plugins/octopus-deploy/dev/index.tsx b/plugins/octopus-deploy/dev/index.tsx index 503cbe6d12..d3d6cb3215 100644 --- a/plugins/octopus-deploy/dev/index.tsx +++ b/plugins/octopus-deploy/dev/index.tsx @@ -1,12 +1,28 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; -import { octopusDeployPlugin, OctopusDeployPage } from '../src/plugin'; +import { octopusDeployPlugin } from '../src/plugin'; +import { EntityPageOctopusDeploy } from '../src/components/EntityPageOctopusDeploy'; createDevApp() .registerPlugin(octopusDeployPlugin) .addPage({ - element: , + element: , title: 'Root Page', - path: '/octopus-deploy' + path: '/octopus-deploy', }) .render(); diff --git a/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx b/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx index 21322057d3..be2a68a687 100644 --- a/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx +++ b/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx @@ -1,123 +1,154 @@ -import { Box, Typography } from "@material-ui/core"; -import { - OctopusEnvironment, - OctopusReleaseProgression -} from '../../api'; +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Box, Typography } from '@material-ui/core'; +import { OctopusEnvironment, OctopusReleaseProgression } from '../../api'; import React from 'react'; -import { ResponseErrorPanel, StatusAborted, StatusError, StatusOK, StatusPending, StatusRunning, StatusWarning, Table, TableColumn } from "@backstage/core-components"; +import { + ResponseErrorPanel, + StatusAborted, + StatusError, + StatusOK, + StatusPending, + StatusRunning, + StatusWarning, + Table, + TableColumn, +} from '@backstage/core-components'; type ReleaseTableProps = { - environments?: OctopusEnvironment[]; - releases?: OctopusReleaseProgression[]; - loading: boolean; - error?: Error + environments?: OctopusEnvironment[]; + releases?: OctopusReleaseProgression[]; + loading: boolean; + error?: Error; }; export const getDeploymentStatusComponent = (state: string | undefined) => { - switch (state) { - case "Success": - return ( - - Success - - ); - case "Queued": - return ( - - Queued - - ); - case "Executing": - return ( - - Executing - - ); - case "Failed": - return ( - - Failed - - ); - case "Cancelling": - return ( - - Cancelling - - ); - case "Canceled": - return ( - - Canceled - - ); - case "TimedOut": - return ( - - Timed Out - - ); - default: - return ( - - Unknown - - ); - } -} - -export const ReleaseTable = ({environments, releases, loading, error}: ReleaseTableProps) => { - if (error) { - return ( -
    - -
    - ); - } - - const columns: TableColumn[] = [ - { - title: 'Version', - field: 'Release.Version', - highlight: false, - width: 'auto' - }, - ...environments?.map(env => ({ - title: env.Name, - width: 'auto', - render: (row: Partial) => { - const deploymentsForEnvironment = row.Deployments[env.Id]; - if (deploymentsForEnvironment) { - return ( - - - {getDeploymentStatusComponent(deploymentsForEnvironment[0].State)} - - - ) - } - } - //field: `Deployments.${env.Id}[0].State` // TODO: We'll probably need to deal with multi-tenant deployments here - })) ?? [] - ] + switch (state) { + case 'Success': + return ( + + Success + + ); + case 'Queued': + return ( + + Queued + + ); + case 'Executing': + return ( + + Executing + + ); + case 'Failed': + return ( + + Failed + + ); + case 'Cancelling': + return ( + + Cancelling + + ); + case 'Canceled': + return ( + + Canceled + + ); + case 'TimedOut': + return ( + + Timed Out + + ); + default: + return ( + + Unknown + + ); + } +}; +export const ReleaseTable = ({ + environments, + releases, + loading, + error, +}: ReleaseTableProps) => { + if (error) { return ( -
    - Octopus Deploy - Releases ({releases ? releases.length : 0}) - - } - data={releases ?? []} - /> - ) -} \ No newline at end of file +
    + +
    + ); + } + + const columns: TableColumn[] = [ + { + title: 'Version', + field: 'Release.Version', + highlight: false, + width: 'auto', + }, + ...(environments?.map(env => ({ + title: env.Name, + width: 'auto', + render: (row: Partial) => { + const deploymentsForEnvironment = row.Deployments + ? row.Deployments[env.Id] + : null; + if (deploymentsForEnvironment) { + return ( + + + {getDeploymentStatusComponent( + deploymentsForEnvironment[0].State, + )} + + + ); + } + return ; + }, + })) ?? []), + ]; + + return ( +
    + Octopus Deploy - Releases ({releases ? releases.length : 0}) + + } + data={releases ?? []} + /> + ); +}; From 09237c3f1441783df68b1c590ad9f5918a025352 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 10:58:19 +0100 Subject: [PATCH 181/417] Use workspace range Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 0a3c37f0cc..059235caf3 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -23,9 +23,9 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.12.3", - "@backstage/core-plugin-api": "^1.3.0", - "@backstage/theme": "^0.2.16", + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/theme": "workspace:^", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -35,10 +35,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.22.1", - "@backstage/core-app-api": "^1.4.0", - "@backstage/dev-utils": "^1.0.11", - "@backstage/test-utils": "^1.2.4", + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", From 318e1fa26bcf7fcb30ea41b3b8fab26b150fae5e Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 11:59:38 +0100 Subject: [PATCH 182/417] Update yarn lock file Signed-off-by: Jonathan Mezach --- yarn.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1a9e8bcfdd..c732c8c21d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3630,7 +3630,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli@^0.22.1, @backstage/cli@workspace:*, @backstage/cli@workspace:^, @backstage/cli@workspace:packages/cli": +"@backstage/cli@workspace:*, @backstage/cli@workspace:^, @backstage/cli@workspace:packages/cli": version: 0.0.0-use.local resolution: "@backstage/cli@workspace:packages/cli" dependencies: @@ -3830,7 +3830,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-app-api@^1.4.0, @backstage/core-app-api@workspace:^, @backstage/core-app-api@workspace:packages/core-app-api": +"@backstage/core-app-api@workspace:^, @backstage/core-app-api@workspace:packages/core-app-api": version: 0.0.0-use.local resolution: "@backstage/core-app-api@workspace:packages/core-app-api" dependencies: @@ -3990,7 +3990,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/dev-utils@^1.0.11, @backstage/dev-utils@workspace:^, @backstage/dev-utils@workspace:packages/dev-utils": +"@backstage/dev-utils@workspace:^, @backstage/dev-utils@workspace:packages/dev-utils": version: 0.0.0-use.local resolution: "@backstage/dev-utils@workspace:packages/dev-utils" dependencies: @@ -6953,13 +6953,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-octopus-deploy@workspace:plugins/octopus-deploy" dependencies: - "@backstage/cli": ^0.22.1 - "@backstage/core-app-api": ^1.4.0 - "@backstage/core-components": ^0.12.3 - "@backstage/core-plugin-api": ^1.3.0 - "@backstage/dev-utils": ^1.0.11 - "@backstage/test-utils": ^1.2.4 - "@backstage/theme": ^0.2.16 + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 @@ -8638,7 +8638,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/test-utils@^1.2.4, @backstage/test-utils@workspace:^, @backstage/test-utils@workspace:packages/test-utils": +"@backstage/test-utils@workspace:^, @backstage/test-utils@workspace:packages/test-utils": version: 0.0.0-use.local resolution: "@backstage/test-utils@workspace:packages/test-utils" dependencies: From 2ac6ab520a71c6208a5632909ebec57caaacbec5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 13:01:42 +0000 Subject: [PATCH 183/417] chore(deps): update dependency @types/express-session to v1.17.6 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7e4005f2c1..7be6e97178 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14394,11 +14394,11 @@ __metadata: linkType: hard "@types/express-session@npm:^1.17.2": - version: 1.17.5 - resolution: "@types/express-session@npm:1.17.5" + version: 1.17.6 + resolution: "@types/express-session@npm:1.17.6" dependencies: "@types/express": "*" - checksum: f6995f7720a18546bcb10cc707cf8c9c92455eb4319c0c50c57e9b9b10ed20dc379d74d5e4c3323fe4e924238b75e13c97822c9d81a80fa064ddc71654c1059d + checksum: f5f2201d6b9568d8b9319735a4f6806b5ca144cee450274965aec54bc0a0331ba8bfffc1ad5addadf2e625769e13813a48cb5aea5b166fa05f474a12302dbb38 languageName: node linkType: hard From b1acb866e721296dbaf376bbfa16f457a29a96fc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 13:02:51 +0000 Subject: [PATCH 184/417] chore(deps): update dependency start-server-and-test to v1.15.4 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7e4005f2c1..21a960cc94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35714,8 +35714,8 @@ __metadata: linkType: hard "start-server-and-test@npm:^1.10.11": - version: 1.15.3 - resolution: "start-server-and-test@npm:1.15.3" + version: 1.15.4 + resolution: "start-server-and-test@npm:1.15.4" dependencies: arg: ^5.0.2 bluebird: 3.7.2 @@ -35729,7 +35729,7 @@ __metadata: server-test: src/bin/start.js start-server-and-test: src/bin/start.js start-test: src/bin/start.js - checksum: 3489c5146e26bc3bfa34d12f546f78fa6d883fdd49d0c60cbf4fb76ef627df6cde0a878253f5ca8e2177b938c00f47c613a811f6e7aa519af3be58576fbc2ab0 + checksum: 0df9a4710ea45ddb1a9f719e0865faa8e26a973beff693dfe244ae2d914bfc6eed4d2db8529cdcad3d53658c4655356e5aca3520485a3ef4d9d9f320956b0e7d languageName: node linkType: hard From c8c46030902e4b7d554ba65ccbe70548c8374718 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 13:04:01 +0000 Subject: [PATCH 185/417] fix(deps): update dependency @uiw/react-codemirror to v4.19.9 Signed-off-by: Renovate Bot --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7e4005f2c1..e495e7cd25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15976,9 +15976,9 @@ __metadata: languageName: node linkType: hard -"@uiw/codemirror-extensions-basic-setup@npm:4.19.7": - version: 4.19.7 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.19.7" +"@uiw/codemirror-extensions-basic-setup@npm:4.19.9": + version: 4.19.9 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.19.9" dependencies: "@codemirror/autocomplete": ^6.0.0 "@codemirror/commands": ^6.0.0 @@ -15995,19 +15995,19 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 4c32d3b41b78776fd41b229edc8777dff4137ff6125836df5a6573e01a0a74f2ae66293a09a3b095a1fbe660b2fc8b2bde93ba4aa92636702a74baea261fcf94 + checksum: f248d1623f33b88b61dd75955441d1b5925b2b2c78d595eac1d4603dc31f107d5973d9cff42c3ade4a2493828d679a8908e5dad03a570511e6095d0028089f85 languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.9.3": - version: 4.19.7 - resolution: "@uiw/react-codemirror@npm:4.19.7" + version: 4.19.9 + resolution: "@uiw/react-codemirror@npm:4.19.9" dependencies: "@babel/runtime": ^7.18.6 "@codemirror/commands": ^6.1.0 "@codemirror/state": ^6.1.1 "@codemirror/theme-one-dark": ^6.0.0 - "@uiw/codemirror-extensions-basic-setup": 4.19.7 + "@uiw/codemirror-extensions-basic-setup": 4.19.9 codemirror: ^6.0.0 peerDependencies: "@babel/runtime": ">=7.11.0" @@ -16017,7 +16017,7 @@ __metadata: codemirror: ">=6.0.0" react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 333c7b0c7181219bb0506cd956eb10fa07aad5f26d3c5a9e7b9875e6c60f1e9bf1c8f74bf160735c75b7dbe9e9b05879c17f5ea641e212ba8f454887f04b0e7e + checksum: ed0d9a7b927df718535bccf553fa7cdabd2cb776f74e6ae75eab0ba321bc60468b5f1b8576a12543729770a11e5438fd4fc925f3f74643985c34a2184c5ae7f6 languageName: node linkType: hard From 3a4e7fbb1646178d3ff4097639395ec318c461aa Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 14:05:13 +0100 Subject: [PATCH 186/417] Pretty most files Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/src/api/index.ts | 147 ++++++++++-------- .../EntityPageOctopusDeploy.tsx | 35 ++++- .../EntityPageOctopusDeploy/index.ts | 17 +- .../src/components/ReleaseTable/index.ts | 17 +- plugins/octopus-deploy/src/constants.ts | 17 +- .../octopus-deploy/src/hooks/useReleases.ts | 61 +++++--- plugins/octopus-deploy/src/plugin.ts | 46 ++++-- plugins/octopus-deploy/src/routes.ts | 19 ++- .../src/utils/getAnnotationFromEntity.ts | 36 +++-- 9 files changed, 279 insertions(+), 116 deletions(-) diff --git a/plugins/octopus-deploy/src/api/index.ts b/plugins/octopus-deploy/src/api/index.ts index b066f700db..f89e429f64 100644 --- a/plugins/octopus-deploy/src/api/index.ts +++ b/plugins/octopus-deploy/src/api/index.ts @@ -1,88 +1,113 @@ -import { createApiRef, DiscoveryApi, IdentityApi } from "@backstage/core-plugin-api"; +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + createApiRef, + DiscoveryApi, + IdentityApi, +} from '@backstage/core-plugin-api'; export type OctopusProgression = { - Environments: OctopusEnvironment[]; - Releases: OctopusReleaseProgression[]; -} + Environments: OctopusEnvironment[]; + Releases: OctopusReleaseProgression[]; +}; export type OctopusEnvironment = { - Id: string, - Name: string -} + Id: string; + Name: string; +}; export type OctopusReleaseProgression = { - Release: OctopusRelease - Deployments: { [key: string]: OctopusDeployment[] } -} + Release: OctopusRelease; + Deployments: { [key: string]: OctopusDeployment[] }; +}; export type OctopusRelease = { - Id: string - Version: string -} + Id: string; + Version: string; +}; export type OctopusDeployment = { - State: string -} + State: string; +}; export const octopusDeployApiRef = createApiRef({ - id: 'plugin.octopusdeploy.service' + id: 'plugin.octopusdeploy.service', }); const DEFAULT_PROXY_PATH_BASE = '/octopus-deploy'; type Options = { - discoveryApi: DiscoveryApi; - identityApi: IdentityApi - /** - * Path to use for requests via the proxy, defaults to /octopus-deploy - */ - proxyPathBase?: string -} + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + /** + * Path to use for requests via the proxy, defaults to /octopus-deploy + */ + proxyPathBase?: string; +}; export interface OctopusDeployApi { - getReleaseProgression(projectId: string, releaseHistoryCount: number): Promise; + getReleaseProgression( + projectId: string, + releaseHistoryCount: number, + ): Promise; } export class OctopusDeployClient implements OctopusDeployApi { - private readonly discoveryApi: DiscoveryApi; - private readonly identityApi: IdentityApi; - private readonly proxyPathBase: string; + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + private readonly proxyPathBase: string; - constructor(options: Options) { - this.discoveryApi = options.discoveryApi; - this.identityApi = options.identityApi; - this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE; + constructor(options: Options) { + this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; + this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE; + } + + async getReleaseProgression( + projectId: string, + releaseHistoryCount: number, + ): Promise { + const url = await this.getApiUrl(projectId, releaseHistoryCount); + + const { token: idToken } = await this.identityApi.getCredentials(); + const response = await fetch(url, { + headers: idToken ? { Authorization: `Bearer ${idToken}` } : {}, + }); + + let responseJson; + + try { + responseJson = await response.json(); + } catch (e) { + responseJson = { releases: [] }; } - async getReleaseProgression(projectId: string, releaseHistoryCount: number): Promise { - const url = await this.getApiUrl(projectId, releaseHistoryCount); - - const { token: idToken } = await this.identityApi.getCredentials(); - const response = await fetch(url, { - headers: idToken ? { Authorization: `Bearer ${idToken}` } : {}, - }); - - let responseJson; - - try { - responseJson = await response.json(); - } catch (e) { - responseJson = { releases: [] }; - } - - if (response.status !== 200) { - throw new Error( - `Error communicating with Octopus Deploy: ${ - responseJson?.error?.title || response.statusText - }`, - ); - } - - return responseJson; + if (response.status !== 200) { + throw new Error( + `Error communicating with Octopus Deploy: ${ + responseJson?.error?.title || response.statusText + }`, + ); } - private async getApiUrl(projectId: string, releaseHistoryCount: number) { - const proxyUrl = await this.discoveryApi.getBaseUrl('proxy'); - return `${proxyUrl}${this.proxyPathBase}/projects/${projectId}/progression?releaseHistoryCount=${releaseHistoryCount}`; - } -} \ No newline at end of file + return responseJson; + } + + private async getApiUrl(projectId: string, releaseHistoryCount: number) { + const proxyUrl = await this.discoveryApi.getBaseUrl('proxy'); + return `${proxyUrl}${this.proxyPathBase}/projects/${projectId}/progression?releaseHistoryCount=${releaseHistoryCount}`; + } +} diff --git a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx index d9b6a001c2..de28edb9e0 100644 --- a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx +++ b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/EntityPageOctopusDeploy.tsx @@ -1,3 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import { useEntity } from '@backstage/plugin-catalog-react'; import { useReleases } from '../../hooks/useReleases'; import { getAnnotationFromEntity } from '../../utils/getAnnotationFromEntity'; @@ -5,11 +20,21 @@ import React from 'react'; import { ReleaseTable } from '../ReleaseTable'; export const EntityPageOctopusDeploy = (props: { defaultLimit?: number }) => { - const { entity } = useEntity(); + const { entity } = useEntity(); - const projectId = getAnnotationFromEntity(entity); + const projectId = getAnnotationFromEntity(entity); - const { environments, releases, loading, error } = useReleases(projectId, props.defaultLimit ?? 3); + const { environments, releases, loading, error } = useReleases( + projectId, + props.defaultLimit ?? 3, + ); - return ; -} \ No newline at end of file + return ( + + ); +}; diff --git a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts index ceed04684b..e168735130 100644 --- a/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts +++ b/plugins/octopus-deploy/src/components/EntityPageOctopusDeploy/index.ts @@ -1 +1,16 @@ -export { EntityPageOctopusDeploy } from './EntityPageOctopusDeploy'; \ No newline at end of file +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { EntityPageOctopusDeploy } from './EntityPageOctopusDeploy'; diff --git a/plugins/octopus-deploy/src/components/ReleaseTable/index.ts b/plugins/octopus-deploy/src/components/ReleaseTable/index.ts index bd0b5bb6b1..d0c679a48e 100644 --- a/plugins/octopus-deploy/src/components/ReleaseTable/index.ts +++ b/plugins/octopus-deploy/src/components/ReleaseTable/index.ts @@ -1 +1,16 @@ -export { ReleaseTable } from './ReleaseTable'; \ No newline at end of file +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { ReleaseTable } from './ReleaseTable'; diff --git a/plugins/octopus-deploy/src/constants.ts b/plugins/octopus-deploy/src/constants.ts index cec3804d9d..391dacb42c 100644 --- a/plugins/octopus-deploy/src/constants.ts +++ b/plugins/octopus-deploy/src/constants.ts @@ -1 +1,16 @@ -export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id'; \ No newline at end of file +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id'; diff --git a/plugins/octopus-deploy/src/hooks/useReleases.ts b/plugins/octopus-deploy/src/hooks/useReleases.ts index ce38bfb286..742ce78dca 100644 --- a/plugins/octopus-deploy/src/hooks/useReleases.ts +++ b/plugins/octopus-deploy/src/hooks/useReleases.ts @@ -1,26 +1,45 @@ -import { useApi } from "@backstage/core-plugin-api"; -import useAsync from "react-use/lib/useAsync"; -import { octopusDeployApiRef, OctopusEnvironment, OctopusReleaseProgression } from "../api"; +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { useApi } from '@backstage/core-plugin-api'; +import useAsync from 'react-use/lib/useAsync'; +import { + octopusDeployApiRef, + OctopusEnvironment, + OctopusReleaseProgression, +} from '../api'; export function useReleases( - projectId: string, - releaseHistoryCount: number + projectId: string, + releaseHistoryCount: number, ): { - environments?: OctopusEnvironment[], - releases?: OctopusReleaseProgression[] - loading: boolean; - error?: Error; + environments?: OctopusEnvironment[]; + releases?: OctopusReleaseProgression[]; + loading: boolean; + error?: Error; } { - const api = useApi(octopusDeployApiRef); - - const { value, loading, error } = useAsync(() => { - return api.getReleaseProgression(projectId, releaseHistoryCount); - }, [ api, projectId, releaseHistoryCount ]); + const api = useApi(octopusDeployApiRef); - return { - environments: value?.Environments, - releases: value?.Releases, - loading, - error - }; -} \ No newline at end of file + const { value, loading, error } = useAsync(() => { + return api.getReleaseProgression(projectId, releaseHistoryCount); + }, [api, projectId, releaseHistoryCount]); + + return { + environments: value?.Environments, + releases: value?.Releases, + loading, + error, + }; +} diff --git a/plugins/octopus-deploy/src/plugin.ts b/plugins/octopus-deploy/src/plugin.ts index c73f4b3aed..1634da2a9a 100644 --- a/plugins/octopus-deploy/src/plugin.ts +++ b/plugins/octopus-deploy/src/plugin.ts @@ -1,13 +1,30 @@ -import { - OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION -} from './constants'; -import { - octopusDeployEntityContentRouteRef -} from './routes'; +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from './constants'; +import { octopusDeployEntityContentRouteRef } from './routes'; import { OctopusDeployClient, octopusDeployApiRef } from './api'; -import { createApiFactory, createPlugin, createRoutableExtension, discoveryApiRef, identityApiRef } from '@backstage/core-plugin-api'; +import { + createApiFactory, + createPlugin, + createRoutableExtension, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; @@ -21,9 +38,10 @@ export const octopusDeployPlugin = createPlugin({ createApiFactory({ api: octopusDeployApiRef, deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, - factory: ({ discoveryApi, identityApi }) => new OctopusDeployClient({ discoveryApi, identityApi }) - }) - ] + factory: ({ discoveryApi, identityApi }) => + new OctopusDeployClient({ discoveryApi, identityApi }), + }), + ], }); /* @@ -42,8 +60,8 @@ export const EntityOctopusDeployContent = octopusDeployPlugin.provide( name: 'EntityOctopusDeployContent', component: () => import('./components/EntityPageOctopusDeploy').then( - m => m.EntityPageOctopusDeploy + m => m.EntityPageOctopusDeploy, ), - mountPoint: octopusDeployEntityContentRouteRef - }) -) \ No newline at end of file + mountPoint: octopusDeployEntityContentRouteRef, + }), +); diff --git a/plugins/octopus-deploy/src/routes.ts b/plugins/octopus-deploy/src/routes.ts index 772db37cb6..824b6ae113 100644 --- a/plugins/octopus-deploy/src/routes.ts +++ b/plugins/octopus-deploy/src/routes.ts @@ -1,5 +1,20 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import { createRouteRef } from '@backstage/core-plugin-api'; export const octopusDeployEntityContentRouteRef = createRouteRef({ - id: 'octopus-deploy-entity-content' -}) + id: 'octopus-deploy-entity-content', +}); diff --git a/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts index b1a8984163..96ac4d19f7 100644 --- a/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts +++ b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts @@ -1,14 +1,30 @@ -import { - OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION -} from '../constants'; +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from '../constants'; import { Entity } from '@backstage/catalog-model'; export function getAnnotationFromEntity(entity: Entity): string { - const annotation = entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION]; - if (!annotation) { - throw new Error('Value for annotation octopus.com/project-id was not found'); - } - - return annotation; -} \ No newline at end of file + const annotation = + entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION]; + if (!annotation) { + throw new Error( + 'Value for annotation octopus.com/project-id was not found', + ); + } + + return annotation; +} From 00280716a99f0c5d622ca04bbc26d999d9309675 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 13:42:05 +0000 Subject: [PATCH 187/417] chore(deps): update dependency @types/nunjucks to v3.2.2 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7be6e97178..3107770cf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15014,9 +15014,9 @@ __metadata: linkType: hard "@types/nunjucks@npm:^3.1.4": - version: 3.2.1 - resolution: "@types/nunjucks@npm:3.2.1" - checksum: 40f3dd8968cd30c19a99c6eec55e3bf354da39ce08840a8d652a7c9754a7e5a8a59f92fb258862c56d223f9908b62c347006d0a26f685a5dc72f13bdb68ce778 + version: 3.2.2 + resolution: "@types/nunjucks@npm:3.2.2" + checksum: e0fdc68f01635b34ea6f5e8845ed6d2e8d11be6347b2f28c8093636454e2401f02c26a2ad6aa459da56f2459f2d59bf72914b6e4774bcd058fa12e2ae5f0f6ef languageName: node linkType: hard From bfea425f8a417c2bce69b62f17ef0e712dcbc2d7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 13:54:08 +0000 Subject: [PATCH 188/417] fix(deps): update dependency @google-cloud/storage to v6.9.3 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 43cdab7a66..42725feb83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9752,8 +9752,8 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^6.0.0": - version: 6.9.2 - resolution: "@google-cloud/storage@npm:6.9.2" + version: 6.9.3 + resolution: "@google-cloud/storage@npm:6.9.3" dependencies: "@google-cloud/paginator": ^3.0.7 "@google-cloud/projectify": ^3.0.0 @@ -9772,7 +9772,7 @@ __metadata: retry-request: ^5.0.0 teeny-request: ^8.0.0 uuid: ^8.0.0 - checksum: e4962be29ca3dd722019db95f99b095993534915d663a82b41c95beaf284d878de5b1357102441e4e375de838299f6d82eff55a2c4e9f610f9a12feac21e2735 + checksum: 32bd3b49509b823504f0007d1d5cb1ec854bbc84e6be1ef397879b99c0f198c6251b85ddec81226428e046a06c0346356d82d26485e9d1f9e7ef943e091db06f languageName: node linkType: hard From fe5646e63f3740c53093215109496c283634e633 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 15:25:52 +0100 Subject: [PATCH 189/417] More prettying Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/README.md | 1 - plugins/octopus-deploy/src/index.ts | 27 +++++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/plugins/octopus-deploy/README.md b/plugins/octopus-deploy/README.md index a789bfabfb..abc0559896 100644 --- a/plugins/octopus-deploy/README.md +++ b/plugins/octopus-deploy/README.md @@ -59,4 +59,3 @@ spec: ``` All set , you will be able to see the plugin in action! - diff --git a/plugins/octopus-deploy/src/index.ts b/plugins/octopus-deploy/src/index.ts index 9573438e87..f3696853df 100644 --- a/plugins/octopus-deploy/src/index.ts +++ b/plugins/octopus-deploy/src/index.ts @@ -1,7 +1,22 @@ -export { - octopusDeployPlugin, - EntityOctopusDeployContent, - isOctopusDeployAvailable - } from './plugin'; +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { + octopusDeployPlugin, + EntityOctopusDeployContent, + isOctopusDeployAvailable, +} from './plugin'; - export * from './api'; +export * from './api'; From d85c4ae7c06f1daa4ec8f3ea43b5f4fdd5a3a8d0 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Wed, 15 Feb 2023 15:27:09 +0100 Subject: [PATCH 190/417] Add notice to test files Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/src/plugin.test.ts | 15 +++++++++++++++ plugins/octopus-deploy/src/setupTests.ts | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/plugins/octopus-deploy/src/plugin.test.ts b/plugins/octopus-deploy/src/plugin.test.ts index ec8e3f260d..a18e74f689 100644 --- a/plugins/octopus-deploy/src/plugin.test.ts +++ b/plugins/octopus-deploy/src/plugin.test.ts @@ -1,3 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import { octopusDeployPlugin } from './plugin'; describe('octopus-deploy', () => { diff --git a/plugins/octopus-deploy/src/setupTests.ts b/plugins/octopus-deploy/src/setupTests.ts index 48c09b5346..73dd8dce47 100644 --- a/plugins/octopus-deploy/src/setupTests.ts +++ b/plugins/octopus-deploy/src/setupTests.ts @@ -1,2 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import '@testing-library/jest-dom'; import 'cross-fetch/polyfill'; From b44c01cb70b1eadebfa1206853359e69dc27d152 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 15 Feb 2023 16:56:43 +0100 Subject: [PATCH 191/417] microsite/blog: add blog post about backend system alpha Signed-off-by: Patrik Oldsberg --- .../blog/2023-02-15-backend-system-alpha.md | 83 ++++++++++++++++++ .../2023-02-15/backend-system-alpha.gif | Bin 0 -> 1642820 bytes .../backend-system-architecture.png | Bin 0 -> 34972 bytes 3 files changed, 83 insertions(+) create mode 100644 microsite/blog/2023-02-15-backend-system-alpha.md create mode 100644 microsite/blog/assets/2023-02-15/backend-system-alpha.gif create mode 100644 microsite/blog/assets/2023-02-15/backend-system-architecture.png diff --git a/microsite/blog/2023-02-15-backend-system-alpha.md b/microsite/blog/2023-02-15-backend-system-alpha.md new file mode 100644 index 0000000000..e0238f887a --- /dev/null +++ b/microsite/blog/2023-02-15-backend-system-alpha.md @@ -0,0 +1,83 @@ +--- +title: Backstage Backend System Alpha +author: Patrik Oldsberg +authorURL: https://github.com/Rugvip +authorImageURL: https://avatars.githubusercontent.com/u/4984472?v=4 +--- + +![backend system alpha header image](assets/2023-02-15/backend-system-alpha.gif) + +For the past year, the Backstage maintainer team has been spending time to give the [old Backstage backend system](https://backstage.io/docs/plugins/backend-plugin) a much needed revamp. Our goal was not to build something completely new from scratch, but rather to solidify the existing foundations that have grown organically. We wanted to make plugin installation a lot simpler, while maintaining and even improving the ways in which you can customize your backend setups. + +We’re happy to announce that the [v1.11](https://backstage.io/docs/releases/v1.11.0) release includes the public alpha of the [new Backstage backend system](https://backstage.io/docs/backend-system/)! The system has already been available to use for some time, as some of you have already found, but this alpha release marks the point where we are finally ready to encourage widespread adoption by plugin builders. We still don’t recommend that you use this new system in your production setups just yet, more on that later. + + + +## History of the Backstage backend system + +The backend system that we all use today has grown very organically based on all the needs that have been discovered along the journey of the Backstage Open Source project. We started out with a very flexible system that was essentially just a collection of recommended patterns for plugins, along with a couple of common interfaces and utilities. This was largely due to the fact that before it was open sourced, the Backstage backend services at Spotify were all built on top of internal frameworks and practices that we couldn’t bring with us. Back in 2020, we didn’t have a lot of knowledge about what a good backend system for Backstage would look like, so we started off with a highly flexible foundation that would evolve organically over time. + +As Backstage grew across all dimensions of adopter count, community size, code size, and capability, we saw the need to take a step back and reevaluate how Backstage backend plugins are built. About one year ago, the maintainers sat down and started to sketch what a new backend system could look like. + +## Designing the New System + +When we set out on this project, we had a few primary goals. First, we intended to introduce as few new concepts as possible. Our existing system already had a lot of different patterns, and ideally we wanted to only give those patterns names and make them part of the framework. Second, we wanted to keep the backend system recognizable to those familiar with the frontend system. The list of goals goes on, we had a lot of reasons to build this new system, these are a few more important ones: + +- Make it easier to create and maintain backend installations. +- Align how plugins provide points of customization and how those customizations are installed. +- Make it much easier to maintain plugins, in particular keeping the API stable. +- Simplify the process of splitting plugins out into separate deployments with shared environments. +- Improve the local development and testing experience. + +Prioritizing simplicity is often a guiding principle that we use for designs that span multiple ownership roles. We decide on which parts of the system that we think are the most important to have as simple as possible, or, viewed from the opposite end, where in the system we put necessary complexity. In this case, we optimized for keeping the backend setup as simple as possible, followed by modules and plugins, then libraries, and lastly the framework itself. What this guidance means in practice is that when there is complexity that needs to be added to implement a certain feature, we place as much of it as possible within the framework itself, then libraries, plugins and modules, and if absolutely needed, the backend setup. + +To get the Backstage backend system to where we are today, we went through three major stages, starting with some very early high level experimentation. If you’re a fan of Git archaeology, you can see some of our early ideas in [our experiments branch](https://github.com/backstage/backstage/commit/fd3e6b67fef25a04789779700db4c37047d59d1b), as well as the [separate repository](https://github.com/backstage/backend-system-exploration) that we used to explore different ideas together with [Roadie](https://roadie.io/). The output of this work was all presented in an [RFC](https://github.com/backstage/backstage/issues/11611) to gather feedback. + +A few months later as the RFC settled, we resumed work and followed up with an initial implementation. At this point there were still a lot of details in the design to figure out, especially as we started looking at how our existing plugins and services fit into this new system. We identified a lot of aspects that we inevitably didn’t consider in the initial design, and started exploring technical solutions to those problems. There was a lot of zooming in and out, both implementing details and then stepping back and looking at how that affects the broader system and where to go next. This ended up being the most time consuming stage, and we spent several months iterating on this. + +We wrapped up this work just before KubeCon NA 2022, with the full system implemented. The state of the system at this point was presented in our talk on the topic, which you can see just below. Except for a few API tweaks, this is what the system still looks like today. + + + +
    + +The final stage was all about polish, which we picked up at the beginning of this year. By leaving a bit of space between the main implementation, or phase two, and the polish phase, phase three, it was much easier to properly scrutinize our past solutions. We forget a lot of the low level reasoning for changes, and it is easier to step back and reconsider parts of the system. For example, we found that our initial design of the `createServiceFactory` function was unnecessarily complex, and could be made much simpler for most usages. In addition to reviewing all the APIs, we also wrote more documentation to help users, ensured that the local development and testing experience was solid, and double checked that there was a smooth migration path from the old system. + +## Architecture + +Now that you’ve learned about the journey of designing the new system, let’s review the new architecture. This blog includes a brief introduction to the architecture of the new system. If you want to dive deeper, check out our [architecture documentation](https://backstage.io/docs/backend-system/architecture/). + +The backend system has five major building blocks: + +- Backend instances act as dependency injection containers and are the unit of deployment in which you install plugins and modules that you want to use. +- Plugins implement the actual features and main business logic, for example the service catalog. +- Services provide shared utilities for plugins to use, for example logging, database access, and serving HTTP. Services are provided by the backend and can be customized in each backend instance. +- Extension Points serve as an optional API surface for plugins to provide deeper customization, such as installing custom processors in the catalog. It is up to each plugin to define their own extension points. +- Modules extend individual plugins with additional features by interacting with the extension points that the plugins expose. A module might for example implement a single entity provider for the catalog. + +![backend system architecture](assets/2023-02-15/backend-system-architecture.png) + +## Benefits of the New System + +This new system reduced the size of a typical backend installation from hundreds of lines of code to just about two dozen, more than an order of magnitude. This reduction comes from shifting complexity away from the backend installation and into the plugins, services, and the backend system itself. Not only does this make a typical backend setup much easier to maintain, but it also makes it much easier to build plugins and modules, and leaves fewer patterns to be unnecessarily invented. + +As part of this shift, we’ve moved many concepts from being coding patterns to being features built into the framework. This will allow us to further evolve the backend system in much more interesting ways, and still bring along the entire Backstage plugin ecosystem. It also helps align Backstage plugins around a couple of extensibility patterns, rather than each plugin having their own bespoke patterns for how extensions are installed. + +## Alpha, what does it mean? + +With the release of the backend system into alpha, we are confident enough in the design of the system that we encourage plugin owners to add support for the new system in their plugins. This means following the [plugin migration guide](https://backstage.io/docs/backend-system/building-plugins-and-modules/migrating) and exporting a plugin instance. Do not remove support for the old system yet – keep your existing `createRouter` export intact. + +While we encourage migration of plugins, we do not yet recommend migrating your backend installations to the new system. We want to create space to gather and address feedback from the plugin migration experience, and to make changes if necessary. + +If you are worried about the upcoming backend migration, you can [take a peek](https://backstage.io/docs/backend-system/building-backends/migrating#migrating-the-index-file) at our `legacyPlugin` helper. It allows you to forklift over all existing plugin setups to the new backend system, and then migrate plugins one by one. + +## Next Steps + +During the next release we will keep working on migrating the core plugins, as well as addressing any feedback that we receive. We don’t want to rush a stable release though, and won’t encourage broad adoption until we’re confident that we won’t have to follow it up with immediate breaking changes. Yet, we are excited about where we are today, and are looking forward to the future stable release! + +Useful Links: + +- [Architecture Docs](https://backstage.io/docs/backend-system/architecture/) +- [Building Plugin](https://backstage.io/docs/backend-system/building-plugins-and-modules/) +- [Core Services](https://backstage.io/docs/backend-system/core-services/) +- [#backend-system](https://discord.com/channels/687207715902193673/1034089724664610938) channel in Discord diff --git a/microsite/blog/assets/2023-02-15/backend-system-alpha.gif b/microsite/blog/assets/2023-02-15/backend-system-alpha.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca91651e9acf2c6a9c4f61a544b1d6f32c91410d GIT binary patch literal 1642820 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

    w@uf$V)7^{ezAa1>e4m}{SsS=rNOfs+ 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

    BEs3}233=Ax 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

    2E7Omd1_DlF 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

    _{4ef6Bja8|I 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 z

    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

    5>}OQuEX;kbgpR5 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≈(9d#(wFwY#ALqN&o@7 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

    >yZVZ!kI-S(Pc$R8mqwq}SL^pBmc763uow3vMX; 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 z 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 z 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

    6n*A86CEABLvBR~- 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

    om7Zm~c5U?X6}yxdL;*1y%$y< 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


    C>O`5WI{ zv;1ThTc55J_h!_mkN5YIk+ZXPPLSLffJ7PVouD}v7ajjturT!YC%rCyrHQ(?;2PZS zB0RsTKO2EJI8q#|8Y7V0a&{3hg`C)Q&8ZjvQxb%9Xa!u^Jl>sKR{ESnuH->?Xc_d6 zkHC?p<>NFrbC%8-d22w&iKGht4y1c?HJe=1#Eszet97w(lmeUs3n6x^gh{yYB7LqC zX@6<>I(dN3UHCVPRu7nY*b(Cfa}bkwrgddn?yQXhM@D7>{tH+q{c4R&w=@g>oG=a)q6Eh@Ig5@EOJ2`@!$t3E zXicoMP)P^cnb*U)PvK3cwL=CDq~D@2fb$-ua1eYPcPTh^3Ju=;Pm45-WlY zx54OrglF&FBAUnO?|}ou;a<7b zL4VLOSl~UQC@$=T$ts#g4$bgWE{^4;9zSF94R{H!+voxby)f3mBchKKc`oiNEA@tk zPG4F{9o*B^PLmg6C*fzucsE+=T*w0$o7^F_EeZ+-t?QHe`4x|ier$tQr=I~ zGZKtWysPY&R3*?%iLYK_HOYJ%`o&I!%i5&;I4HbHl^jkru<}b_pj+3pG+KqD@CQ*= zD2PJMGp%^CSoXN~^PLMVHjkx9m{-?J+zqJP;NT*56{zKhtJrW1W>PN)w)SYi^CNGg zeH~K<>fgYGx>F-D2vesX*v_>O0FqW<=OktY0LC?Z1=d2F7{GDX-`cMKU=}Qic9xPL zZ^($^ZG}_jG$-B~`&-l^a)CYTOx0VsznFsyJY7+gV!xSuB-yDoV3b&VFB10xs$`CC z-ANNcfRHC3EljCkYdRB=?wt|K`m$*vkEY_IFzc26L9ThLyyr$xoa;Gxclr9@>G-Z$SJefz%WrWA||C5A;V`+tQsov#r9}Rxp z1D6VDSvfL&3-r zbp9Rb%hF&Tril}Tka4B=hRdG4!?w**A2p9SGxvdrJMFZ$<;!GJsYIRj(qZ&&fql#$ z~Xb&;sT;W!Oh0&s~54{Ykc%n)<3%s_}ef0mpt^~5G=b7_a z1fNr(((3uI!Nx-?#prt8(R);>>I`280Co380(1{<==D{g=o011+a#U3tE!T0V=}`u z6kTLDwNVeP-}>uGPHDK?t7)7Zo!6i&wDZ1!PshG^;}ZRCP$N{jAHkv}%0q?G`=Iv^Cie4`7SF;vUmX{%ooF_$P%5OR~o;*9+( zD3Y3aY~>kOOVkS=wj~5tbpFj2Zs%6M-Tx#$y;=O`&nA5-`zn$lW&`r*gw)_eYW^hOIQ#!T^kN8!EM4(mpP8TpJ-~2d!

    ;;k*0Im~?GK5JhD;WL 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%0Dx)GKYzO7R0C* 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

    pqb_leUL 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 G7XJcGR5@V) literal 0 HcmV?d00001 diff --git a/microsite/blog/assets/2023-02-15/backend-system-architecture.png b/microsite/blog/assets/2023-02-15/backend-system-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..90c1a495fd8c6b5ab334de52eee70c6c7b96fc70 GIT binary patch literal 34972 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 Date: Wed, 15 Feb 2023 18:38:42 +0100 Subject: [PATCH 192/417] Use outerHTML during sanitize to preserve html tag attribs Signed-off-by: Raghunandan --- .../src/reader/transformers/html/transformer.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/techdocs/src/reader/transformers/html/transformer.ts b/plugins/techdocs/src/reader/transformers/html/transformer.ts index a197a2d4b7..61498a37b0 100644 --- a/plugins/techdocs/src/reader/transformers/html/transformer.ts +++ b/plugins/techdocs/src/reader/transformers/html/transformer.ts @@ -15,12 +15,12 @@ */ import DOMPurify from 'dompurify'; -import { useMemo, useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; -import { useApi, configApiRef } from '@backstage/core-plugin-api'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Transformer } from '../transformer'; -import { removeUnsafeLinks, removeUnsafeIframes } from './hooks'; +import { removeUnsafeIframes, removeUnsafeLinks } from './hooks'; /** * Returns html sanitizer configuration @@ -34,7 +34,7 @@ const useSanitizerConfig = () => { }; /** - * Returns a transformer that sanitizes the dom's internal html. + * Returns a transformer that sanitizes the dom */ export const useSanitizerTransformer = (): Transformer => { const config = useSanitizerConfig(); @@ -51,7 +51,8 @@ export const useSanitizerTransformer = (): Transformer => { DOMPurify.addHook('beforeSanitizeElements', removeUnsafeIframes(hosts)); } - return DOMPurify.sanitize(dom.innerHTML, { + // using outerHTML as we want to preserve the html tag attributes (lang) + return DOMPurify.sanitize(dom.outerHTML, { ADD_TAGS: tags, FORBID_TAGS: ['style'], WHOLE_DOCUMENT: true, From f320c299c67b3f1eea9752f25692483e2168504a Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Wed, 15 Feb 2023 18:47:18 +0100 Subject: [PATCH 193/417] Add changeset Signed-off-by: Raghunandan --- .changeset/ninety-turtles-wait.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/ninety-turtles-wait.md diff --git a/.changeset/ninety-turtles-wait.md b/.changeset/ninety-turtles-wait.md new file mode 100644 index 0000000000..18f9dc70e9 --- /dev/null +++ b/.changeset/ninety-turtles-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +The html tag attributes in the documentation content inserted to shadow DOM is preserved to improve accessibility From d70d11e60018afbdfd20202ab0e95093b938de98 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 15 Feb 2023 19:13:35 +0100 Subject: [PATCH 194/417] Update 2023-02-15-backend-system-alpha.md Signed-off-by: Patrik Oldsberg --- microsite/blog/2023-02-15-backend-system-alpha.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/blog/2023-02-15-backend-system-alpha.md b/microsite/blog/2023-02-15-backend-system-alpha.md index e0238f887a..9970945f67 100644 --- a/microsite/blog/2023-02-15-backend-system-alpha.md +++ b/microsite/blog/2023-02-15-backend-system-alpha.md @@ -78,6 +78,6 @@ During the next release we will keep working on migrating the core plugins, as w Useful Links: - [Architecture Docs](https://backstage.io/docs/backend-system/architecture/) -- [Building Plugin](https://backstage.io/docs/backend-system/building-plugins-and-modules/) +- [Building Plugins](https://backstage.io/docs/backend-system/building-plugins-and-modules/) - [Core Services](https://backstage.io/docs/backend-system/core-services/) - [#backend-system](https://discord.com/channels/687207715902193673/1034089724664610938) channel in Discord From 2ea578216294ea714c0f84ccfdecfdc524050ba1 Mon Sep 17 00:00:00 2001 From: Elizabeth Hobbs Date: Wed, 15 Feb 2023 10:24:12 -0800 Subject: [PATCH 195/417] [linguist-backend] no longer skip initial batch Fixes #16370 Co-authored-by: Jason Nguyen Co-authored-by: Thomas Camargo Signed-off-by: Jason Nguyen Signed-off-by: Thomas Camargo Signed-off-by: Elizabeth Hobbs --- .changeset/slimy-lobsters-kneel.md | 5 +++++ plugins/linguist-backend/src/api/LinguistBackendApi.ts | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/slimy-lobsters-kneel.md diff --git a/.changeset/slimy-lobsters-kneel.md b/.changeset/slimy-lobsters-kneel.md new file mode 100644 index 0000000000..40ff476a64 --- /dev/null +++ b/.changeset/slimy-lobsters-kneel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-linguist-backend': patch +--- + +Fixed bug in LinguistBackendApi that caused initial batch of entities to be skipped. diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index 34d04b02f9..6c2e46e112 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -114,6 +114,7 @@ export class LinguistBackendApi { ); const entities = entitiesOverview.filteredEntities.slice( + 0, this.batchSize ?? 20, ); entities.forEach(async entityRef => { From 91ac8efbb149785e4f64319be343920d18817b59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Feb 2023 18:50:49 +0000 Subject: [PATCH 196/417] fix(deps): update dependency minimist to v1.2.8 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7d00ad8f19..765a698204 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29483,9 +29483,9 @@ __metadata: linkType: hard "minimist@npm:>=1.2.2, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": - version: 1.2.7 - resolution: "minimist@npm:1.2.7" - checksum: 7346574a1038ca23c32e02252f603801f09384dd1d78b69a943a4e8c2c28730b80e96193882d3d3b22a063445f460e48316b29b8a25addca2d7e5e8f75478bec + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 languageName: node linkType: hard From ae08281331c96e526f82d9e33930179438511067 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Wed, 15 Feb 2023 14:31:50 -0500 Subject: [PATCH 197/417] expose the todos-backend plugin using the new plugin system Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- packages/backend-next/src/index.ts | 2 + plugins/todo-backend/src/lib/utils.ts | 107 ++++++++++++++++++ plugins/todo-backend/src/plugin.ts | 86 ++++++++++++++ .../src/service/TodoReaderService.ts | 35 +++++- plugins/todo-backend/src/service/index.ts | 2 + plugins/todo-backend/src/service/plugin.ts | 94 +++++++++++++++ plugins/todo-backend/src/service/router.ts | 106 ++--------------- plugins/todo-backend/src/service/types.ts | 8 ++ 8 files changed, 340 insertions(+), 100 deletions(-) create mode 100644 plugins/todo-backend/src/lib/utils.ts create mode 100644 plugins/todo-backend/src/plugin.ts create mode 100644 plugins/todo-backend/src/service/plugin.ts diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index 97b6eaf32b..a2f542afb1 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -18,10 +18,12 @@ import { catalogPlugin } from '@backstage/plugin-catalog-backend'; import { catalogModuleTemplateKind } from '@backstage/plugin-scaffolder-backend'; import { createBackend } from '@backstage/backend-defaults'; import { appPlugin } from '@backstage/plugin-app-backend'; +import { todosPlugin } from '@backstage/plugin-todo-backend'; const backend = createBackend(); backend.add(catalogPlugin()); backend.add(catalogModuleTemplateKind()); backend.add(appPlugin({ appPackageName: 'example-app' })); +backend.add(todosPlugin()); backend.start(); diff --git a/plugins/todo-backend/src/lib/utils.ts b/plugins/todo-backend/src/lib/utils.ts new file mode 100644 index 0000000000..cf0c2e4ea6 --- /dev/null +++ b/plugins/todo-backend/src/lib/utils.ts @@ -0,0 +1,107 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { InputError } from '@backstage/errors'; + +export const parseIntegerParam = ( + str: unknown, + ctx: string, +): number | undefined => { + if (str === undefined) { + return undefined; + } + if (typeof str !== 'string') { + throw new InputError(`invalid ${ctx}, must be a string`); + } + const parsed = parseInt(str, 10); + if (!Number.isInteger(parsed) || String(parsed) !== str) { + throw new InputError(`invalid ${ctx}, not an integer`); + } + return parsed; +}; + +export const parseOrderByParam = ( + str: unknown, + allowedFields: T, +): { field: T[number]; direction: 'asc' | 'desc' } | undefined => { + if (str === undefined) { + return undefined; + } + if (typeof str !== 'string') { + throw new InputError(`invalid orderBy query, must be a string`); + } + const [field, direction] = str.split('='); + if (!field) { + throw new InputError(`invalid orderBy query, field name is empty`); + } + if (direction !== 'asc' && direction !== 'desc') { + throw new InputError( + `invalid orderBy query, order direction must be 'asc' or 'desc'`, + ); + } + + if (field && !allowedFields.includes(field)) { + throw new InputError( + `invalid orderBy field, must be one of ${allowedFields.join(', ')}`, + ); + } + return { field, direction }; +}; + +export const parseFilterParam = ( + str: unknown, + allowedFields: T, +): { field: T[number]; value: string }[] | undefined => { + if (str === undefined) { + return undefined; + } + + const filters = new Array<{ field: T[number]; value: string }>(); + + const strs = [str].flat(); + for (const filterStr of strs) { + if (typeof filterStr !== 'string') { + throw new InputError( + `invalid filter query, must be a string or list of strings`, + ); + } + const splitIndex = filterStr.indexOf('='); + if (splitIndex <= 0) { + throw new InputError( + `invalid filter query, must separate field from value using '='`, + ); + } + + const field = filterStr.slice(0, splitIndex); + if (!allowedFields.includes(field)) { + throw new InputError( + `invalid filter field, must be one of ${allowedFields.join(', ')}`, + ); + } + + const value = filterStr.slice(splitIndex + 1); + if (!value) { + throw new InputError(`invalid filter query, value may not be empty`); + } + filters.push({ field, value }); + } + + return filters; +}; + +export const getBearerToken = (header?: string): string | undefined => { + return header?.match(/Bearer\s+(\S+)/i)?.[1]; +}; diff --git a/plugins/todo-backend/src/plugin.ts b/plugins/todo-backend/src/plugin.ts new file mode 100644 index 0000000000..49e8d354b1 --- /dev/null +++ b/plugins/todo-backend/src/plugin.ts @@ -0,0 +1,86 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + createBackendPlugin, + coreServices, +} from '@backstage/backend-plugin-api'; +import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; +import { InputError } from '@backstage/errors'; +import express, { Router } from 'express'; +import { + getBearerToken, + parseFilterParam, + parseIntegerParam, + parseOrderByParam, +} from './lib/utils'; +import { todoReaderServiceRef } from './service/TodoReaderService'; +import { TODO_FIELDS } from './service/types'; + +/** + * The Todos plugin is responsible for aggregating todo comments within source. + * @alpha + */ +export const todosPlugin = createBackendPlugin({ + pluginId: 'todo-backend', + register(env) { + env.registerInit({ + deps: { + todoReader: todoReaderServiceRef, + http: coreServices.httpRouter, + }, + async init({ http, todoReader }) { + const router = Router(); + router.use(express.json()); + + router.get('/v1/todos', async (req, res) => { + const offset = parseIntegerParam(req.query.offset, 'offset query'); + const limit = parseIntegerParam(req.query.limit, 'limit query'); + const orderBy = parseOrderByParam(req.query.orderBy, TODO_FIELDS); + const filters = parseFilterParam(req.query.filter, TODO_FIELDS); + + const entityRef = req.query.entity; + if (entityRef && typeof entityRef !== 'string') { + throw new InputError(`entity query must be a string`); + } + let entity: CompoundEntityRef | undefined = undefined; + if (entityRef) { + try { + entity = parseEntityRef(entityRef); + } catch (error) { + throw new InputError(`Invalid entity ref, ${error}`); + } + } + + const todos = await todoReader.listTodos( + { + entity, + offset, + limit, + orderBy, + filters, + }, + { + token: getBearerToken(req.headers.authorization), + }, + ); + res.json(todos); + }); + http.use(router); + }, + }); + }, +}); diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index 35fd76b8be..93908c0f9f 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -20,8 +20,15 @@ import { getEntitySourceLocation, stringifyEntityRef, } from '@backstage/catalog-model'; -import { TodoReader } from '../lib'; +import { TodoReader, TodoScmReader } from '../lib'; import { ListTodosRequest, ListTodosResponse, TodoService } from './types'; +import { + coreServices, + createServiceFactory, + createServiceRef, +} from '@backstage/backend-plugin-api'; +import { catalogServiceRef } from '@backstage/plugin-catalog-node'; +import { loggerToWinstonLogger } from '@backstage/backend-common'; const DEFAULT_DEFAULT_PAGE_SIZE = 10; const DEFAULT_MAX_PAGE_SIZE = 50; @@ -130,3 +137,29 @@ export class TodoReaderService implements TodoService { }; } } + +export const todoReaderServiceRef = createServiceRef({ + id: 'todo-client', + defaultFactory: async service => + createServiceFactory({ + service, + deps: { + catalogApi: catalogServiceRef, + logger: coreServices.logger, + reader: coreServices.urlReader, + config: coreServices.config, + }, + async factory({ catalogApi, logger, reader, config }) { + const winstonLogger = loggerToWinstonLogger(logger); + const todoReader = TodoScmReader.fromConfig(config, { + reader: reader, + logger: winstonLogger, + }); + return new TodoReaderService({ + catalogClient: catalogApi, + todoReader, + // TODO: override defaults here + }); + }, + }), +}); diff --git a/plugins/todo-backend/src/service/index.ts b/plugins/todo-backend/src/service/index.ts index 380d95dbe1..3dfff3f33e 100644 --- a/plugins/todo-backend/src/service/index.ts +++ b/plugins/todo-backend/src/service/index.ts @@ -19,3 +19,5 @@ export type { RouterOptions } from './router'; export type { TodoService, ListTodosRequest, ListTodosResponse } from './types'; export { TodoReaderService } from './TodoReaderService'; export type { TodoReaderServiceOptions } from './TodoReaderService'; +export { todosPlugin } from './plugin'; +export type { TodosPluginDependencies } from './plugin'; diff --git a/plugins/todo-backend/src/service/plugin.ts b/plugins/todo-backend/src/service/plugin.ts new file mode 100644 index 0000000000..54b089221f --- /dev/null +++ b/plugins/todo-backend/src/service/plugin.ts @@ -0,0 +1,94 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + createBackendPlugin, + coreServices, + HttpRouterService, +} from '@backstage/backend-plugin-api'; +import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; +import { InputError } from '@backstage/errors'; +import express, { Router } from 'express'; +import { + getBearerToken, + parseFilterParam, + parseIntegerParam, + parseOrderByParam, +} from '../lib/utils'; +import { todoReaderServiceRef } from './TodoReaderService'; +import { TodoService, TODO_FIELDS } from './types'; + +export type TodosPluginDependencies = { + todoReader: TodoService; + http: HttpRouterService; +}; + +const todosPluginInit = async (params: TodosPluginDependencies) => { + const { http, todoReader } = params; + const router = Router(); + router.use(express.json()); + + router.get('/v1/todos', async (req, res) => { + const offset = parseIntegerParam(req.query.offset, 'offset query'); + const limit = parseIntegerParam(req.query.limit, 'limit query'); + const orderBy = parseOrderByParam(req.query.orderBy, TODO_FIELDS); + const filters = parseFilterParam(req.query.filter, TODO_FIELDS); + + const entityRef = req.query.entity; + if (entityRef && typeof entityRef !== 'string') { + throw new InputError(`entity query must be a string`); + } + let entity: CompoundEntityRef | undefined = undefined; + if (entityRef) { + try { + entity = parseEntityRef(entityRef); + } catch (error) { + throw new InputError(`Invalid entity ref, ${error}`); + } + } + + const todos = await todoReader.listTodos( + { + entity, + offset, + limit, + orderBy, + filters, + }, + { + token: getBearerToken(req.headers.authorization), + }, + ); + res.json(todos); + }); + http.use(router); +}; + +/** + * @alpha + */ +export const todosPlugin = createBackendPlugin({ + pluginId: 'todo-backend', + register(env) { + env.registerInit({ + deps: { + todoReader: todoReaderServiceRef, + http: coreServices.httpRouter, + }, + init: todosPluginInit, + }); + }, +}); diff --git a/plugins/todo-backend/src/service/router.ts b/plugins/todo-backend/src/service/router.ts index 33356a83d6..5954fab009 100644 --- a/plugins/todo-backend/src/service/router.ts +++ b/plugins/todo-backend/src/service/router.ts @@ -18,15 +18,13 @@ import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; import { InputError } from '@backstage/errors'; import express from 'express'; import Router from 'express-promise-router'; -import { TodoService } from './types'; - -const TODO_FIELDS = [ - 'text', - 'tag', - 'author', - 'viewUrl', - 'repoFilePath', -] as const; +import { type TodoService, TODO_FIELDS } from './types'; +import { + getBearerToken, + parseFilterParam, + parseIntegerParam, + parseOrderByParam, +} from '../lib/utils'; /** @public */ export interface RouterOptions { @@ -78,93 +76,3 @@ export async function createRouter( return router; } - -export function parseIntegerParam( - str: unknown, - ctx: string, -): number | undefined { - if (str === undefined) { - return undefined; - } - if (typeof str !== 'string') { - throw new InputError(`invalid ${ctx}, must be a string`); - } - const parsed = parseInt(str, 10); - if (!Number.isInteger(parsed) || String(parsed) !== str) { - throw new InputError(`invalid ${ctx}, not an integer`); - } - return parsed; -} - -export function parseOrderByParam( - str: unknown, - allowedFields: T, -): { field: T[number]; direction: 'asc' | 'desc' } | undefined { - if (str === undefined) { - return undefined; - } - if (typeof str !== 'string') { - throw new InputError(`invalid orderBy query, must be a string`); - } - const [field, direction] = str.split('='); - if (!field) { - throw new InputError(`invalid orderBy query, field name is empty`); - } - if (direction !== 'asc' && direction !== 'desc') { - throw new InputError( - `invalid orderBy query, order direction must be 'asc' or 'desc'`, - ); - } - - if (field && !allowedFields.includes(field)) { - throw new InputError( - `invalid orderBy field, must be one of ${allowedFields.join(', ')}`, - ); - } - return { field, direction }; -} - -export function parseFilterParam( - str: unknown, - allowedFields: T, -): { field: T[number]; value: string }[] | undefined { - if (str === undefined) { - return undefined; - } - - const filters = new Array<{ field: T[number]; value: string }>(); - - const strs = [str].flat(); - for (const filterStr of strs) { - if (typeof filterStr !== 'string') { - throw new InputError( - `invalid filter query, must be a string or list of strings`, - ); - } - const splitIndex = filterStr.indexOf('='); - if (splitIndex <= 0) { - throw new InputError( - `invalid filter query, must separate field from value using '='`, - ); - } - - const field = filterStr.slice(0, splitIndex); - if (!allowedFields.includes(field)) { - throw new InputError( - `invalid filter field, must be one of ${allowedFields.join(', ')}`, - ); - } - - const value = filterStr.slice(splitIndex + 1); - if (!value) { - throw new InputError(`invalid filter query, value may not be empty`); - } - filters.push({ field, value }); - } - - return filters; -} - -function getBearerToken(header?: string): string | undefined { - return header?.match(/Bearer\s+(\S+)/i)?.[1]; -} diff --git a/plugins/todo-backend/src/service/types.ts b/plugins/todo-backend/src/service/types.ts index 88d2f2b340..ab15e20027 100644 --- a/plugins/todo-backend/src/service/types.ts +++ b/plugins/todo-backend/src/service/types.ts @@ -48,3 +48,11 @@ export interface TodoService { options?: { token?: string }, ): Promise; } + +export const TODO_FIELDS = [ + 'text', + 'tag', + 'author', + 'viewUrl', + 'repoFilePath', +] as const; From ac8929f2f31ae8cb4c569379a88326e918fad035 Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Wed, 15 Feb 2023 20:15:43 +0100 Subject: [PATCH 198/417] Fix export of catalog collator entity transformer Signed-off-by: Ilya Savich --- .changeset/four-lizards-grin.md | 5 +++++ plugins/catalog-backend/src/search/index.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/four-lizards-grin.md diff --git a/.changeset/four-lizards-grin.md b/.changeset/four-lizards-grin.md new file mode 100644 index 0000000000..6fa5f57243 --- /dev/null +++ b/.changeset/four-lizards-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Fix export of `defaultCatalogCollatorEntityTransformer`. diff --git a/plugins/catalog-backend/src/search/index.ts b/plugins/catalog-backend/src/search/index.ts index c2a23e5132..3603ab2e60 100644 --- a/plugins/catalog-backend/src/search/index.ts +++ b/plugins/catalog-backend/src/search/index.ts @@ -17,7 +17,7 @@ export { DefaultCatalogCollatorFactory } from './DefaultCatalogCollatorFactory'; export type { DefaultCatalogCollatorFactoryOptions } from './DefaultCatalogCollatorFactory'; export type { CatalogCollatorEntityTransformer } from './CatalogCollatorEntityTransformer'; -export type { defaultCatalogCollatorEntityTransformer } from './defaultCatalogCollatorEntityTransformer'; +export { defaultCatalogCollatorEntityTransformer } from './defaultCatalogCollatorEntityTransformer'; /** * todo(backstage/techdocs-core): stop exporting this in a future release. From 3b630ee2cda5850783072e65fac7471f6d0a6f25 Mon Sep 17 00:00:00 2001 From: Ana Luiza Ramalho dos Santos Date: Tue, 14 Feb 2023 10:21:22 -0300 Subject: [PATCH 199/417] test: add test from PluginTaskSchedulerJanitor Signed-off-by: Ana Luiza Ramalho dos Santos --- .changeset/rare-buses-swim.md | 2 +- .../tasks/PluginTaskSchedulerJanitor.test.ts | 92 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts diff --git a/.changeset/rare-buses-swim.md b/.changeset/rare-buses-swim.md index 4e4c11e792..4626343ca3 100644 --- a/.changeset/rare-buses-swim.md +++ b/.changeset/rare-buses-swim.md @@ -1,5 +1,5 @@ --- -'@backstage/backend-tasks': minor +'@backstage/backend-tasks': patch --- Added the adapted query to mysql and sqlite3 databases to not returning warning on logs diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts new file mode 100644 index 0000000000..f981bf59fe --- /dev/null +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts @@ -0,0 +1,92 @@ +/* + * Copyright 2021 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 { getVoidLogger } from '@backstage/backend-common'; +import { TestDatabases } from '@backstage/backend-test-utils'; +import { Knex } from 'knex'; +import { Duration } from 'luxon'; +import waitForExpect from 'wait-for-expect'; +import { migrateBackendTasks } from '../database/migrateBackendTasks'; +import { DbTasksRow, DB_TASKS_TABLE } from '../database/tables'; +import { PluginTaskSchedulerJanitor } from './PluginTaskSchedulerJanitor'; + +const insertTask = async (knex: Knex, task: DbTasksRow) => { + return knex(DB_TASKS_TABLE) + .insert(task) + .onConflict('id') + .merge(['settings_json']); +}; + +const getTask = async (knex: Knex): Promise => { + return (await knex(DB_TASKS_TABLE))[0]; +}; + +describe('PluginTaskSchedulerJanitor', () => { + const logger = getVoidLogger(); + const databases = TestDatabases.create({ + ids: ['MYSQL_8', 'POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], + }); + + jest.setTimeout(300_000); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + it.each(databases.eachSupportedId())( + 'Should update date if current_run_expires_at expires , %p', + async databaseId => { + const knex = await databases.init(databaseId); + await migrateBackendTasks(knex); + + const dateYesterday = new Date( + new Date().setDate(new Date().getDate() - 1), + ); + + await insertTask(knex, { + id: 'task1', + settings_json: '', + next_run_start_at: new Date('2023-03-01 00:00:00'), + current_run_ticket: 'ticket', + current_run_started_at: dateYesterday, + current_run_expires_at: dateYesterday, + }); + + const worker = new PluginTaskSchedulerJanitor({ + knex, + waitBetweenRuns: Duration.fromObject({ minutes: 1 }), + logger, + }); + + const abortController = new AbortController(); + + await worker.start(abortController.signal); + + const row1 = await getTask(knex); + + await waitForExpect(async () => { + expect(row1).toEqual( + expect.objectContaining({ + id: 'task1', + current_run_ticket: null, + current_run_started_at: null, + current_run_expires_at: null, + }), + ); + }); + }, + ); +}); From 7e8930ae1c609683f4289c73abba28de50149a46 Mon Sep 17 00:00:00 2001 From: Thomas Cardonne Date: Wed, 15 Feb 2023 23:02:42 +0100 Subject: [PATCH 200/417] fix(plugins-catalog): align icon in CatalogSearchResultListItem Fixes: #16376 Signed-off-by: Thomas Cardonne --- .changeset/fuzzy-trains-search.md | 5 +++++ .../CatalogSearchResultListItem.tsx | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .changeset/fuzzy-trains-search.md diff --git a/.changeset/fuzzy-trains-search.md b/.changeset/fuzzy-trains-search.md new file mode 100644 index 0000000000..229d25f3b5 --- /dev/null +++ b/.changeset/fuzzy-trains-search.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Fix icon alignment in `CatalogSearchResultListItem` diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index a277584d2f..98dd5bd4e2 100644 --- a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -31,7 +31,9 @@ import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; const useStyles = makeStyles( { - item: {}, + item: { + display: 'flex', + }, flexContainer: { flexWrap: 'wrap', }, From 350ee5dcb6a6b9037fdb06f26c5f58bda0d6e787 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Thu, 16 Feb 2023 08:26:47 +0100 Subject: [PATCH 201/417] Add an api-report file Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/api-report.md | 100 +++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 plugins/octopus-deploy/api-report.md diff --git a/plugins/octopus-deploy/api-report.md b/plugins/octopus-deploy/api-report.md new file mode 100644 index 0000000000..84d65804ca --- /dev/null +++ b/plugins/octopus-deploy/api-report.md @@ -0,0 +1,100 @@ +## API Report File for "@backstage/plugin-octopus-deploy" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ApiRef } from '@backstage/core-plugin-api'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; +import { IdentityApi } from '@backstage/core-plugin-api'; + +// Warning: (ae-missing-release-tag) "EntityOctopusDeployContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const EntityOctopusDeployContent: (props: { + defaultLimit?: number | undefined; +}) => JSX.Element; + +// @public (undocumented) +export const isOctopusDeployAvailable: (entity: Entity) => boolean; + +// Warning: (ae-missing-release-tag) "OctopusDeployApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface OctopusDeployApi { + // (undocumented) + getReleaseProgression( + projectId: string, + releaseHistoryCount: number, + ): Promise; +} + +// Warning: (ae-missing-release-tag) "octopusDeployApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const octopusDeployApiRef: ApiRef; + +// Warning: (ae-missing-release-tag) "OctopusDeployClient" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class OctopusDeployClient implements OctopusDeployApi { + // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts + constructor(options: Options); + // (undocumented) + getReleaseProgression( + projectId: string, + releaseHistoryCount: number, + ): Promise; +} + +// Warning: (ae-missing-release-tag) "OctopusDeployment" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OctopusDeployment = { + State: string; +}; + +// Warning: (ae-missing-release-tag) "octopusDeployPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const octopusDeployPlugin: BackstagePlugin<{}, {}, {}>; + +// Warning: (ae-missing-release-tag) "OctopusEnvironment" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OctopusEnvironment = { + Id: string; + Name: string; +}; + +// Warning: (ae-missing-release-tag) "OctopusProgression" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OctopusProgression = { + Environments: OctopusEnvironment[]; + Releases: OctopusReleaseProgression[]; +}; + +// Warning: (ae-missing-release-tag) "OctopusRelease" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OctopusRelease = { + Id: string; + Version: string; +}; + +// Warning: (ae-missing-release-tag) "OctopusReleaseProgression" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type OctopusReleaseProgression = { + Release: OctopusRelease; + Deployments: { + [key: string]: OctopusDeployment[]; + }; +}; + +// (No @packageDocumentation comment for this package) +``` From 4faab54915fae7cd414f1610440e40911c7854d3 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Thu, 16 Feb 2023 08:48:56 +0100 Subject: [PATCH 202/417] Fix API report Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/api-report.md | 28 +++++++------------------ plugins/octopus-deploy/src/api/index.ts | 11 +++++++++- plugins/octopus-deploy/src/plugin.ts | 2 ++ 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/plugins/octopus-deploy/api-report.md b/plugins/octopus-deploy/api-report.md index 84d65804ca..563e7ebea4 100644 --- a/plugins/octopus-deploy/api-report.md +++ b/plugins/octopus-deploy/api-report.md @@ -11,8 +11,6 @@ import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { IdentityApi } from '@backstage/core-plugin-api'; -// Warning: (ae-missing-release-tag) "EntityOctopusDeployContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const EntityOctopusDeployContent: (props: { defaultLimit?: number | undefined; @@ -21,8 +19,6 @@ export const EntityOctopusDeployContent: (props: { // @public (undocumented) export const isOctopusDeployAvailable: (entity: Entity) => boolean; -// Warning: (ae-missing-release-tag) "OctopusDeployApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export interface OctopusDeployApi { // (undocumented) @@ -32,16 +28,11 @@ export interface OctopusDeployApi { ): Promise; } -// Warning: (ae-missing-release-tag) "octopusDeployApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const octopusDeployApiRef: ApiRef; -// Warning: (ae-missing-release-tag) "OctopusDeployClient" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export class OctopusDeployClient implements OctopusDeployApi { - // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts constructor(options: Options); // (undocumented) getReleaseProgression( @@ -50,44 +41,32 @@ export class OctopusDeployClient implements OctopusDeployApi { ): Promise; } -// Warning: (ae-missing-release-tag) "OctopusDeployment" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type OctopusDeployment = { State: string; }; -// Warning: (ae-missing-release-tag) "octopusDeployPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const octopusDeployPlugin: BackstagePlugin<{}, {}, {}>; -// Warning: (ae-missing-release-tag) "OctopusEnvironment" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type OctopusEnvironment = { Id: string; Name: string; }; -// Warning: (ae-missing-release-tag) "OctopusProgression" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type OctopusProgression = { Environments: OctopusEnvironment[]; Releases: OctopusReleaseProgression[]; }; -// Warning: (ae-missing-release-tag) "OctopusRelease" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type OctopusRelease = { Id: string; Version: string; }; -// Warning: (ae-missing-release-tag) "OctopusReleaseProgression" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type OctopusReleaseProgression = { Release: OctopusRelease; @@ -96,5 +75,12 @@ export type OctopusReleaseProgression = { }; }; +// @public (undocumented) +export type Options = { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; + proxyPathBase?: string; +}; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/octopus-deploy/src/api/index.ts b/plugins/octopus-deploy/src/api/index.ts index f89e429f64..dcdd881c10 100644 --- a/plugins/octopus-deploy/src/api/index.ts +++ b/plugins/octopus-deploy/src/api/index.ts @@ -19,37 +19,44 @@ import { IdentityApi, } from '@backstage/core-plugin-api'; +/** @public */ export type OctopusProgression = { Environments: OctopusEnvironment[]; Releases: OctopusReleaseProgression[]; }; +/** @public */ export type OctopusEnvironment = { Id: string; Name: string; }; +/** @public */ export type OctopusReleaseProgression = { Release: OctopusRelease; Deployments: { [key: string]: OctopusDeployment[] }; }; +/** @public */ export type OctopusRelease = { Id: string; Version: string; }; +/** @public */ export type OctopusDeployment = { State: string; }; +/** @public */ export const octopusDeployApiRef = createApiRef({ id: 'plugin.octopusdeploy.service', }); const DEFAULT_PROXY_PATH_BASE = '/octopus-deploy'; -type Options = { +/** @public */ +export type Options = { discoveryApi: DiscoveryApi; identityApi: IdentityApi; /** @@ -58,6 +65,7 @@ type Options = { proxyPathBase?: string; }; +/** @public */ export interface OctopusDeployApi { getReleaseProgression( projectId: string, @@ -65,6 +73,7 @@ export interface OctopusDeployApi { ): Promise; } +/** @public */ export class OctopusDeployClient implements OctopusDeployApi { private readonly discoveryApi: DiscoveryApi; private readonly identityApi: IdentityApi; diff --git a/plugins/octopus-deploy/src/plugin.ts b/plugins/octopus-deploy/src/plugin.ts index 1634da2a9a..15bb32c9bd 100644 --- a/plugins/octopus-deploy/src/plugin.ts +++ b/plugins/octopus-deploy/src/plugin.ts @@ -32,6 +32,7 @@ import { Entity } from '@backstage/catalog-model'; export const isOctopusDeployAvailable = (entity: Entity) => Boolean(entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION]); +/** @public */ export const octopusDeployPlugin = createPlugin({ id: 'octopus-deploy', apis: [ @@ -55,6 +56,7 @@ export const OctopusDeployPage = octopusDeployPlugin.provide( ); */ +/** @public */ export const EntityOctopusDeployContent = octopusDeployPlugin.provide( createRoutableExtension({ name: 'EntityOctopusDeployContent', From de6fcb0822387da055d45e1f0ecd9c394734b4e5 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 09:42:03 +0000 Subject: [PATCH 203/417] fix: add a comment to installation instructions to README.md Signed-off-by: pamelin --- plugins/stackstorm/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/stackstorm/README.md b/plugins/stackstorm/README.md index 1671e6150f..0d5caeaca2 100644 --- a/plugins/stackstorm/README.md +++ b/plugins/stackstorm/README.md @@ -16,6 +16,7 @@ One of the quickest ways is [running StackStorm with Docker](https://docs.stacks 1. Install the plugin with `yarn` in the root of your Backstage directory ```bash +# From your Backstage root directory yarn --cwd packages/app add @backstage/plugin-stackstorm ``` From b6a04cb4b37bc1723b5d6d58dde49a4089b4ecfd Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 09:44:49 +0000 Subject: [PATCH 204/417] fix: remove unnecessary Grid on the StackStormHome Signed-off-by: pamelin --- .../StackStormHome/StackStormHome.tsx | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx index a059505c2b..d3065ff2e5 100644 --- a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx +++ b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { Grid, IconButton } from '@material-ui/core'; +import { IconButton } from '@material-ui/core'; import { Header, Page, @@ -38,29 +38,17 @@ export const StackStormHome = () => ( - - - - - + - - - - - + - - - - - + From 5b85cc1595ddf6ba4dcd9e60d21f6f5569d61fc7 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 10:03:18 +0000 Subject: [PATCH 205/417] fix: update case of StackStrom to Stackstorm or stackstorm where necessary Signed-off-by: pamelin --- plugins/stackstorm/src/api/StackStormClient.test.ts | 8 ++++---- plugins/stackstorm/src/api/StackStormClient.ts | 4 ++-- plugins/stackstorm/src/api/index.ts | 6 +++--- plugins/stackstorm/src/api/types.ts | 4 ++-- .../src/components/ActionsList/ActionsList.test.tsx | 8 ++++---- .../src/components/ActionsList/ActionsList.tsx | 6 +++--- .../ExecutionsTable/ExecutionPanel.test.tsx | 6 +++--- .../components/ExecutionsTable/ExecutionPanel.tsx | 4 ++-- .../ExecutionsTable/ExecutionsTable.test.tsx | 6 +++--- .../components/ExecutionsTable/ExecutionsTable.tsx | 4 ++-- .../src/components/PacksTable/PacksTable.test.tsx | 6 +++--- .../src/components/PacksTable/PacksTable.tsx | 4 ++-- .../StackStormHome/StackStormHome.test.tsx | 12 ++++++------ .../src/components/StackStormHome/StackStormHome.tsx | 2 +- .../src/components/StackStormHome/index.ts | 2 +- plugins/stackstorm/src/plugin.ts | 9 ++++----- 16 files changed, 45 insertions(+), 46 deletions(-) diff --git a/plugins/stackstorm/src/api/StackStormClient.test.ts b/plugins/stackstorm/src/api/StackStormClient.test.ts index 24400e3174..4a3e4cb79b 100644 --- a/plugins/stackstorm/src/api/StackStormClient.test.ts +++ b/plugins/stackstorm/src/api/StackStormClient.test.ts @@ -17,7 +17,7 @@ import { UrlPatternDiscovery } from '@backstage/core-app-api'; import { setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { StackStormClient } from './StackStormClient'; +import { StackstormClient } from './StackstormClient'; import { Action, Execution, Pack } from './types'; const server = setupServer(); @@ -148,12 +148,12 @@ const identityApiMock = () => ({ getCredentials: jest.fn().mockResolvedValue({ token: undefined }), }); -describe('StackStormClient', () => { +describe('StackstormClient', () => { setupRequestMockHandlers(server); const mockBaseUrl = 'http://backstage:9191/api/proxy'; const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); - let client: StackStormClient; + let client: StackstormClient; const setupHandlers = () => { server.use( @@ -184,7 +184,7 @@ describe('StackStormClient', () => { beforeEach(() => { setupHandlers(); - client = new StackStormClient({ + client = new StackstormClient({ discoveryApi: discoveryApi, identityApi: identityApiMock(), }); diff --git a/plugins/stackstorm/src/api/StackStormClient.ts b/plugins/stackstorm/src/api/StackStormClient.ts index c93901ce43..5fa862dc5a 100644 --- a/plugins/stackstorm/src/api/StackStormClient.ts +++ b/plugins/stackstorm/src/api/StackStormClient.ts @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Action, Execution, Pack, StackStormApi } from './types'; +import { Action, Execution, Pack, StackstormApi } from './types'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; -export class StackStormClient implements StackStormApi { +export class StackstormClient implements StackstormApi { private readonly discoveryApi: DiscoveryApi; private readonly identityApi: IdentityApi; diff --git a/plugins/stackstorm/src/api/index.ts b/plugins/stackstorm/src/api/index.ts index 2291fb1f73..0ce652e27b 100644 --- a/plugins/stackstorm/src/api/index.ts +++ b/plugins/stackstorm/src/api/index.ts @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { stackStormApiRef } from './types'; +export { stackstormApiRef } from './types'; export type { Action, Execution, ExecutionLog, Pack, - StackStormApi, + StackstormApi, } from './types'; -export { StackStormClient } from './StackStormClient'; +export { StackstormClient } from './StackstormClient'; diff --git a/plugins/stackstorm/src/api/types.ts b/plugins/stackstorm/src/api/types.ts index 13c92fb055..401f79c9b6 100644 --- a/plugins/stackstorm/src/api/types.ts +++ b/plugins/stackstorm/src/api/types.ts @@ -15,7 +15,7 @@ */ import { createApiRef } from '@backstage/core-plugin-api'; -export const stackStormApiRef = createApiRef({ +export const stackstormApiRef = createApiRef({ id: 'plugin.stackstorm.service', }); @@ -51,7 +51,7 @@ export type Pack = { version: string; }; -export interface StackStormApi { +export interface StackstormApi { getExecutions(limit: number, offset: number): Promise; getExecution(id: string): Promise; getPacks(): Promise; diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx index b59d2f4132..5876860c54 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx @@ -15,7 +15,7 @@ */ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; -import { Action, Pack, StackStormApi, stackStormApiRef } from '../../api'; +import { Action, Pack, StackstormApi, stackstormApiRef } from '../../api'; import { ActionsList, PackListItem } from './ActionsList'; const packs: Pack[] = [ @@ -53,14 +53,14 @@ const actions: Action[] = [ ]; describe('ActionsList', () => { - const mockApi: jest.Mocked = { + const mockApi: jest.Mocked = { getPacks: jest.fn().mockResolvedValue(packs), getActions: jest.fn().mockResolvedValue(actions), } as any; it('should render all packs', async () => { const { getByText } = await renderInTestApp( - + , ); @@ -73,7 +73,7 @@ describe('ActionsList', () => { it('should render all pack actions', async () => { const { getByText } = await renderInTestApp( - + {}} /> , ); diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx index 47e328716f..e792a4f6d2 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx @@ -29,7 +29,7 @@ import { makeStyles } from '@material-ui/core/styles'; import ExpandMore from '@material-ui/icons/ExpandMore'; import ExpandLess from '@material-ui/icons/ExpandLess'; import { Alert } from '@material-ui/lab'; -import { Action, Pack, stackStormApiRef } from '../../api'; +import { Action, Pack, stackstormApiRef } from '../../api'; const useStyles = makeStyles(theme => ({ root: { @@ -54,7 +54,7 @@ type ActionItemsProps = { export const ActionItems = ({ pack }: ActionItemsProps) => { const classes = useStyles(); - const st2 = useApi(stackStormApiRef); + const st2 = useApi(stackstormApiRef); const config = useApi(configApiRef); const { value, loading, error } = useAsync(async (): Promise => { @@ -120,7 +120,7 @@ export const PackListItem = ({ pack, opened, onClick }: PackListItemProps) => { }; export const ActionsList = () => { - const st2 = useApi(stackStormApiRef); + const st2 = useApi(stackstormApiRef); const classes = useStyles(); const [expanded, setExpanded] = useState([]); diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx index 51adbe0371..442151ebc1 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, } from '@backstage/test-utils'; import React from 'react'; -import { Execution, StackStormApi, stackStormApiRef } from '../../api'; +import { Execution, StackstormApi, stackstormApiRef } from '../../api'; import { ExecutionPanel } from './ExecutionPanel'; const execution: Execution = { @@ -52,7 +52,7 @@ const execution: Execution = { }; describe('ExecutionPanel', () => { - const mockApi: jest.Mocked = { + const mockApi: jest.Mocked = { getExecution: jest.fn().mockResolvedValue(execution), } as any; @@ -60,7 +60,7 @@ describe('ExecutionPanel', () => { const { getByText } = await renderInTestApp( { }; export const ExecutionPanel = ({ id }: { id: string }) => { - const st2 = useApi(stackStormApiRef); + const st2 = useApi(stackstormApiRef); const { value, loading, error } = useAsync(async (): Promise => { const data = await st2.getExecution(id); diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx index dc2bfa4db8..b53d3a2f5f 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, } from '@backstage/test-utils'; import React from 'react'; -import { Execution, StackStormApi, stackStormApiRef } from '../../api'; +import { Execution, StackstormApi, stackstormApiRef } from '../../api'; import { ExecutionsTable } from './ExecutionsTable'; const executions: Execution[] = [ @@ -81,7 +81,7 @@ const executions: Execution[] = [ ]; describe('ExecutionsTable', () => { - const mockApi: jest.Mocked = { + const mockApi: jest.Mocked = { getExecutions: jest.fn().mockResolvedValue(executions), } as any; @@ -89,7 +89,7 @@ describe('ExecutionsTable', () => { const { getByText } = await renderInTestApp( { - const st2 = useApi(stackStormApiRef); + const st2 = useApi(stackstormApiRef); const errorApi = useApi(errorApiRef); const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(10); diff --git a/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx b/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx index b45d460068..9de17e2f14 100644 --- a/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx +++ b/plugins/stackstorm/src/components/PacksTable/PacksTable.test.tsx @@ -15,7 +15,7 @@ */ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; -import { Pack, StackStormApi, stackStormApiRef } from '../../api'; +import { Pack, StackstormApi, stackstormApiRef } from '../../api'; import { PacksTable } from './PacksTable'; const packs: Pack[] = [ @@ -32,13 +32,13 @@ const packs: Pack[] = [ ]; describe('PacksTable', () => { - const mockApi: jest.Mocked = { + const mockApi: jest.Mocked = { getPacks: jest.fn().mockResolvedValue(packs), } as any; it('should render all packs', async () => { const { getByText } = await renderInTestApp( - + , ); diff --git a/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx index b150aeec4d..ebb5e8a14e 100644 --- a/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx +++ b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx @@ -18,7 +18,7 @@ import { Progress, Table, TableColumn } from '@backstage/core-components'; import { Alert } from '@material-ui/lab'; import useAsync from 'react-use/lib/useAsync'; import { useApi } from '@backstage/core-plugin-api'; -import { Pack, stackStormApiRef } from '../../api'; +import { Pack, stackstormApiRef } from '../../api'; type DenseTableProps = { packs: Pack[]; @@ -42,7 +42,7 @@ export const DenseTable = ({ packs }: DenseTableProps) => { }; export const PacksTable = () => { - const st2 = useApi(stackStormApiRef); + const st2 = useApi(stackstormApiRef); const { value, loading, error } = useAsync(async (): Promise => { const data = await st2.getPacks(); diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx index 6249fa71e8..897cec61c1 100644 --- a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx +++ b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ import React from 'react'; -import { StackStormHome } from './StackStormHome'; +import { StackstormHome } from './StackstormHome'; import { screen } from '@testing-library/react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { StackStormApi, stackStormApiRef } from '../../api'; +import { StackstormApi, stackstormApiRef } from '../../api'; -describe('StackStormHome', () => { - const mockApi: jest.Mocked = { +describe('StackstormHome', () => { + const mockApi: jest.Mocked = { getExecutions: jest.fn().mockResolvedValue([]), getExecution: jest.fn().mockResolvedValue({}), getPacks: jest.fn().mockResolvedValue([]), @@ -29,8 +29,8 @@ describe('StackStormHome', () => { it('should render', async () => { await renderInTestApp( - - + + , ); expect(screen.getByText('Welcome to StackStorm!')).toBeInTheDocument(); diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx index d3065ff2e5..d96d45e82d 100644 --- a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx +++ b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx @@ -27,7 +27,7 @@ import { ExecutionsTable } from '../ExecutionsTable'; import { PacksTable } from '../PacksTable/PacksTable'; import { ActionsList } from '../ActionsList'; -export const StackStormHome = () => ( +export const StackstormHome = () => (

    diff --git a/plugins/stackstorm/src/components/StackStormHome/index.ts b/plugins/stackstorm/src/components/StackStormHome/index.ts index 27c6db48ab..2063d21f34 100644 --- a/plugins/stackstorm/src/components/StackStormHome/index.ts +++ b/plugins/stackstorm/src/components/StackStormHome/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { StackStormHome } from './StackStormHome'; +export { StackstormHome } from './StackstormHome'; diff --git a/plugins/stackstorm/src/plugin.ts b/plugins/stackstorm/src/plugin.ts index 74df4a0b66..6f36e4fc7f 100644 --- a/plugins/stackstorm/src/plugin.ts +++ b/plugins/stackstorm/src/plugin.ts @@ -21,8 +21,7 @@ import { discoveryApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { stackStormApiRef, StackStormClient } from './api'; - +import { stackstormApiRef, StackstormClient } from './api'; import { rootRouteRef } from './routes'; /** @@ -34,13 +33,13 @@ export const stackstormPlugin = createPlugin({ id: 'stackstorm', apis: [ createApiFactory({ - api: stackStormApiRef, + api: stackstormApiRef, deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef, }, factory: ({ discoveryApi, identityApi }) => - new StackStormClient({ + new StackstormClient({ discoveryApi, identityApi, }), @@ -60,7 +59,7 @@ export const StackstormPage = stackstormPlugin.provide( createRoutableExtension({ name: 'StackstormPage', component: () => - import('./components/StackStormHome').then(m => m.StackStormHome), + import('./components/StackstormHome').then(m => m.StackstormHome), mountPoint: rootRouteRef, }), ); From 83e83873912619b218452ef7260aed673e4d8752 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 10:25:29 +0000 Subject: [PATCH 206/417] fix: use FetchApi instead of IdentityApi Signed-off-by: pamelin --- .../src/api/StackStormClient.test.ts | 11 ++----- .../stackstorm/src/api/StackStormClient.ts | 32 +++++++++++++------ plugins/stackstorm/src/plugin.ts | 8 ++--- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/plugins/stackstorm/src/api/StackStormClient.test.ts b/plugins/stackstorm/src/api/StackStormClient.test.ts index 4a3e4cb79b..7166c8297b 100644 --- a/plugins/stackstorm/src/api/StackStormClient.test.ts +++ b/plugins/stackstorm/src/api/StackStormClient.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { UrlPatternDiscovery } from '@backstage/core-app-api'; -import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { StackstormClient } from './StackstormClient'; @@ -141,13 +141,6 @@ const actions: Action[] = [ }, ]; -const identityApiMock = () => ({ - signOut: jest.fn(), - getProfileInfo: jest.fn(), - getBackstageIdentity: jest.fn(), - getCredentials: jest.fn().mockResolvedValue({ token: undefined }), -}); - describe('StackstormClient', () => { setupRequestMockHandlers(server); @@ -186,7 +179,7 @@ describe('StackstormClient', () => { setupHandlers(); client = new StackstormClient({ discoveryApi: discoveryApi, - identityApi: identityApiMock(), + fetchApi: new MockFetchApi(), }); }); diff --git a/plugins/stackstorm/src/api/StackStormClient.ts b/plugins/stackstorm/src/api/StackStormClient.ts index 5fa862dc5a..7048ad1796 100644 --- a/plugins/stackstorm/src/api/StackStormClient.ts +++ b/plugins/stackstorm/src/api/StackStormClient.ts @@ -14,36 +14,48 @@ * limitations under the License. */ import { Action, Execution, Pack, StackstormApi } from './types'; -import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; +import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; export class StackstormClient implements StackstormApi { private readonly discoveryApi: DiscoveryApi; - private readonly identityApi: IdentityApi; + private readonly fetchApi: FetchApi; constructor({ discoveryApi, - identityApi, + fetchApi, }: { discoveryApi: DiscoveryApi; - identityApi: IdentityApi; + fetchApi: FetchApi; }) { this.discoveryApi = discoveryApi; - this.identityApi = identityApi; + this.fetchApi = fetchApi; } private async get(input: string): Promise { - const { token: idToken } = await this.identityApi.getCredentials(); const apiUrl = `${await this.discoveryApi.getBaseUrl('proxy')}/stackstorm`; - const response = await fetch(`${apiUrl}${input}`, { - method: 'GET', + const response = await this.fetchApi.fetch(`${apiUrl}${input}`, { headers: { 'Content-Type': 'application/json', - ...(idToken && { Authorization: `Bearer ${idToken}` }), }, }); if (!response.ok) throw new Error(`Unable to get data: ${response.status}`); - return await response.json(); + return (await response.json()) as T; + } + + async addProject(bazaarProject: any): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('bazaar'); + + return await this.fetchApi + .fetch(`${baseUrl}/projects`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(bazaarProject), + }) + .then(resp => resp.json()); } async getExecutions(limit?: number, offset?: number): Promise { diff --git a/plugins/stackstorm/src/plugin.ts b/plugins/stackstorm/src/plugin.ts index 6f36e4fc7f..8e903c69e8 100644 --- a/plugins/stackstorm/src/plugin.ts +++ b/plugins/stackstorm/src/plugin.ts @@ -19,7 +19,7 @@ import { createPlugin, createRoutableExtension, discoveryApiRef, - identityApiRef, + fetchApiRef, } from '@backstage/core-plugin-api'; import { stackstormApiRef, StackstormClient } from './api'; import { rootRouteRef } from './routes'; @@ -36,12 +36,12 @@ export const stackstormPlugin = createPlugin({ api: stackstormApiRef, deps: { discoveryApi: discoveryApiRef, - identityApi: identityApiRef, + fetchApi: fetchApiRef, }, - factory: ({ discoveryApi, identityApi }) => + factory: ({ discoveryApi, fetchApi }) => new StackstormClient({ discoveryApi, - identityApi, + fetchApi, }), }), ], From 9c53ca52eca9a87d658878c9ce7b07bf97f6ed79 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 11:47:09 +0000 Subject: [PATCH 207/417] fix: move webUrl construction into the st2 client Signed-off-by: pamelin --- plugins/stackstorm/config.d.ts | 4 +- .../src/api/StackStormClient.test.ts | 37 ++++++++++++++----- .../stackstorm/src/api/StackStormClient.ts | 30 ++++++++++++++- plugins/stackstorm/src/api/types.ts | 2 + .../components/ActionsList/ActionsList.tsx | 10 +---- .../ExecutionsTable/ExecutionPanel.test.tsx | 22 ++++------- .../ExecutionsTable/ExecutionPanel.tsx | 12 +++--- .../ExecutionsTable/ExecutionsTable.test.tsx | 15 +++----- .../ExecutionsTable/ExecutionsTable.tsx | 12 ++---- plugins/stackstorm/src/plugin.ts | 6 ++- 10 files changed, 89 insertions(+), 61 deletions(-) diff --git a/plugins/stackstorm/config.d.ts b/plugins/stackstorm/config.d.ts index 64276503fc..b85d682eb0 100644 --- a/plugins/stackstorm/config.d.ts +++ b/plugins/stackstorm/config.d.ts @@ -14,12 +14,12 @@ * limitations under the License. */ export interface Config { - stackstorm?: { + stackstorm: { /** * StackStorm Web UI url * Used in links to StackStorm web UI * @visibility frontend */ - webUrl?: string; + webUrl: string; }; } diff --git a/plugins/stackstorm/src/api/StackStormClient.test.ts b/plugins/stackstorm/src/api/StackStormClient.test.ts index 7166c8297b..9757bde2af 100644 --- a/plugins/stackstorm/src/api/StackStormClient.test.ts +++ b/plugins/stackstorm/src/api/StackStormClient.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { UrlPatternDiscovery } from '@backstage/core-app-api'; +import { ConfigReader, UrlPatternDiscovery } from '@backstage/core-app-api'; import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; @@ -177,31 +177,50 @@ describe('StackstormClient', () => { beforeEach(() => { setupHandlers(); - client = new StackstormClient({ - discoveryApi: discoveryApi, - fetchApi: new MockFetchApi(), - }); + client = StackstormClient.fromConfig( + new ConfigReader({ + stackstorm: { + webUrl: 'http://stackstorm.example.com:8080', + }, + }), + { + discoveryApi: discoveryApi, + fetchApi: new MockFetchApi(), + }, + ); }); - it('get executions should return executions with emulated pagination', async () => { + it('getExecutions should return executions with emulated pagination', async () => { const got = await client.getExecutions(2, 1); expect(got.length).toEqual(2); expect(got).toMatchObject(executions.slice(1, 3)); }); - it('get execution should return one execution', async () => { + it('getExecution should return one execution', async () => { const got = await client.getExecution('63dcac3e18ba00e09e7bb3b6'); expect(got).toMatchObject(executionWithDetails); }); - it('get packs should return list of all packs', async () => { + it('getPacks should return list of all packs', async () => { const got = await client.getPacks(); expect(got.length).toEqual(packs.length); expect(got).toMatchObject(packs); }); - it('get actions should return list of actions', async () => { + it('getActions should return list of actions', async () => { const got = await client.getActions('core'); expect(got).toMatchObject(actions); }); + + it('getExecutionHistoryUrl should return webUrl for executions', async () => { + const got = client.getExecutionHistoryUrl('123abc'); + expect(got).toEqual('http://stackstorm.example.com:8080/?#/history/123abc'); + }); + + it('getActionUrl should return webUrl for action', async () => { + const got = client.getActionUrl('core.shell'); + expect(got).toEqual( + 'http://stackstorm.example.com:8080/?#/actions/core.shell', + ); + }); }); diff --git a/plugins/stackstorm/src/api/StackStormClient.ts b/plugins/stackstorm/src/api/StackStormClient.ts index 7048ad1796..692bfbe4a6 100644 --- a/plugins/stackstorm/src/api/StackStormClient.ts +++ b/plugins/stackstorm/src/api/StackStormClient.ts @@ -14,21 +14,39 @@ * limitations under the License. */ import { Action, Execution, Pack, StackstormApi } from './types'; -import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; +import { ConfigApi, DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; export class StackstormClient implements StackstormApi { private readonly discoveryApi: DiscoveryApi; private readonly fetchApi: FetchApi; + private readonly webUrl: string; - constructor({ + private constructor({ discoveryApi, fetchApi, + webUrl, }: { discoveryApi: DiscoveryApi; fetchApi: FetchApi; + webUrl: string; }) { this.discoveryApi = discoveryApi; this.fetchApi = fetchApi; + this.webUrl = webUrl; + } + + static fromConfig( + config: ConfigApi, + dependencies: { + discoveryApi: DiscoveryApi; + fetchApi: FetchApi; + }, + ): StackstormClient { + return new StackstormClient({ + discoveryApi: dependencies.discoveryApi, + fetchApi: dependencies.fetchApi, + webUrl: config.getString('stackstorm.webUrl'), + }); } private async get(input: string): Promise { @@ -87,4 +105,12 @@ export class StackstormClient implements StackstormApi { const path = `/actions?${new URLSearchParams(params)}`; return this.get(path); } + + getExecutionHistoryUrl(id: string): string { + return `${this.webUrl}/?#/history/${id}`; + } + + getActionUrl(ref: string): string { + return `${this.webUrl}/?#/actions/${ref}`; + } } diff --git a/plugins/stackstorm/src/api/types.ts b/plugins/stackstorm/src/api/types.ts index 401f79c9b6..6ebf3d67a6 100644 --- a/plugins/stackstorm/src/api/types.ts +++ b/plugins/stackstorm/src/api/types.ts @@ -56,4 +56,6 @@ export interface StackstormApi { getExecution(id: string): Promise; getPacks(): Promise; getActions(pack: string): Promise; + getExecutionHistoryUrl(id: string): string; + getActionUrl(ref: string): string; } diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx index e792a4f6d2..96262d7e6b 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx @@ -16,7 +16,7 @@ import React, { useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { Progress } from '@backstage/core-components'; -import { useApi, configApiRef } from '@backstage/core-plugin-api'; +import { useApi } from '@backstage/core-plugin-api'; import { List, ListItemText, @@ -55,7 +55,6 @@ type ActionItemsProps = { export const ActionItems = ({ pack }: ActionItemsProps) => { const classes = useStyles(); const st2 = useApi(stackstormApiRef); - const config = useApi(configApiRef); const { value, loading, error } = useAsync(async (): Promise => { const data = await st2.getActions(pack.ref); @@ -76,12 +75,7 @@ export const ActionItems = ({ pack }: ActionItemsProps) => { key={a.ref} button className={classes.nested} - onClick={() => - window.open( - `${config.getString('stackstorm.webUrl')}/?#/actions/${a.ref}`, - '_blank', - ) - } + onClick={() => window.open(st2.getActionUrl(a.ref), '_blank')} > {a.runner_type} diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx index 442151ebc1..53930d339f 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.test.tsx @@ -13,12 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { configApiRef } from '@backstage/core-plugin-api'; -import { - MockConfigApi, - renderInTestApp, - TestApiProvider, -} from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { Execution, StackstormApi, stackstormApiRef } from '../../api'; import { ExecutionPanel } from './ExecutionPanel'; @@ -54,19 +49,16 @@ const execution: Execution = { describe('ExecutionPanel', () => { const mockApi: jest.Mocked = { getExecution: jest.fn().mockResolvedValue(execution), + getExecutionHistoryUrl: jest + .fn() + .mockResolvedValue( + 'http://stackstorm.example.com:8080/?#/history/63dcac3e18ba00e09e7bb3b6', + ), } as any; it('should render execution details', async () => { const { getByText } = await renderInTestApp( - + , ); diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx index 78b0f0dd5a..47f301e910 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import { CodeSnippet, Progress } from '@backstage/core-components'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { useApi } from '@backstage/core-plugin-api'; import { Execution, stackstormApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { Alert } from '@material-ui/lab'; @@ -65,11 +65,9 @@ const TRow = withStyles(theme => ({ }))(TableRow); const ExecutionCard = ({ e }: { e: Execution }) => { - const config = useApi(configApiRef); + const st2 = useApi(stackstormApiRef); const classes = useStyles(); - const webUrl = `${config.getString('stackstorm.webUrl')}/?#/history/${e.id}`; - return ( @@ -139,7 +137,11 @@ const ExecutionCard = ({ e }: { e: Execution }) => { /> - diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx index b53d3a2f5f..1890bfa10b 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx @@ -83,19 +83,16 @@ const executions: Execution[] = [ describe('ExecutionsTable', () => { const mockApi: jest.Mocked = { getExecutions: jest.fn().mockResolvedValue(executions), + getExecutionHistoryUrl: jest + .fn() + .mockResolvedValue( + 'http://stackstorm.example.com:8080/?#/history/123abc', + ), } as any; it('should render all executions', async () => { const { getByText } = await renderInTestApp( - + , ); diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx index 289c896678..1816f1db1f 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx @@ -15,7 +15,7 @@ */ import React, { useEffect, useState } from 'react'; import { Link, Table, TableColumn } from '@backstage/core-components'; -import { useApi, configApiRef, errorApiRef } from '@backstage/core-plugin-api'; +import { useApi, errorApiRef } from '@backstage/core-plugin-api'; import { Execution, stackstormApiRef } from '../../api'; import { Status } from './Status'; import { ExecutionPanel } from './ExecutionPanel'; @@ -37,7 +37,7 @@ export const DenseTable = ({ onPageChange, onRowsPerPageChange, }: DenseTableProps) => { - const config = useApi(configApiRef); + const st2 = useApi(stackstormApiRef); const columns: TableColumn[] = [ { @@ -54,13 +54,7 @@ export const DenseTable = ({ { title: 'Execution ID', field: 'id', - render: e => ( - - {e.id} - - ), + render: e => {e.id}, }, ]; diff --git a/plugins/stackstorm/src/plugin.ts b/plugins/stackstorm/src/plugin.ts index 8e903c69e8..be4b9c065c 100644 --- a/plugins/stackstorm/src/plugin.ts +++ b/plugins/stackstorm/src/plugin.ts @@ -15,6 +15,7 @@ */ import { + configApiRef, createApiFactory, createPlugin, createRoutableExtension, @@ -35,11 +36,12 @@ export const stackstormPlugin = createPlugin({ createApiFactory({ api: stackstormApiRef, deps: { + configApi: configApiRef, discoveryApi: discoveryApiRef, fetchApi: fetchApiRef, }, - factory: ({ discoveryApi, fetchApi }) => - new StackstormClient({ + factory: ({ configApi, discoveryApi, fetchApi }) => + StackstormClient.fromConfig(configApi, { discoveryApi, fetchApi, }), From fe16d3e1aa68956e145689571410c69773230ed9 Mon Sep 17 00:00:00 2001 From: Morgan Bentell Date: Thu, 16 Feb 2023 13:19:42 +0100 Subject: [PATCH 208/417] Update CONTRIBUTING.md Clarify how semantic versioning should be used. The emphasis was on `0.x` versions, but nowadays most packages are above `1.0` so hopefully this will be less confusing. Signed-off-by: Morgan Bentell --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f3de7bf0e5..e22fbf29a4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -136,7 +136,7 @@ Changesets **are** needed for new packages, as that is what triggers the package 1. Run `yarn changeset` 2. Select which packages you want to include a changeset for -3. Select impact of change that you're introducing, using `minor` for breaking changes and `patch` otherwise. We do not use `major` changes while packages are at version `0.x`. +3. Select impact of the change you're introducing. If the package you are changing is at version `0.x`, use `minor` for breaking changes and `patch` otherwise. If the package is at `1.0.0` or higher, use `major` for breaking changes, `minor` for backwards compatible API changes, and `patch` otherwise. See the [Semantic Versioning specification](https://semver.org/#semantic-versioning-specification-semver) for more details. 4. Explain your changes in the generated changeset. See [examples of well written changesets](https://backstage.io/docs/getting-started/contributors#writing-changesets). 5. Add generated changeset to Git 6. Push the commit with your changeset to the branch associated with your PR From b69c41bfaf9f46555f6f0e350c6e692be96be6ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 16 Feb 2023 14:57:19 +0100 Subject: [PATCH 209/417] fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../tasks/PluginTaskSchedulerJanitor.test.ts | 22 +++++++++++-------- .../src/tasks/PluginTaskSchedulerJanitor.ts | 10 +++++---- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts index f981bf59fe..5b5d592b7b 100644 --- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.test.ts @@ -37,17 +37,22 @@ const getTask = async (knex: Knex): Promise => { describe('PluginTaskSchedulerJanitor', () => { const logger = getVoidLogger(); const databases = TestDatabases.create({ - ids: ['MYSQL_8', 'POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], + ids: [ + /* 'MYSQL_8' not supported yet */ + 'POSTGRES_13', + 'POSTGRES_9', + 'SQLITE_3', + ], }); - jest.setTimeout(300_000); + jest.setTimeout(60_000); beforeEach(() => { jest.resetAllMocks(); }); it.each(databases.eachSupportedId())( - 'Should update date if current_run_expires_at expires , %p', + 'Should update date if current_run_expires_at expires, %p', async databaseId => { const knex = await databases.init(databaseId); await migrateBackendTasks(knex); @@ -66,19 +71,16 @@ describe('PluginTaskSchedulerJanitor', () => { }); const worker = new PluginTaskSchedulerJanitor({ + waitBetweenRuns: Duration.fromObject({ milliseconds: 20 }), knex, - waitBetweenRuns: Duration.fromObject({ minutes: 1 }), logger, }); const abortController = new AbortController(); - - await worker.start(abortController.signal); - - const row1 = await getTask(knex); + worker.start(abortController.signal); await waitForExpect(async () => { - expect(row1).toEqual( + await expect(getTask(knex)).resolves.toEqual( expect.objectContaining({ id: 'task1', current_run_ticket: null, @@ -87,6 +89,8 @@ describe('PluginTaskSchedulerJanitor', () => { }), ); }); + + abortController.abort(); }, ); }); diff --git a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts index 0d8ea79d13..f69b7d9b88 100644 --- a/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts +++ b/packages/backend-tasks/src/tasks/PluginTaskSchedulerJanitor.ts @@ -53,16 +53,18 @@ export class PluginTaskSchedulerJanitor { private async runOnce() { const dbNull = this.knex.raw('null'); - let tasks: Array<{ id: string }>; const configClient = this.knex.client.config.client; + let tasks: Array<{ id: string }>; if (configClient.includes('sqlite3') || configClient.includes('mysql')) { - const now = await this.knex.select(this.knex.fn.now()); tasks = await this.knex(DB_TASKS_TABLE) .select('id') - .where('current_run_expires_at', '<', now); + .where('current_run_expires_at', '<', this.knex.fn.now()); await this.knex(DB_TASKS_TABLE) - .where('current_run_expires_at', '<', now) + .whereIn( + 'id', + tasks.map(t => t.id), + ) .update({ current_run_ticket: dbNull, current_run_started_at: dbNull, From 443de29d7f10b42df07db0e326363ea83f9d49c1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 14:09:45 +0000 Subject: [PATCH 210/417] chore(deps): update dependency @types/tar to v6.1.4 Signed-off-by: Renovate Bot --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 14256cbc29..fc7605bdf1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15542,12 +15542,12 @@ __metadata: linkType: hard "@types/tar@npm:^6.1.1": - version: 6.1.3 - resolution: "@types/tar@npm:6.1.3" + version: 6.1.4 + resolution: "@types/tar@npm:6.1.4" dependencies: "@types/node": "*" - minipass: ^3.3.5 - checksum: 3a221f74adfcef8555b9c4cc951907dfd567630744ffe5211da1b44caf2a4c3b02297b73c9fb02d171e93a7a7c74fb15c1826e3f0438f0e5e8f4c790db59ddcf + minipass: ^4.0.0 + checksum: 48a1f6b8665ed03f37f74966cfe991a33d6e85cee28aaa6ef42c7ca8448cdbc1e2ca96b473b6b53f1d7bd91423ae0dcfe54a295607d7ac4b4cbb9dbf167df7fa languageName: node linkType: hard @@ -29574,7 +29574,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^3.0.0, minipass@npm:^3.1.0, minipass@npm:^3.1.1, minipass@npm:^3.1.3, minipass@npm:^3.1.6, minipass@npm:^3.3.5": +"minipass@npm:^3.0.0, minipass@npm:^3.1.0, minipass@npm:^3.1.1, minipass@npm:^3.1.3, minipass@npm:^3.1.6": version: 3.3.5 resolution: "minipass@npm:3.3.5" dependencies: From 177aef100789eb232301a2a1f435cfc5c24fd3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 16 Feb 2023 15:43:03 +0100 Subject: [PATCH 211/417] remove triple-beam again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- packages/backend-common/package.json | 1 - yarn.lock | 8 -------- 2 files changed, 9 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index ad7b24a9df..d356d67fab 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -114,7 +114,6 @@ "@types/stoppable": "^1.1.0", "@types/supertest": "^2.0.8", "@types/tar": "^6.1.1", - "@types/triple-beam": "^1.3.2", "@types/webpack-env": "^1.15.2", "@types/yauzl": "^2.10.0", "aws-sdk-mock": "^5.2.1", diff --git a/yarn.lock b/yarn.lock index b6791bf778..fc7605bdf1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3457,7 +3457,6 @@ __metadata: "@types/stoppable": ^1.1.0 "@types/supertest": ^2.0.8 "@types/tar": ^6.1.1 - "@types/triple-beam": ^1.3.2 "@types/webpack-env": ^1.15.2 "@types/yauzl": ^2.10.0 archiver: ^5.0.2 @@ -15595,13 +15594,6 @@ __metadata: languageName: node linkType: hard -"@types/triple-beam@npm:^1.3.2": - version: 1.3.2 - resolution: "@types/triple-beam@npm:1.3.2" - checksum: dd7b4a563fb710abc992e5d59eac481bed9e303fada2e276e37b00be31c392e03300ee468e57761e616512872e77935f92472877d0704a19688d15a726cee17b - languageName: node - linkType: hard - "@types/trusted-types@npm:*": version: 2.0.2 resolution: "@types/trusted-types@npm:2.0.2" From ea4e4bbf0ef08b8dd6811c57849b9350b4bd5d6a Mon Sep 17 00:00:00 2001 From: Scott Edwards Date: Thu, 16 Feb 2023 14:44:23 +0000 Subject: [PATCH 212/417] Add Cazoo to Adopters Signed-off-by: Scott Edwards --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 4329a00664..38e67adfee 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -230,4 +230,4 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [XP Inc.](https://www.linkedin.com/company/xpinc/) | [Gabriel Santos](https://www.linkedin.com/in/gabriel-santos-6bb740a/) | Developer Portal Catalog (components, APIs, resources, users, groups) and organization relations. | [OVO Energy](https://www.ovoenergy.com/) | [Michael Wizner](https://github.com/mwz), [Dan Laird](https://github.com/dlaird-ovo), [Samantha Betts](https://github.com/sammbetts) | Developer Experience Tool with an aim to to improve processes, boost productivity, finding of information/docs and building tech engagement throughout the business. | [MusicTribe](https://careers.musictribe.com/) | [Alex Ford](mailto:alex.j.ford@gmail.com), [Tiago Barbosa](https://github.com/t1agob) | We are starting to use Backstage as a developer portal to share API specifications and documentation, to quickly onboard new projects with the software templates, and to help developers discover software through the catalog. - +| [Cazoo](https://www.cazoo.co.uk/) | [Abz Mungul](https://www.linkedin.com/in/abzmungul/), [Scott Edwards](https://www.linkedin.com/in/scott-edwards-tech/) | We're assessing Backstage as our developer platform at Cazoo with a focus on reducing cognitive load for our engineers. We're currently aiming for 3 outcomes: creating visibility into service ownership across teams, improving the discoverability of event schemas and relationships, and improving the discoverability of technical documentation and best practices. | From d1137b0e9037646762c16449446f0a0d1d767b63 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 16 Feb 2023 15:51:06 +0100 Subject: [PATCH 213/417] chore: enter pre-release Signed-off-by: blam --- .changeset/pre.json | 214 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 .changeset/pre.json diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 0000000000..fa7ab06d08 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,214 @@ +{ + "mode": "pre", + "tag": "next", + "initialVersions": { + "example-app": "0.2.80", + "@backstage/app-defaults": "1.2.0", + "example-backend": "0.2.80", + "@backstage/backend-app-api": "0.4.0", + "@backstage/backend-common": "0.18.2", + "@backstage/backend-defaults": "0.1.7", + "@backstage/backend-dev-utils": "0.1.0", + "example-backend-next": "0.0.8", + "@backstage/backend-plugin-api": "0.4.0", + "@backstage/backend-tasks": "0.4.3", + "@backstage/backend-test-utils": "0.1.34", + "@backstage/catalog-client": "1.3.1", + "@backstage/catalog-model": "1.2.0", + "@backstage/cli": "0.22.2", + "@backstage/cli-common": "0.1.11", + "@backstage/codemods": "0.1.43", + "@backstage/config": "1.0.6", + "@backstage/config-loader": "1.1.8", + "@backstage/core-app-api": "1.5.0", + "@backstage/core-components": "0.12.4", + "@backstage/core-plugin-api": "1.4.0", + "@backstage/create-app": "0.4.37", + "@backstage/dev-utils": "1.0.12", + "e2e-test": "0.2.0", + "@backstage/errors": "1.1.4", + "@backstage/eslint-plugin": "0.1.0", + "@backstage/integration": "1.4.2", + "@backstage/integration-aws-node": "0.1.1", + "@backstage/integration-react": "1.1.10", + "@backstage/release-manifests": "0.0.8", + "@backstage/repo-tools": "0.1.2", + "@techdocs/cli": "1.3.2", + "techdocs-cli-embedded-app": "0.2.79", + "@backstage/test-utils": "1.2.5", + "@backstage/theme": "0.2.17", + "@backstage/types": "1.0.2", + "@backstage/version-bridge": "1.0.3", + "@backstage/plugin-adr": "0.4.0", + "@backstage/plugin-adr-backend": "0.3.0", + "@backstage/plugin-adr-common": "0.2.6", + "@backstage/plugin-airbrake": "0.3.15", + "@backstage/plugin-airbrake-backend": "0.2.15", + "@backstage/plugin-allure": "0.1.31", + "@backstage/plugin-analytics-module-ga": "0.1.26", + "@backstage/plugin-apache-airflow": "0.2.8", + "@backstage/plugin-api-docs": "0.9.0", + "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.1", + "@backstage/plugin-apollo-explorer": "0.1.8", + "@backstage/plugin-app-backend": "0.3.42", + "@backstage/plugin-auth-backend": "0.18.0", + "@backstage/plugin-auth-node": "0.2.11", + "@backstage/plugin-azure-devops": "0.2.6", + "@backstage/plugin-azure-devops-backend": "0.3.21", + "@backstage/plugin-azure-devops-common": "0.3.0", + "@backstage/plugin-azure-sites": "0.1.4", + "@backstage/plugin-azure-sites-backend": "0.1.4", + "@backstage/plugin-azure-sites-common": "0.1.0", + "@backstage/plugin-badges": "0.2.39", + "@backstage/plugin-badges-backend": "0.1.36", + "@backstage/plugin-bazaar": "0.2.4", + "@backstage/plugin-bazaar-backend": "0.2.5", + "@backstage/plugin-bitbucket-cloud-common": "0.2.3", + "@backstage/plugin-bitrise": "0.1.42", + "@backstage/plugin-catalog": "1.8.0", + "@backstage/plugin-catalog-backend": "1.7.2", + "@backstage/plugin-catalog-backend-module-aws": "0.1.15", + "@backstage/plugin-catalog-backend-module-azure": "0.1.13", + "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.9", + "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.9", + "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.7", + "@backstage/plugin-catalog-backend-module-gerrit": "0.1.10", + "@backstage/plugin-catalog-backend-module-github": "0.2.5", + "@backstage/plugin-catalog-backend-module-gitlab": "0.1.13", + "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.2.0", + "@backstage/plugin-catalog-backend-module-ldap": "0.5.9", + "@backstage/plugin-catalog-backend-module-msgraph": "0.5.0", + "@backstage/plugin-catalog-backend-module-openapi": "0.1.8", + "@backstage/plugin-catalog-common": "1.0.11", + "@internal/plugin-catalog-customized": "0.0.7", + "@backstage/plugin-catalog-graph": "0.2.27", + "@backstage/plugin-catalog-graphql": "0.3.18", + "@backstage/plugin-catalog-import": "0.9.5", + "@backstage/plugin-catalog-node": "1.3.3", + "@backstage/plugin-catalog-react": "1.3.0", + "@backstage/plugin-cicd-statistics": "0.1.17", + "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.11", + "@backstage/plugin-circleci": "0.3.15", + "@backstage/plugin-cloudbuild": "0.3.15", + "@backstage/plugin-code-climate": "0.1.15", + "@backstage/plugin-code-coverage": "0.2.8", + "@backstage/plugin-code-coverage-backend": "0.2.8", + "@backstage/plugin-codescene": "0.1.10", + "@backstage/plugin-config-schema": "0.1.38", + "@backstage/plugin-cost-insights": "0.12.4", + "@backstage/plugin-cost-insights-common": "0.1.1", + "@backstage/plugin-dynatrace": "2.0.0", + "@backstage/plugin-entity-feedback": "0.1.0", + "@backstage/plugin-entity-feedback-backend": "0.1.0", + "@backstage/plugin-entity-feedback-common": "0.1.0", + "@backstage/plugin-entity-validation": "0.1.0", + "@backstage/plugin-events-backend": "0.2.3", + "@backstage/plugin-events-backend-module-aws-sqs": "0.1.4", + "@backstage/plugin-events-backend-module-azure": "0.1.4", + "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.4", + "@backstage/plugin-events-backend-module-gerrit": "0.1.4", + "@backstage/plugin-events-backend-module-github": "0.1.4", + "@backstage/plugin-events-backend-module-gitlab": "0.1.4", + "@backstage/plugin-events-backend-test-utils": "0.1.4", + "@backstage/plugin-events-node": "0.2.3", + "@internal/plugin-todo-list": "1.0.10", + "@internal/plugin-todo-list-backend": "1.0.10", + "@internal/plugin-todo-list-common": "1.0.8", + "@backstage/plugin-explore": "0.4.0", + "@backstage/plugin-explore-backend": "0.0.4", + "@backstage/plugin-explore-common": "0.0.1", + "@backstage/plugin-explore-react": "0.0.26", + "@backstage/plugin-firehydrant": "0.1.32", + "@backstage/plugin-fossa": "0.2.47", + "@backstage/plugin-gcalendar": "0.3.11", + "@backstage/plugin-gcp-projects": "0.3.34", + "@backstage/plugin-git-release-manager": "0.3.28", + "@backstage/plugin-github-actions": "0.5.15", + "@backstage/plugin-github-deployments": "0.1.46", + "@backstage/plugin-github-issues": "0.2.4", + "@backstage/plugin-github-pull-requests-board": "0.1.9", + "@backstage/plugin-gitops-profiles": "0.3.33", + "@backstage/plugin-gocd": "0.1.21", + "@backstage/plugin-graphiql": "0.2.47", + "@backstage/plugin-graphql-backend": "0.1.32", + "@backstage/plugin-graphql-voyager": "0.1.0", + "@backstage/plugin-home": "0.4.31", + "@backstage/plugin-ilert": "0.2.4", + "@backstage/plugin-jenkins": "0.7.14", + "@backstage/plugin-jenkins-backend": "0.1.32", + "@backstage/plugin-jenkins-common": "0.1.13", + "@backstage/plugin-kafka": "0.3.15", + "@backstage/plugin-kafka-backend": "0.2.35", + "@backstage/plugin-kubernetes": "0.7.8", + "@backstage/plugin-kubernetes-backend": "0.9.3", + "@backstage/plugin-kubernetes-common": "0.6.0", + "@backstage/plugin-lighthouse": "0.4.0", + "@backstage/plugin-lighthouse-backend": "0.1.0", + "@backstage/plugin-lighthouse-common": "0.1.0", + "@backstage/plugin-linguist": "0.1.0", + "@backstage/plugin-linguist-backend": "0.1.0", + "@backstage/plugin-linguist-common": "0.1.0", + "@backstage/plugin-microsoft-calendar": "0.1.0", + "@backstage/plugin-newrelic": "0.3.33", + "@backstage/plugin-newrelic-dashboard": "0.2.8", + "@backstage/plugin-org": "0.6.5", + "@backstage/plugin-org-react": "0.1.4", + "@backstage/plugin-pagerduty": "0.5.8", + "@backstage/plugin-periskop": "0.1.13", + "@backstage/plugin-periskop-backend": "0.1.13", + "@backstage/plugin-permission-backend": "0.5.17", + "@backstage/plugin-permission-common": "0.7.3", + "@backstage/plugin-permission-node": "0.7.5", + "@backstage/plugin-permission-react": "0.4.10", + "@backstage/plugin-playlist": "0.1.6", + "@backstage/plugin-playlist-backend": "0.2.5", + "@backstage/plugin-playlist-common": "0.1.4", + "@backstage/plugin-proxy-backend": "0.2.36", + "@backstage/plugin-rollbar": "0.4.15", + "@backstage/plugin-rollbar-backend": "0.1.39", + "@backstage/plugin-scaffolder": "1.11.0", + "@backstage/plugin-scaffolder-backend": "1.11.0", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.17", + "@backstage/plugin-scaffolder-backend-module-rails": "0.4.10", + "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.2", + "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.15", + "@backstage/plugin-scaffolder-common": "1.2.5", + "@backstage/plugin-scaffolder-node": "0.1.0", + "@backstage/plugin-scaffolder-react": "1.1.0", + "@backstage/plugin-search": "1.1.0", + "@backstage/plugin-search-backend": "1.2.3", + "@backstage/plugin-search-backend-module-elasticsearch": "1.1.3", + "@backstage/plugin-search-backend-module-pg": "0.5.3", + "@backstage/plugin-search-backend-node": "1.1.3", + "@backstage/plugin-search-common": "1.2.1", + "@backstage/plugin-search-react": "1.5.0", + "@backstage/plugin-sentry": "0.5.0", + "@backstage/plugin-shortcuts": "0.3.7", + "@backstage/plugin-sonarqube": "0.6.3", + "@backstage/plugin-sonarqube-backend": "0.1.7", + "@backstage/plugin-sonarqube-react": "0.1.2", + "@backstage/plugin-splunk-on-call": "0.4.4", + "@backstage/plugin-stack-overflow": "0.1.11", + "@backstage/plugin-stack-overflow-backend": "0.1.11", + "@backstage/plugin-tech-insights": "0.3.7", + "@backstage/plugin-tech-insights-backend": "0.5.8", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.26", + "@backstage/plugin-tech-insights-common": "0.2.10", + "@backstage/plugin-tech-insights-node": "0.4.0", + "@backstage/plugin-tech-radar": "0.6.1", + "@backstage/plugin-techdocs": "1.5.0", + "@backstage/plugin-techdocs-addons-test-utils": "1.0.10", + "@backstage/plugin-techdocs-backend": "1.5.3", + "@backstage/plugin-techdocs-module-addons-contrib": "1.0.10", + "@backstage/plugin-techdocs-node": "1.5.0", + "@backstage/plugin-techdocs-react": "1.1.3", + "@backstage/plugin-todo": "0.2.17", + "@backstage/plugin-todo-backend": "0.1.39", + "@backstage/plugin-user-settings": "0.7.0", + "@backstage/plugin-user-settings-backend": "0.1.6", + "@backstage/plugin-vault": "0.1.9", + "@backstage/plugin-vault-backend": "0.2.8", + "@backstage/plugin-xcmetrics": "0.2.35" + }, + "changesets": [] +} From 8c57bb780f5227710cbd352698fa7cf210e3877b Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Thu, 16 Feb 2023 08:24:42 -0500 Subject: [PATCH 214/417] create changeset for exposing the todos-backend plugin using the new system Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- .changeset/new-waves-sing.md | 6 ++++++ plugins/todo-backend/src/service/router.test.ts | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .changeset/new-waves-sing.md diff --git a/.changeset/new-waves-sing.md b/.changeset/new-waves-sing.md new file mode 100644 index 0000000000..124a508bde --- /dev/null +++ b/.changeset/new-waves-sing.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-todo-backend': minor +'example-backend-next': patch +--- + +Expose the todos-backend plugin using the new system, add the new entrypoint for todos-backend into the experimental backend diff --git a/plugins/todo-backend/src/service/router.test.ts b/plugins/todo-backend/src/service/router.test.ts index 0254147681..f2d9f2c7a3 100644 --- a/plugins/todo-backend/src/service/router.test.ts +++ b/plugins/todo-backend/src/service/router.test.ts @@ -18,12 +18,12 @@ import express from 'express'; import request from 'supertest'; import { errorHandler } from '@backstage/backend-common'; +import { createRouter } from './router'; import { - createRouter, parseFilterParam, parseIntegerParam, parseOrderByParam, -} from './router'; +} from '../lib/utils'; import { TodoService } from './types'; const mockListBody = { From 2e2d64b891bf1added88f27d9ae49c617b17da96 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:10:56 +0000 Subject: [PATCH 215/417] chore(deps): update dependency eslint-plugin-testing-library to v5.10.2 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b6791bf778..4559666e5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22050,13 +22050,13 @@ __metadata: linkType: hard "eslint-plugin-testing-library@npm:^5.9.1": - version: 5.10.1 - resolution: "eslint-plugin-testing-library@npm:5.10.1" + version: 5.10.2 + resolution: "eslint-plugin-testing-library@npm:5.10.2" dependencies: "@typescript-eslint/utils": ^5.43.0 peerDependencies: eslint: ^7.5.0 || ^8.0.0 - checksum: fbc24ce8cbd03bee283ae520f023bd52f10d21fb25bd66c5a09a0e0ad17997bae559450438ce0b4fcc38b4e14b6802f18482c41d2bc72bf1a8e1a12a91766572 + checksum: 3b2b330e62f4a6dc438050006f0d0c97605f6861828b153271dc6d2fafb1e60f4e86fbaa8166c7afd452e3b6cad39413738fd4c8e2eb2def1915c678154676da languageName: node linkType: hard From 0d0629e85aaf5487836dd9e44813d08ef871abfa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 15:12:06 +0000 Subject: [PATCH 216/417] fix(deps): update dependency @roadiehq/backstage-plugin-buildkite to v2.1.4 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b6791bf778..901d7cf372 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12860,8 +12860,8 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-buildkite@npm:^2.0.8": - version: 2.1.3 - resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.3" + version: 2.1.4 + resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.4" dependencies: "@backstage/catalog-model": ^1.1.5 "@backstage/core-components": ^0.12.3 @@ -12879,7 +12879,7 @@ __metadata: react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: d7716bc6588863ae845630beac21b2a0ea8e2af4d01af1be432161007576c9c73419b2496ce868062e5af4ef9e3d02e9140eee8840c48223ded79c63d3efbb24 + checksum: 6f45a9d4fe5429f5052ecae7547e608fe4b4c6b43e5ed7d113e9648d37fbe40ced92f51f29ffe719517de101e7821e14fd7d03cc588860a90392de6fafb6e9f6 languageName: node linkType: hard From 581b1f8a3a2fa45857401bfa03e4d83898791650 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Thu, 16 Feb 2023 10:21:41 -0500 Subject: [PATCH 217/417] add api-report Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/todo-backend/api-report.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index 277c87fea9..3e3c4cb58c 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -3,10 +3,12 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import express from 'express'; +import { HttpRouterService } from '@backstage/backend-plugin-api'; import { Logger } from 'winston'; import { ScmIntegrations } from '@backstage/integration'; import { UrlReader } from '@backstage/backend-common'; @@ -144,4 +146,15 @@ export interface TodoService { }, ): Promise; } + +// @alpha (undocumented) +export const todosPlugin: () => BackendFeature; + +// Warning: (ae-missing-release-tag) "TodosPluginDependencies" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type TodosPluginDependencies = { + todoReader: TodoService; + http: HttpRouterService; +}; ``` From e87c967175ed3948e048191c7231c7be038e8e79 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:05:09 +0000 Subject: [PATCH 218/417] fix(deps): update dependency @roadiehq/backstage-plugin-github-insights to v2.3.4 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 550c230ba3..dc43dd077f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12883,8 +12883,8 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-github-insights@npm:^2.0.5": - version: 2.3.3 - resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.3" + version: 2.3.4 + resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.4" dependencies: "@backstage/catalog-model": ^1.1.5 "@backstage/core-components": ^0.12.3 @@ -12906,7 +12906,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 - checksum: e92b46ee34f8ae65a2cb796ae0d011a66e6dd5f731270b5925a314c706af471474316f2d489ef444c33747c3b5656e7ac74b8a39d6e4d777f5ccd3a992144f6a + checksum: 20a633dc9731ccab4f49a376d272c4b710107eacadd253bfaa3e00f9b0196632fd6fb03f651cc5e44cc99d6838ffc5b9d83c03764c0bd3926a0c8f7b3614aff7 languageName: node linkType: hard From 89209ca8daf0eec65fd14fc5c6d5c3366e3d926c Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 16:18:05 +0000 Subject: [PATCH 219/417] fix: refactor error handling to use ResponseErrorPanel Signed-off-by: pamelin --- plugins/stackstorm/package.json | 1 + .../stackstorm/src/api/StackStormClient.ts | 20 ++-------- .../components/ActionsList/ActionsList.tsx | 7 ++-- .../ExecutionsTable/ExecutionPanel.tsx | 9 +++-- .../ExecutionsTable/ExecutionsTable.tsx | 40 +++++++++---------- .../src/components/PacksTable/PacksTable.tsx | 10 +++-- yarn.lock | 1 + 7 files changed, 39 insertions(+), 49 deletions(-) diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index 03e65d21c5..c5b266782e 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -36,6 +36,7 @@ "dependencies": { "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", "@backstage/theme": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", diff --git a/plugins/stackstorm/src/api/StackStormClient.ts b/plugins/stackstorm/src/api/StackStormClient.ts index 692bfbe4a6..1eb81c63e9 100644 --- a/plugins/stackstorm/src/api/StackStormClient.ts +++ b/plugins/stackstorm/src/api/StackStormClient.ts @@ -15,6 +15,7 @@ */ import { Action, Execution, Pack, StackstormApi } from './types'; import { ConfigApi, DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; +import { ResponseError } from '@backstage/errors'; export class StackstormClient implements StackstormApi { private readonly discoveryApi: DiscoveryApi; @@ -57,28 +58,13 @@ export class StackstormClient implements StackstormApi { }, }); - if (!response.ok) throw new Error(`Unable to get data: ${response.status}`); + if (!response.ok) throw await ResponseError.fromResponse(response); return (await response.json()) as T; } - async addProject(bazaarProject: any): Promise { - const baseUrl = await this.discoveryApi.getBaseUrl('bazaar'); - - return await this.fetchApi - .fetch(`${baseUrl}/projects`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - body: JSON.stringify(bazaarProject), - }) - .then(resp => resp.json()); - } - async getExecutions(limit?: number, offset?: number): Promise { const params = { - limit: limit?.toString() || '25', + limit: limit?.toString() || '10', offset: offset?.toString() || '0', include_attributes: 'id,status,start_timestamp,action.ref,action.name,rule.ref', diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx index 96262d7e6b..35006baef0 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx @@ -15,7 +15,7 @@ */ import React, { useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; -import { Progress } from '@backstage/core-components'; +import { Progress, ResponseErrorPanel } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; import { List, @@ -28,7 +28,6 @@ import { import { makeStyles } from '@material-ui/core/styles'; import ExpandMore from '@material-ui/icons/ExpandMore'; import ExpandLess from '@material-ui/icons/ExpandLess'; -import { Alert } from '@material-ui/lab'; import { Action, Pack, stackstormApiRef } from '../../api'; const useStyles = makeStyles(theme => ({ @@ -64,7 +63,7 @@ export const ActionItems = ({ pack }: ActionItemsProps) => { if (loading) { return ; } else if (error) { - return {error.message}; + return ; } return ( @@ -133,7 +132,7 @@ export const ActionsList = () => { if (loading) { return ; } else if (error) { - return {error.message}; + return ; } return ( diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx index 47f301e910..8a55c31246 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionPanel.tsx @@ -14,11 +14,14 @@ * limitations under the License. */ import React from 'react'; -import { CodeSnippet, Progress } from '@backstage/core-components'; +import { + CodeSnippet, + Progress, + ResponseErrorPanel, +} from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; import { Execution, stackstormApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; -import { Alert } from '@material-ui/lab'; import { Button, Card, @@ -160,7 +163,7 @@ export const ExecutionPanel = ({ id }: { id: string }) => { if (loading) { return ; } else if (error) { - return {error.message}; + return ; } return ; diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx index 1816f1db1f..f034cb64e8 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx @@ -13,12 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useEffect, useState } from 'react'; -import { Link, Table, TableColumn } from '@backstage/core-components'; -import { useApi, errorApiRef } from '@backstage/core-plugin-api'; +import React, { useState } from 'react'; +import { + Link, + ResponseErrorPanel, + Table, + TableColumn, +} from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; import { Execution, stackstormApiRef } from '../../api'; import { Status } from './Status'; import { ExecutionPanel } from './ExecutionPanel'; +import useAsync from 'react-use/lib/useAsync'; type DenseTableProps = { executions: Execution[]; @@ -89,34 +95,24 @@ export const DenseTable = ({ export const ExecutionsTable = () => { const st2 = useApi(stackstormApiRef); - const errorApi = useApi(errorApiRef); const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(10); - const [data, setData] = useState([]); - const [loading, setLoading] = useState(false); - useEffect(() => { - const getData = async () => { - setLoading(true); - await st2 - .getExecutions(rowsPerPage, page * rowsPerPage) - .then(d => { - setData(d); - }) - .catch(err => { - errorApi.post(err); - }); - setLoading(false); - }; - getData(); - }, [errorApi, page, rowsPerPage, st2]); + const { value, loading, error } = useAsync(async (): Promise => { + const data = await st2.getExecutions(rowsPerPage, page * rowsPerPage); + return data; + }, [page, rowsPerPage, st2]); + + if (error) { + return ; + } return ( diff --git a/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx index ebb5e8a14e..2167200e8e 100644 --- a/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx +++ b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx @@ -14,8 +14,12 @@ * limitations under the License. */ import React from 'react'; -import { Progress, Table, TableColumn } from '@backstage/core-components'; -import { Alert } from '@material-ui/lab'; +import { + Progress, + ResponseErrorPanel, + Table, + TableColumn, +} from '@backstage/core-components'; import useAsync from 'react-use/lib/useAsync'; import { useApi } from '@backstage/core-plugin-api'; import { Pack, stackstormApiRef } from '../../api'; @@ -52,7 +56,7 @@ export const PacksTable = () => { if (loading) { return ; } else if (error) { - return {error.message}; + return ; } return ; diff --git a/yarn.lock b/yarn.lock index 5c8cdcad98..71eb638d93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7964,6 +7964,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 From 52b453aadbd7832f8f66d07d9adb296d99967b2d Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 16:59:00 +0000 Subject: [PATCH 220/417] fix: use core Link component for action links Signed-off-by: pamelin --- .../src/components/ActionsList/ActionsList.test.tsx | 5 +++++ .../src/components/ActionsList/ActionsList.tsx | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx index 5876860c54..2a65db427a 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.test.tsx @@ -56,6 +56,11 @@ describe('ActionsList', () => { const mockApi: jest.Mocked = { getPacks: jest.fn().mockResolvedValue(packs), getActions: jest.fn().mockResolvedValue(actions), + getActionUrl: jest + .fn() + .mockResolvedValue( + 'http://stackstorm.example.com:8080/?#/actions/core.action', + ), } as any; it('should render all packs', async () => { diff --git a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx index 35006baef0..1080f67373 100644 --- a/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx +++ b/plugins/stackstorm/src/components/ActionsList/ActionsList.tsx @@ -15,7 +15,7 @@ */ import React, { useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; -import { Progress, ResponseErrorPanel } from '@backstage/core-components'; +import { Link, Progress, ResponseErrorPanel } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; import { List, @@ -72,9 +72,12 @@ export const ActionItems = ({ pack }: ActionItemsProps) => { return ( window.open(st2.getActionUrl(a.ref), '_blank')} + underline="none" + color="inherit" + button > {a.runner_type} From 689a04a446132802fdaf8b3e50fe5de17c76e175 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 17:05:20 +0000 Subject: [PATCH 221/417] fix: use encodeURIComponent in StackstormClient Signed-off-by: pamelin --- plugins/stackstorm/src/api/StackStormClient.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/stackstorm/src/api/StackStormClient.ts b/plugins/stackstorm/src/api/StackStormClient.ts index 1eb81c63e9..495384e8a5 100644 --- a/plugins/stackstorm/src/api/StackStormClient.ts +++ b/plugins/stackstorm/src/api/StackStormClient.ts @@ -75,7 +75,7 @@ export class StackstormClient implements StackstormApi { } async getExecution(id: string): Promise { - const path = `/executions/${id}`; + const path = `/executions/${encodeURIComponent(id)}`; return this.get(path); } @@ -93,10 +93,10 @@ export class StackstormClient implements StackstormApi { } getExecutionHistoryUrl(id: string): string { - return `${this.webUrl}/?#/history/${id}`; + return `${this.webUrl}/?#/history/${encodeURIComponent(id)}`; } getActionUrl(ref: string): string { - return `${this.webUrl}/?#/actions/${ref}`; + return `${this.webUrl}/?#/actions/${encodeURIComponent(ref)}`; } } From a1aacf3d27b0d3717e0c685f646892005aeac888 Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 17:25:10 +0000 Subject: [PATCH 222/417] fix: rename files Signed-off-by: pamelin --- .../api/{StackStormClient.test.ts => StackstormClient.test.ts} | 0 .../src/api/{StackStormClient.ts => StackstormClient.ts} | 0 .../StackstormHome.test.tsx} | 0 .../StackStormHome.tsx => StackstormHome/StackstormHome.tsx} | 0 .../src/components/{StackStormHome => StackstormHome}/index.ts | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename plugins/stackstorm/src/api/{StackStormClient.test.ts => StackstormClient.test.ts} (100%) rename plugins/stackstorm/src/api/{StackStormClient.ts => StackstormClient.ts} (100%) rename plugins/stackstorm/src/components/{StackStormHome/StackStormHome.test.tsx => StackstormHome/StackstormHome.test.tsx} (100%) rename plugins/stackstorm/src/components/{StackStormHome/StackStormHome.tsx => StackstormHome/StackstormHome.tsx} (100%) rename plugins/stackstorm/src/components/{StackStormHome => StackstormHome}/index.ts (100%) diff --git a/plugins/stackstorm/src/api/StackStormClient.test.ts b/plugins/stackstorm/src/api/StackstormClient.test.ts similarity index 100% rename from plugins/stackstorm/src/api/StackStormClient.test.ts rename to plugins/stackstorm/src/api/StackstormClient.test.ts diff --git a/plugins/stackstorm/src/api/StackStormClient.ts b/plugins/stackstorm/src/api/StackstormClient.ts similarity index 100% rename from plugins/stackstorm/src/api/StackStormClient.ts rename to plugins/stackstorm/src/api/StackstormClient.ts diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx b/plugins/stackstorm/src/components/StackstormHome/StackstormHome.test.tsx similarity index 100% rename from plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx rename to plugins/stackstorm/src/components/StackstormHome/StackstormHome.test.tsx diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx b/plugins/stackstorm/src/components/StackstormHome/StackstormHome.tsx similarity index 100% rename from plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx rename to plugins/stackstorm/src/components/StackstormHome/StackstormHome.tsx diff --git a/plugins/stackstorm/src/components/StackStormHome/index.ts b/plugins/stackstorm/src/components/StackstormHome/index.ts similarity index 100% rename from plugins/stackstorm/src/components/StackStormHome/index.ts rename to plugins/stackstorm/src/components/StackstormHome/index.ts From 7d0674b8539de4173418ae706b0e2765077d6af4 Mon Sep 17 00:00:00 2001 From: Raghunandan Date: Thu, 16 Feb 2023 18:37:32 +0100 Subject: [PATCH 223/417] trying to pass vale linter check Signed-off-by: Raghunandan --- .changeset/ninety-turtles-wait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/ninety-turtles-wait.md b/.changeset/ninety-turtles-wait.md index 18f9dc70e9..683583528f 100644 --- a/.changeset/ninety-turtles-wait.md +++ b/.changeset/ninety-turtles-wait.md @@ -2,4 +2,4 @@ '@backstage/plugin-techdocs': patch --- -The html tag attributes in the documentation content inserted to shadow DOM is preserved to improve accessibility +The HTML tag attributes in the documentation content inserted to shadow DOM is preserved to improve accessibility From fd28151c954271b9109fcd1315a791be6e4d72be Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Thu, 16 Feb 2023 12:39:47 -0500 Subject: [PATCH 224/417] separates concerns of type usage within todo-backend Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/todo-backend/api-report.md | 6 ++---- plugins/todo-backend/src/service/index.ts | 8 ++++++-- plugins/todo-backend/src/service/plugin.ts | 9 ++------- plugins/todo-backend/src/service/types.ts | 9 +++++++++ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index 3e3c4cb58c..7492865ee4 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -8,7 +8,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import express from 'express'; -import { HttpRouterService } from '@backstage/backend-plugin-api'; +import type { HttpRouterService } from '@backstage/backend-plugin-api'; import { Logger } from 'winston'; import { ScmIntegrations } from '@backstage/integration'; import { UrlReader } from '@backstage/backend-common'; @@ -150,9 +150,7 @@ export interface TodoService { // @alpha (undocumented) export const todosPlugin: () => BackendFeature; -// Warning: (ae-missing-release-tag) "TodosPluginDependencies" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @alpha (undocumented) export type TodosPluginDependencies = { todoReader: TodoService; http: HttpRouterService; diff --git a/plugins/todo-backend/src/service/index.ts b/plugins/todo-backend/src/service/index.ts index 3dfff3f33e..89a6939cda 100644 --- a/plugins/todo-backend/src/service/index.ts +++ b/plugins/todo-backend/src/service/index.ts @@ -16,8 +16,12 @@ export { createRouter } from './router'; export type { RouterOptions } from './router'; -export type { TodoService, ListTodosRequest, ListTodosResponse } from './types'; +export type { + TodoService, + ListTodosRequest, + ListTodosResponse, + TodosPluginDependencies, +} from './types'; export { TodoReaderService } from './TodoReaderService'; export type { TodoReaderServiceOptions } from './TodoReaderService'; export { todosPlugin } from './plugin'; -export type { TodosPluginDependencies } from './plugin'; diff --git a/plugins/todo-backend/src/service/plugin.ts b/plugins/todo-backend/src/service/plugin.ts index 54b089221f..6c5fd3bf6c 100644 --- a/plugins/todo-backend/src/service/plugin.ts +++ b/plugins/todo-backend/src/service/plugin.ts @@ -17,7 +17,6 @@ import { createBackendPlugin, coreServices, - HttpRouterService, } from '@backstage/backend-plugin-api'; import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; import { InputError } from '@backstage/errors'; @@ -29,12 +28,8 @@ import { parseOrderByParam, } from '../lib/utils'; import { todoReaderServiceRef } from './TodoReaderService'; -import { TodoService, TODO_FIELDS } from './types'; - -export type TodosPluginDependencies = { - todoReader: TodoService; - http: HttpRouterService; -}; +import { TODO_FIELDS } from './types'; +import type { TodosPluginDependencies } from './types'; const todosPluginInit = async (params: TodosPluginDependencies) => { const { http, todoReader } = params; diff --git a/plugins/todo-backend/src/service/types.ts b/plugins/todo-backend/src/service/types.ts index ab15e20027..6b56487605 100644 --- a/plugins/todo-backend/src/service/types.ts +++ b/plugins/todo-backend/src/service/types.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import type { HttpRouterService } from '@backstage/backend-plugin-api'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { TodoItem } from '../lib'; @@ -56,3 +57,11 @@ export const TODO_FIELDS = [ 'viewUrl', 'repoFilePath', ] as const; + +/** + * @alpha + */ +export type TodosPluginDependencies = { + todoReader: TodoService; + http: HttpRouterService; +}; From 25394d153f46639ec4e03ba98d681666bef185da Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 18:09:32 +0000 Subject: [PATCH 225/417] fix: remove unused imports Signed-off-by: pamelin --- .../components/ExecutionsTable/ExecutionsTable.test.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx index 1890bfa10b..6727f3cc56 100644 --- a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx +++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.test.tsx @@ -13,12 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { configApiRef } from '@backstage/core-plugin-api'; -import { - MockConfigApi, - renderInTestApp, - TestApiProvider, -} from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { Execution, StackstormApi, stackstormApiRef } from '../../api'; import { ExecutionsTable } from './ExecutionsTable'; From 76c4fcd44785110dce4ca8ea59b6e245393c303d Mon Sep 17 00:00:00 2001 From: pamelin Date: Thu, 16 Feb 2023 18:18:43 +0000 Subject: [PATCH 226/417] fix: add st2 icon Signed-off-by: pamelin --- microsite/data/plugins/stackstorm.yaml | 1 + microsite/static/img/stackstorm.png | Bin 0 -> 3936 bytes 2 files changed, 1 insertion(+) create mode 100644 microsite/static/img/stackstorm.png diff --git a/microsite/data/plugins/stackstorm.yaml b/microsite/data/plugins/stackstorm.yaml index 282117d1fe..2524ca538f 100644 --- a/microsite/data/plugins/stackstorm.yaml +++ b/microsite/data/plugins/stackstorm.yaml @@ -5,6 +5,7 @@ authorUrl: https://github.com/ExpediaGroup category: Automation description: Manage StackStorm workflow executions from within Backstage. documentation: https://github.com/backstage/backstage/tree/master/plugins/stackstorm +iconUrl: img/stackstorm.png npmPackageName: '@backstage/plugin-stackstorm' tags: - stackstorm diff --git a/microsite/static/img/stackstorm.png b/microsite/static/img/stackstorm.png new file mode 100644 index 0000000000000000000000000000000000000000..f017906e073f53022e412210f4c1852eea1f4197 GIT binary patch literal 3936 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 Date: Thu, 16 Feb 2023 19:36:36 +0100 Subject: [PATCH 227/417] chore: fixing code block in sidebar Signed-off-by: blam --- docs/features/software-templates/testing-scaffolder-alpha.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-templates/testing-scaffolder-alpha.md b/docs/features/software-templates/testing-scaffolder-alpha.md index 2182a86976..76479b137e 100644 --- a/docs/features/software-templates/testing-scaffolder-alpha.md +++ b/docs/features/software-templates/testing-scaffolder-alpha.md @@ -1,6 +1,6 @@ --- id: testing-scaffolder-alpha -title: 'Experimental: Testing out the `alpha` Scaffolder plugin' +title: 'Experimental: Testing out the alpha Scaffolder plugin' # prettier-ignore description: Docs on the upcoming breaking release for the scaffolder plugin --- From 692d9a01347623b1f1a20cc96c9b7493ec6864a0 Mon Sep 17 00:00:00 2001 From: Adam Vollrath Date: Thu, 16 Feb 2023 12:37:29 -0600 Subject: [PATCH 228/417] Use `postgres` container in preview deployments on Uffizzi Signed-off-by: Adam Vollrath --- .github/uffizzi/docker-compose.uffizzi.yml | 11 ++++++++--- .github/uffizzi/uffizzi.production.app-config.yaml | 10 +++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/uffizzi/docker-compose.uffizzi.yml b/.github/uffizzi/docker-compose.uffizzi.yml index 49039cad2a..76a7b4eafc 100644 --- a/.github/uffizzi/docker-compose.uffizzi.yml +++ b/.github/uffizzi/docker-compose.uffizzi.yml @@ -10,9 +10,10 @@ services: image: '${BACKSTAGE_IMAGE}' environment: - POSTGRES_HOST: db + POSTGRES_HOST: localhost + POSTGRES_PORT: 5432 POSTGRES_USER: postgres - POSTGRES_PASSWORD: example + POSTGRES_PASSWORD: kiTMoTsiEuyQ43GrL4Hv NODE_ENV: production deploy: resources: @@ -26,4 +27,8 @@ services: db: image: postgres environment: - POSTGRES_PASSWORD: example + POSTGRES_PASSWORD: kiTMoTsiEuyQ43GrL4Hv + deploy: + resources: + limits: + memory: 250M diff --git a/.github/uffizzi/uffizzi.production.app-config.yaml b/.github/uffizzi/uffizzi.production.app-config.yaml index d4b70641da..30cffa11c9 100644 --- a/.github/uffizzi/uffizzi.production.app-config.yaml +++ b/.github/uffizzi/uffizzi.production.app-config.yaml @@ -9,13 +9,17 @@ backend: baseUrl: ${UFFIZZI_URL} auth: keys: - # random mock key for uffizi deployments + # random mock key for Uffizzi deployments - secret: 5TXvdjVZFxF7qf9K5RAYRDoGrLzJooqa listen: port: 7007 database: - client: better-sqlite3 - connection: ':memory:' + client: pg + connection: + host: ${POSTGRES_HOST} + port: ${POSTGRES_PORT} + user: ${POSTGRES_USER} + password: ${POSTGRES_PASSWORD} cache: store: memory cors: From dd266650aa3cd6502b6dd6432386cd88d6582143 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 16 Feb 2023 20:38:17 +0100 Subject: [PATCH 229/417] chore: fix small alignment issue with owner Signed-off-by: blam --- .../src/next/components/TemplateCard/TemplateCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx index 6f89808405..af44085151 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx @@ -162,7 +162,7 @@ export const TemplateCard = (props: TemplateCardProps) => { )} - +
    {ownedByRelations.length > 0 && ( From d4100d0ec422d1121f6e131a9950f17b03eb9ac6 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 16 Feb 2023 20:40:42 +0100 Subject: [PATCH 230/417] chore: changeset Signed-off-by: blam --- .changeset/spotty-wasps-complain.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/spotty-wasps-complain.md diff --git a/.changeset/spotty-wasps-complain.md b/.changeset/spotty-wasps-complain.md new file mode 100644 index 0000000000..7b1e42b2a0 --- /dev/null +++ b/.changeset/spotty-wasps-complain.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Fix alignment bug for owners on `TemplateCard` From b81f3e2bd52182136907b90385a0d5273e59a2ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 23:41:44 +0000 Subject: [PATCH 231/417] chore(deps): bump undici from 5.12.0 to 5.19.1 Bumps [undici](https://github.com/nodejs/undici) from 5.12.0 to 5.19.1. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v5.12.0...v5.19.1) --- updated-dependencies: - dependency-name: undici dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 550c230ba3..51c397f55c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -37433,11 +37433,11 @@ __metadata: linkType: hard "undici@npm:^5.12.0, undici@npm:^5.8.0": - version: 5.12.0 - resolution: "undici@npm:5.12.0" + version: 5.19.1 + resolution: "undici@npm:5.19.1" dependencies: busboy: ^1.6.0 - checksum: fbc227704943c05aa3dc1630695e10309c17d0a535678594d136db107c50593248e9ace70e1ab77496a6c837bf14aa2ab3c501a7a6c45fb6277dbf0846e15ffe + checksum: 57ee94ee74d944faa41dbcb2faf4e0c90069708d3aaae860185884e51376b5d457728352a8396d69a3c9cb752b62ff99a19a664c5aacb7ee61cc488af499a01c languageName: node linkType: hard From 542da6ba1191c38584d78c9a2e395717edf133e6 Mon Sep 17 00:00:00 2001 From: Guanghui Li Date: Fri, 17 Feb 2023 00:07:48 -0600 Subject: [PATCH 232/417] Fixed IdentifyClient import inconsistency in permissions tutorial Signed-off-by: Guanghui Li --- .../plugin-authors/02-adding-a-basic-permission-check.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md index 2ceb8057f4..44a3e43718 100644 --- a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md +++ b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md @@ -100,7 +100,7 @@ Edit `plugins/todo-list-backend/src/service/router.ts`: Pass the `permissions` object to the plugin in `packages/backend/src/plugins/todolist.ts`: ```diff - import { IdentityClient } from '@backstage/plugin-auth-backend'; + import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; import { createRouter } from '@internal/plugin-todo-list-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; @@ -112,7 +112,7 @@ Pass the `permissions` object to the plugin in `packages/backend/src/plugins/tod }: PluginEnvironment): Promise { return await createRouter({ logger, - identity: new IdentityClient({ + identity: DefaultIdentityClient.create({ discovery, issuer: await discovery.getExternalBaseUrl('auth'), }), From e52e12298b68d5cd55b24366a0f071b280f44069 Mon Sep 17 00:00:00 2001 From: pamelin Date: Fri, 17 Feb 2023 09:40:25 +0000 Subject: [PATCH 233/417] fix: update stackstorm config Signed-off-by: pamelin --- plugins/stackstorm/config.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/stackstorm/config.d.ts b/plugins/stackstorm/config.d.ts index b85d682eb0..bf7b56823a 100644 --- a/plugins/stackstorm/config.d.ts +++ b/plugins/stackstorm/config.d.ts @@ -14,7 +14,7 @@ * limitations under the License. */ export interface Config { - stackstorm: { + stackstorm?: { /** * StackStorm Web UI url * Used in links to StackStorm web UI From a4ebd513527c7c4f0674196eed680a01b2409afe Mon Sep 17 00:00:00 2001 From: drodil Date: Thu, 16 Feb 2023 09:21:08 +0200 Subject: [PATCH 234/417] fix: revert use graph API target url for access token Signed-off-by: drodil --- .changeset/eighty-geese-return.md | 5 +++++ .../src/microsoftGraph/client.test.ts | 2 +- .../src/microsoftGraph/client.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/eighty-geese-return.md diff --git a/.changeset/eighty-geese-return.md b/.changeset/eighty-geese-return.md new file mode 100644 index 0000000000..1f95e4843e --- /dev/null +++ b/.changeset/eighty-geese-return.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +revert ms graph token as it breaks the graph provider diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts index f7d98f12c6..f621b4d924 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts @@ -53,7 +53,7 @@ describe('MicrosoftGraphClient', () => { expect(await response.json()).toEqual({ value: 'example' }); expect(tokenCredential.getToken).toHaveBeenCalledTimes(1); expect(tokenCredential.getToken).toHaveBeenCalledWith( - 'https://example.com/.default', + 'https://graph.microsoft.com/.default', ); }); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts index 7a685b258d..c644e545d6 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts @@ -219,7 +219,7 @@ export class MicrosoftGraphClient { ): Promise { // Make sure that we always have a valid access token (might be cached) const token = await this.tokenCredential.getToken( - `${this.baseUrl}/.default`, + 'https://graph.microsoft.com/.default', ); if (!token) { From e19c3ab15539c391ba50ac9ccc90c6a5db00fd09 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Thu, 16 Feb 2023 20:04:09 +0100 Subject: [PATCH 235/417] Update eighty-geese-return.md Signed-off-by: Ben Lambert --- .changeset/eighty-geese-return.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eighty-geese-return.md b/.changeset/eighty-geese-return.md index 1f95e4843e..49361de8e7 100644 --- a/.changeset/eighty-geese-return.md +++ b/.changeset/eighty-geese-return.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-backend-module-msgraph': patch --- -revert ms graph token as it breaks the graph provider +Revert using `baseUrl` for MS Graph provider as it breaks token retrieval From e3e2c57272e5f7a955d9ff0ce23ebb8e760591bc Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 11:11:53 +0100 Subject: [PATCH 236/417] chore: moving `@alpha` types to `@public` Signed-off-by: blam --- plugins/sonarqube-react/api-report.md | 14 +++++++------- plugins/sonarqube-react/src/api/SonarQubeApi.ts | 12 ++++++------ .../sonarqube-react/src/hooks/useProjectInfo.ts | 2 +- plugins/sonarqube/api-report.md | 2 +- plugins/sonarqube/src/api/SonarQubeClient.ts | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/plugins/sonarqube-react/api-report.md b/plugins/sonarqube-react/api-report.md index be84c45cce..6ffa98915b 100644 --- a/plugins/sonarqube-react/api-report.md +++ b/plugins/sonarqube-react/api-report.md @@ -6,7 +6,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; -// @alpha (undocumented) +// @public (undocumented) export interface FindingSummary { // (undocumented) getComponentMeasuresUrl: SonarUrlProcessorFunc; @@ -25,7 +25,7 @@ export interface FindingSummary { // @public (undocumented) export const isSonarQubeAvailable: (entity: Entity) => boolean; -// @alpha (undocumented) +// @public (undocumented) export type MetricKey = | 'alert_status' | 'bugs' @@ -39,7 +39,7 @@ export type MetricKey = | 'coverage' | 'duplicated_lines_density'; -// @alpha +// @public export type Metrics = { [key in MetricKey]: string | undefined; }; @@ -47,7 +47,7 @@ export type Metrics = { // @public (undocumented) export const SONARQUBE_PROJECT_KEY_ANNOTATION = 'sonarqube.org/project-key'; -// @alpha (undocumented) +// @public (undocumented) export type SonarQubeApi = { getFindingSummary(options: { componentKey?: string; @@ -55,13 +55,13 @@ export type SonarQubeApi = { }): Promise; }; -// @alpha (undocumented) +// @public (undocumented) export const sonarQubeApiRef: ApiRef; -// @alpha (undocumented) +// @public (undocumented) export type SonarUrlProcessorFunc = (identifier: string) => string; -// @alpha +// @public export const useProjectInfo: (entity: Entity) => { projectInstance: string | undefined; projectKey: string | undefined; diff --git a/plugins/sonarqube-react/src/api/SonarQubeApi.ts b/plugins/sonarqube-react/src/api/SonarQubeApi.ts index ee6b1bb6a3..13517d97fe 100644 --- a/plugins/sonarqube-react/src/api/SonarQubeApi.ts +++ b/plugins/sonarqube-react/src/api/SonarQubeApi.ts @@ -16,7 +16,7 @@ import { createApiRef } from '@backstage/core-plugin-api'; -/** @alpha */ +/** @public */ export type MetricKey = // alert status | 'alert_status' @@ -43,11 +43,11 @@ export type MetricKey = // duplicated lines | 'duplicated_lines_density'; -/** @alpha */ +/** @public */ export type SonarUrlProcessorFunc = (identifier: string) => string; /** - * @alpha + * @public * * Define a type to make sure that all metrics are used */ @@ -55,7 +55,7 @@ export type Metrics = { [key in MetricKey]: string | undefined; }; -/** @alpha */ +/** @public */ export interface FindingSummary { lastAnalysis: string; metrics: Metrics; @@ -65,12 +65,12 @@ export interface FindingSummary { getSecurityHotspotsUrl: () => string; } -/** @alpha */ +/** @public */ export const sonarQubeApiRef = createApiRef({ id: 'plugin.sonarqube.service', }); -/** @alpha */ +/** @public */ export type SonarQubeApi = { getFindingSummary(options: { componentKey?: string; diff --git a/plugins/sonarqube-react/src/hooks/useProjectInfo.ts b/plugins/sonarqube-react/src/hooks/useProjectInfo.ts index 119e568e46..3336bd1805 100644 --- a/plugins/sonarqube-react/src/hooks/useProjectInfo.ts +++ b/plugins/sonarqube-react/src/hooks/useProjectInfo.ts @@ -25,7 +25,7 @@ export const SONARQUBE_PROJECT_INSTANCE_SEPARATOR = '/'; * * If part or all info are not found, they will default to undefined * - * @alpha + * @public * @param entity - entity to find the sonarqube information from. * @returns a ProjectInfo properly populated. */ diff --git a/plugins/sonarqube/api-report.md b/plugins/sonarqube/api-report.md index f77c66ac59..db3f38e31d 100644 --- a/plugins/sonarqube/api-report.md +++ b/plugins/sonarqube/api-report.md @@ -42,7 +42,7 @@ export const SonarQubeCard: (props: { duplicationRatings?: DuplicationRating[]; }) => JSX.Element; -// @alpha (undocumented) +// @public (undocumented) export class SonarQubeClient implements SonarQubeApi { constructor({ discoveryApi, diff --git a/plugins/sonarqube/src/api/SonarQubeClient.ts b/plugins/sonarqube/src/api/SonarQubeClient.ts index f742fe026f..14c7936e92 100644 --- a/plugins/sonarqube/src/api/SonarQubeClient.ts +++ b/plugins/sonarqube/src/api/SonarQubeClient.ts @@ -23,7 +23,7 @@ import { import { InstanceUrlWrapper, FindingsWrapper } from './types'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; -/** @alpha */ +/** @public */ export class SonarQubeClient implements SonarQubeApi { discoveryApi: DiscoveryApi; identityApi: IdentityApi; From 8ae65a0bc1d7c12659dba62e2fbb293e7705e556 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 11:15:08 +0100 Subject: [PATCH 237/417] chore: changeset Signed-off-by: blam --- .changeset/swift-bags-wave.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/swift-bags-wave.md diff --git a/.changeset/swift-bags-wave.md b/.changeset/swift-bags-wave.md new file mode 100644 index 0000000000..8f57c7f89b --- /dev/null +++ b/.changeset/swift-bags-wave.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-sonarqube-react': patch +'@backstage/plugin-sonarqube': patch +--- + +Moved imports from `/alpha` to main public exports. From a3576a386ed3af37d84345f8c3518ada5990f24b Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 09:21:34 +0100 Subject: [PATCH 238/417] chore: fixing the eslint rule Signed-off-by: blam --- packages/eslint-plugin/lib/visitImports.js | 2 ++ .../eslint-plugin/rules/no-undeclared-imports.js | 12 +++++++----- .../eslint-plugin/src/no-undeclared-imports.test.ts | 11 +++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/lib/visitImports.js b/packages/eslint-plugin/lib/visitImports.js index 43401bf5f9..1a344c1101 100644 --- a/packages/eslint-plugin/lib/visitImports.js +++ b/packages/eslint-plugin/lib/visitImports.js @@ -34,6 +34,7 @@ const getPackages = require('./getPackages'); * @property {'value' | 'type'} kind * @property {string} path * @property {import('./getPackages').ExtendedPackage} package + * @property {string} packageName */ /** @@ -160,6 +161,7 @@ module.exports = function visitImports(context, visitor) { kind: info.kind, path: subPath, package: pkg, + packageName, }); } diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index 42624beb5c..c86792b933 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -151,11 +151,13 @@ module.exports = { } return visitImports(context, (node, imp) => { - if (imp.type !== 'external') { - return; - } - // We leave checking of type imports to the repo-tools check - if (imp.kind === 'type') { + // We leave checking of type imports to the repo-tools check, + // and we skip builtins and local imports + if ( + imp.kind === 'type' || + imp.type === 'builtin' || + imp.type === 'local' + ) { return; } diff --git a/packages/eslint-plugin/src/no-undeclared-imports.test.ts b/packages/eslint-plugin/src/no-undeclared-imports.test.ts index 1b5cbee853..78844899ba 100644 --- a/packages/eslint-plugin/src/no-undeclared-imports.test.ts +++ b/packages/eslint-plugin/src/no-undeclared-imports.test.ts @@ -236,5 +236,16 @@ ruleTester.run(RULE, rule, { ), ], }, + { + code: `import '@internal/foo'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED( + '@internal/foo', + 'dependencies', + joinPath('packages', 'bar'), + ), + ], + }, ], }); From a061c466d665dfed8383ff06a7417cba3398802c Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 09:22:53 +0100 Subject: [PATCH 239/417] chore: add changeset Signed-off-by: blam --- .changeset/gentle-pears-clean.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/gentle-pears-clean.md diff --git a/.changeset/gentle-pears-clean.md b/.changeset/gentle-pears-clean.md new file mode 100644 index 0000000000..d92c3709ae --- /dev/null +++ b/.changeset/gentle-pears-clean.md @@ -0,0 +1,5 @@ +--- +'@backstage/eslint-plugin': patch +--- + +Fixing a bug that we should check internal dependencies too From f85b1001238c1db2f3c1e5962377d5cd79a88af8 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 10:42:18 +0100 Subject: [PATCH 240/417] chore: fix missing deps Signed-off-by: blam --- packages/e2e-test/package.json | 1 + plugins/auth-backend/package.json | 1 + .../catalog-backend-module-aws/package.json | 2 + .../package.json | 1 + .../src/run.ts | 47 ++++++++++++------- .../src/service/standaloneApplication.ts | 4 ++ 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index ee447a1736..39cc84cb14 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -27,6 +27,7 @@ }, "bin": "bin/e2e-test", "dependencies": { + "@backstage/create-app": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/errors": "workspace:^", "chalk": "^4.0.0", diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 3481ae2714..dee7f6e442 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -78,6 +78,7 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", + "@backstage/test-utils": "workspace:^", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 4082a4f83b..f583d64792 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -41,7 +41,9 @@ "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^", + "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", + "@backstage/plugin-kubernetes-common": "workspace:^", "@backstage/types": "workspace:^", "aws-sdk": "^2.840.0", "lodash": "^4.17.21", diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 9a09ea6ca2..ff8272e29e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -34,6 +34,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-defaults": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", "@backstage/catalog-model": "workspace:^", diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index e9cc7dbb2a..eb66140fe2 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -13,8 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { coreServices } from '@backstage/backend-plugin-api'; -import { startTestBackend } from '@backstage/backend-test-utils'; +import { createBackend } from '@backstage/backend-defaults'; +import { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; import { catalogPlugin } from '@backstage/plugin-catalog-backend'; import { @@ -46,25 +49,33 @@ async function main() { }, }; - await startTestBackend({ - services: [[coreServices.config, new ConfigReader(config)]], - extensionPoints: [], - features: [ - catalogPlugin(), - incrementalIngestionEntityProviderCatalogModule({ - providers: [ - { - provider: provider, - options: { - burstInterval: { seconds: 1 }, - burstLength: { seconds: 10 }, - restLength: { seconds: 10 }, - }, - }, - ], + const backend = createBackend({ + services: [ + createServiceFactory({ + service: coreServices.config, + deps: {}, + factory: () => new ConfigReader(config), }), ], }); + + backend.add(catalogPlugin()); + backend.add( + incrementalIngestionEntityProviderCatalogModule({ + providers: [ + { + provider: provider, + options: { + burstInterval: { seconds: 1 }, + burstLength: { seconds: 10 }, + restLength: { seconds: 10 }, + }, + }, + ], + }), + ); + + await backend.start(); } main().catch(error => { diff --git a/plugins/vault-backend/src/service/standaloneApplication.ts b/plugins/vault-backend/src/service/standaloneApplication.ts index bcec8ca419..ba4c0edc3e 100644 --- a/plugins/vault-backend/src/service/standaloneApplication.ts +++ b/plugins/vault-backend/src/service/standaloneApplication.ts @@ -28,6 +28,10 @@ import helmet from 'helmet'; import { Logger } from 'winston'; import { createRouter } from './router'; import { ConfigReader } from '@backstage/config'; + +// Think this file will probably go away once we move to backend system +// And restructure into the /dev folder +// eslint-disable-next-line @backstage/no-undeclared-imports import { TestDatabases } from '@backstage/backend-test-utils'; import { TaskScheduler } from '@backstage/backend-tasks'; From bf611cf019a091775ae484eb6e1377b9c5a71254 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 10:43:09 +0100 Subject: [PATCH 241/417] chore: added changesets Signed-off-by: blam --- .changeset/spotty-bees-tell.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/spotty-bees-tell.md diff --git a/.changeset/spotty-bees-tell.md b/.changeset/spotty-bees-tell.md new file mode 100644 index 0000000000..5267d8a6a0 --- /dev/null +++ b/.changeset/spotty-bees-tell.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-catalog-backend-module-aws': patch +--- + +Fix missing `dependencies` in `package.json` From e24851b4facf2458d845b20a0adf39d7703420f0 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 10:57:18 +0100 Subject: [PATCH 242/417] chore: added mock node_modules for resolution Signed-off-by: blam --- .../node_modules/@internal/foo/index.js | 0 .../node_modules/@internal/foo/package.json | 17 +++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 packages/eslint-plugin/src/__fixtures__/monorepo/packages/node_modules/@internal/foo/index.js create mode 100644 packages/eslint-plugin/src/__fixtures__/monorepo/packages/node_modules/@internal/foo/package.json diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/node_modules/@internal/foo/index.js b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/node_modules/@internal/foo/index.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/node_modules/@internal/foo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/node_modules/@internal/foo/package.json new file mode 100644 index 0000000000..c15a2c1718 --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/node_modules/@internal/foo/package.json @@ -0,0 +1,17 @@ +{ + "name": "@internal/foo", + "main": "index.js", + "dependencies": { + "@internal/bar": "1.0.0" + }, + "devDependencies": { + "lodash": "*" + }, + "peerDependencies": { + "react": "*" + }, + "files": [ + "dist", + "type-utils" + ] +} From b37fa77b00feacbe9f7e38ee4e3acbbee4e510f8 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 11:02:09 +0100 Subject: [PATCH 243/417] chore: fixing yarn.lock Signed-off-by: blam --- packages/e2e-test/package.json | 2 +- yarn.lock | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 39cc84cb14..718f8fd079 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -27,8 +27,8 @@ }, "bin": "bin/e2e-test", "dependencies": { - "@backstage/create-app": "workspace:^", "@backstage/cli-common": "workspace:^", + "@backstage/create-app": "workspace:^", "@backstage/errors": "workspace:^", "chalk": "^4.0.0", "commander": "^9.1.0", diff --git a/yarn.lock b/yarn.lock index 550c230ba3..7d905a0873 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3964,7 +3964,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/create-app@workspace:*, @backstage/create-app@workspace:packages/create-app": +"@backstage/create-app@workspace:*, @backstage/create-app@workspace:^, @backstage/create-app@workspace:packages/create-app": version: 0.0.0-use.local resolution: "@backstage/create-app@workspace:packages/create-app" dependencies: @@ -4438,6 +4438,7 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" + "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@davidzemon/passport-okta-oauth": ^0.0.5 "@google-cloud/firestore": ^6.0.0 @@ -4795,7 +4796,9 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-catalog-backend": "workspace:^" + "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" + "@backstage/plugin-kubernetes-common": "workspace:^" "@backstage/types": "workspace:^" "@types/lodash": ^4.14.151 aws-sdk: ^2.840.0 @@ -4997,6 +5000,7 @@ __metadata: dependencies: "@backstage/backend-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" + "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -21023,6 +21027,7 @@ __metadata: dependencies: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" + "@backstage/create-app": "workspace:^" "@backstage/errors": "workspace:^" "@types/fs-extra": ^9.0.1 "@types/node": ^16.11.26 From b22d090dda148f47aba18fa74742fe3af91e900b Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 11:41:02 +0100 Subject: [PATCH 244/417] chore: skip imports for the package itself, this works as expected in node Signed-off-by: blam --- packages/eslint-plugin/rules/no-undeclared-imports.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index c86792b933..b1e11d1b97 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -161,6 +161,11 @@ module.exports = { return; } + // We skip imports for the package itself + if (imp.packageName === localPkg.packageJson.name) { + return; + } + const modulePath = path.relative(localPkg.dir, filePath); const expectedType = getExpectedDepType( localPkg.packageJson, From 66b3a3956b82ad7bdd5b1c6334a1d94d32f94eab Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 17 Feb 2023 12:09:26 +0100 Subject: [PATCH 245/417] chore: changeset Signed-off-by: blam --- .changeset/polite-chicken-do.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-chicken-do.md diff --git a/.changeset/polite-chicken-do.md b/.changeset/polite-chicken-do.md new file mode 100644 index 0000000000..33e4149253 --- /dev/null +++ b/.changeset/polite-chicken-do.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-vault-backend': patch +--- + +Ignore the `eslint` error From 4a1c318853dc15b98a18db642a2acce0b487d900 Mon Sep 17 00:00:00 2001 From: Niklas Aronsson Date: Fri, 17 Feb 2023 09:54:24 +0100 Subject: [PATCH 246/417] Linguist-backend: Add token to catalogClient The catalog client calls will fail for backstage deployments with authentication. Signed-off-by: Niklas Aronsson --- .changeset/nice-planets-wave.md | 5 +++++ plugins/linguist-backend/api-report.md | 4 ++++ .../src/api/LinguistBackendApi.ts | 19 +++++++++++++++---- .../src/service/router.test.ts | 7 +++++++ .../linguist-backend/src/service/router.ts | 6 +++++- .../src/service/standaloneServer.ts | 2 ++ 6 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 .changeset/nice-planets-wave.md diff --git a/.changeset/nice-planets-wave.md b/.changeset/nice-planets-wave.md new file mode 100644 index 0000000000..2af1a14d83 --- /dev/null +++ b/.changeset/nice-planets-wave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-linguist-backend': minor +--- + +**BREAKING** The linguist-backend `createRouter` now requires that the `tokenManger` is passed to the router. diff --git a/plugins/linguist-backend/api-report.md b/plugins/linguist-backend/api-report.md index c11296b0b3..18fcec978e 100644 --- a/plugins/linguist-backend/api-report.md +++ b/plugins/linguist-backend/api-report.md @@ -14,6 +14,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { ProcessedEntity } from '@backstage/plugin-linguist-common'; import { TaskScheduleDefinition } from '@backstage/backend-tasks'; +import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; // @public (undocumented) @@ -29,6 +30,7 @@ export class LinguistBackendApi { store: LinguistBackendStore, urlReader: UrlReader, discovery: PluginEndpointDiscovery, + tokenManager: TokenManager, age?: HumanDuration, batchSize?: number, useSourceLocation?: boolean, @@ -96,6 +98,8 @@ export interface RouterOptions { reader: UrlReader; // (undocumented) scheduler?: PluginTaskScheduler; + // (undocumented) + tokenManager: TokenManager; } // (No @packageDocumentation comment for this package) diff --git a/plugins/linguist-backend/src/api/LinguistBackendApi.ts b/plugins/linguist-backend/src/api/LinguistBackendApi.ts index 6c2e46e112..105335b0ed 100644 --- a/plugins/linguist-backend/src/api/LinguistBackendApi.ts +++ b/plugins/linguist-backend/src/api/LinguistBackendApi.ts @@ -25,7 +25,11 @@ import { CatalogClient, GetEntitiesRequest, } from '@backstage/catalog-client'; -import { PluginEndpointDiscovery, UrlReader } from '@backstage/backend-common'; +import { + PluginEndpointDiscovery, + TokenManager, + UrlReader, +} from '@backstage/backend-common'; import { DateTime } from 'luxon'; import { LINGUIST_ANNOTATION } from '@backstage/plugin-linguist-common'; @@ -46,6 +50,8 @@ export class LinguistBackendApi { private readonly store: LinguistBackendStore; private readonly urlReader: UrlReader; private readonly discovery: PluginEndpointDiscovery; + private readonly tokenManager: TokenManager; + private readonly catalogClient: CatalogClient; private readonly age?: HumanDuration; private readonly batchSize?: number; @@ -55,6 +61,7 @@ export class LinguistBackendApi { store: LinguistBackendStore, urlReader: UrlReader, discovery: PluginEndpointDiscovery, + tokenManager: TokenManager, age?: HumanDuration, batchSize?: number, useSourceLocation?: boolean, @@ -63,8 +70,8 @@ export class LinguistBackendApi { this.store = store; this.urlReader = urlReader; this.discovery = discovery; + this.tokenManager = tokenManager; this.catalogClient = new CatalogClient({ discoveryApi: this.discovery }); - this.batchSize = batchSize; this.age = age; this.useSourceLocation = useSourceLocation; @@ -98,7 +105,8 @@ export class LinguistBackendApi { fields: ['kind', 'metadata'], }; - const response = await this.catalogClient.getEntities(request); + const { token } = await this.tokenManager.getToken(); + const response = await this.catalogClient.getEntities(request, { token }); const entities = response.items; entities.forEach(entity => { @@ -118,7 +126,10 @@ export class LinguistBackendApi { this.batchSize ?? 20, ); entities.forEach(async entityRef => { - const entity = await this.catalogClient.getEntityByRef(entityRef); + const { token } = await this.tokenManager.getToken(); + const entity = await this.catalogClient.getEntityByRef(entityRef, { + token, + }); const annotationKey = this.useSourceLocation ? ANNOTATION_SOURCE_LOCATION : LINGUIST_ANNOTATION; diff --git a/plugins/linguist-backend/src/service/router.test.ts b/plugins/linguist-backend/src/service/router.test.ts index 34f16f4b21..b8bde9d35d 100644 --- a/plugins/linguist-backend/src/service/router.test.ts +++ b/plugins/linguist-backend/src/service/router.test.ts @@ -19,6 +19,7 @@ import { getVoidLogger, PluginDatabaseManager, PluginEndpointDiscovery, + TokenManager, UrlReaders, } from '@backstage/backend-common'; import express from 'express'; @@ -48,6 +49,11 @@ const testDiscovery: jest.Mocked = { getExternalBaseUrl: jest.fn(), }; +const mockedTokenManager: jest.Mocked = { + getToken: jest.fn(), + authenticate: jest.fn(), +}; + const mockUrlReader = UrlReaders.default({ logger: getVoidLogger(), config: new ConfigReader({}), @@ -72,6 +78,7 @@ describe('createRouter', () => { database: createDatabase(), reader: mockUrlReader, logger: getVoidLogger(), + tokenManager: mockedTokenManager, }, ); app = express().use(router); diff --git a/plugins/linguist-backend/src/service/router.ts b/plugins/linguist-backend/src/service/router.ts index e3aeec604e..18c43d996a 100644 --- a/plugins/linguist-backend/src/service/router.ts +++ b/plugins/linguist-backend/src/service/router.ts @@ -18,6 +18,7 @@ import { errorHandler, PluginDatabaseManager, PluginEndpointDiscovery, + TokenManager, UrlReader, } from '@backstage/backend-common'; import express from 'express'; @@ -44,6 +45,7 @@ export interface RouterOptions { linguistBackendApi?: LinguistBackendApi; logger: Logger; reader: UrlReader; + tokenManager: TokenManager; database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; scheduler?: PluginTaskScheduler; @@ -56,7 +58,8 @@ export async function createRouter( ): Promise { const { schedule, age, batchSize, useSourceLocation } = pluginOptions; - const { logger, reader, database, discovery, scheduler } = routerOptions; + const { logger, reader, database, discovery, scheduler, tokenManager } = + routerOptions; const linguistBackendStore = await LinguistBackendDatabase.create( await database.getClient(), @@ -69,6 +72,7 @@ export async function createRouter( linguistBackendStore, reader, discovery, + tokenManager, age, batchSize, useSourceLocation, diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 828c83630a..11604cddfb 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -20,6 +20,7 @@ import { SingleHostDiscovery, UrlReaders, useHotMemoize, + ServerTokenManager, } from '@backstage/backend-common'; import { Server } from 'http'; import { Logger } from 'winston'; @@ -66,6 +67,7 @@ export async function startStandaloneServer( discovery: SingleHostDiscovery.fromConfig(config), reader: UrlReaders.default({ logger, config }), logger, + tokenManager: ServerTokenManager.noop(), }, ); From 3c60558ef2bfbae265e42e225515c7bd9a5fb3b4 Mon Sep 17 00:00:00 2001 From: djamaile Date: Fri, 17 Feb 2023 15:11:32 +0100 Subject: [PATCH 247/417] chore: delete generate-changeset-feedback script Signed-off-by: djamaile --- scripts/generate-changeset-feedback.js | 314 ------------------------- 1 file changed, 314 deletions(-) delete mode 100644 scripts/generate-changeset-feedback.js diff --git a/scripts/generate-changeset-feedback.js b/scripts/generate-changeset-feedback.js deleted file mode 100644 index b9ad09ca72..0000000000 --- a/scripts/generate-changeset-feedback.js +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2022 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. - */ - -const fs = require('fs'); -const { execFile: execFileCb } = require('child_process'); -const { promisify } = require('util'); -const { - basename, - resolve: resolvePath, - relative: relativePath, -} = require('path'); - -const execFile = promisify(execFileCb); - -// Tells whether a path relative to the package directory has an effect -// on the published package -function isPublishedPath(path) { - if (path.startsWith('dev/')) { - return false; - } - if (path.includes('__mocks__')) { - return false; - } - if (path.includes('__fixtures__')) { - return false; - } - // Don't count manual modifications to the changelog - if (path === 'CHANGELOG.md') { - return false; - } - // API report changes by themselves don't count - if (path === 'api-report.md' || path === 'cli-report.md') { - return false; - } - // Lint changes don't count - if (path === '.eslintrc.js') { - return false; - } - - const name = basename(path); - if (name.startsWith('setupTests.')) { - return false; - } - if (name.includes('.test.')) { - return false; - } - if (name.includes('.stories.')) { - return false; - } - return true; -} - -async function listChangedFiles(ref) { - if (!ref) { - throw new Error('ref is required'); - } - - const { stdout } = await execFile('git', ['diff', '--name-only', ref]); - return stdout.trim().split(/\r?\n/); -} - -async function listPackages() { - const rootPkg = require(resolvePath(process.cwd(), './package.json')); - if (!rootPkg?.workspaces?.packages) { - throw new Error('No workspaces found in root package.json'); - } - - const pkgs = []; - - // Naive workspace lookup implementation, we can't shell out to yarn here as the implementation embedded in the repo - for (const pkgPath of rootPkg?.workspaces?.packages) { - const readDirRecursive = (dir, parts) => { - const [nextPart] = parts; - - // We've reached the end of the path pattern, check if package.json exists - if (!nextPart) { - try { - const pkg = require(resolvePath(dir, 'package.json')); - pkgs.push({ - path: relativePath(process.cwd(), dir), - name: pkg.name, - }); - } catch { - process.stderr.write(`Failed to read package.json in ${dir}\n`); - } - return; - } - - for (const filePath of fs.readdirSync(dir)) { - if (fs.statSync(resolvePath(dir, filePath)).isDirectory()) { - if (filePath === nextPart || nextPart === '*') { - readDirRecursive(resolvePath(dir, filePath), parts.slice(1)); - } - } - } - }; - - // Split the workspace paths by / and check each directory level recursively - readDirRecursive(process.cwd(), pkgPath.split('/')); - } - - return pkgs; -} - -async function loadChangesets(filePaths) { - const changesets = []; - for (const filePath of filePaths) { - if (!filePath.startsWith('.changeset/') || !filePath.endsWith('.md')) { - continue; - } - try { - const content = await fs.promises.readFile(filePath, 'utf8'); - let lines = content.split(/\r?\n/); - - lines = lines.slice(lines.findIndex(line => line === '---') + 1); - lines = lines.slice( - 0, - lines.findIndex(line => line === '---'), - ); - - const bumps = new Map(); - bumps.toJSON = () => Object.fromEntries(bumps); - for (const line of lines) { - const match = line.match(/^'(.*)': (patch|minor|major)$/); - if (!match) { - throw new Error(`Invalid changeset line: ${line}`); - } - - bumps.set(match[1], match[2]); - } - - changesets.push({ - filePath, - bumps, - }); - } catch (error) { - if (error.code !== 'ENOENT') { - throw error; - } - } - } - - return changesets; -} - -async function listChangedPackages(changedFiles, packages) { - const changedPackageMap = new Map(); - for (const filePath of changedFiles) { - for (const pkg of packages) { - if (filePath.startsWith(`${pkg.path}/`)) { - const pkgPath = relativePath(pkg.path, filePath); - if (!isPublishedPath(pkgPath)) { - break; - } - const entry = changedPackageMap.get(pkg.name); - if (entry) { - entry.files.push(pkgPath); - } else { - const pkgJson = require(resolvePath(pkg.path, 'package.json')); - - changedPackageMap.set(pkg.name, { - ...pkg, - version: pkgJson.version, - isStable: !pkgJson.version.startsWith('0.'), - isPrivate: Boolean(pkgJson.private), - files: [pkgPath], - }); - } - break; - } - } - } - return Array.from(changedPackageMap.values()); -} - -function formatSection(prefix = [], generator, suffix = ['']) { - const lines = Array.from(generator()); - if (lines.length === 0) { - return ''; - } - - return [...[prefix].flat(), ...lines, ...[suffix].flat(), '', ''].join('\n'); -} - -function formatSummary(changedPackages, changesets) { - const changedNames = new Set(changedPackages.map(pkg => pkg.name)); - - let output = ''; - - output += formatSection( - `## Missing Changesets - -The following package(s) are changed by this PR but do not have a changeset: -`, - function* section() { - for (const pkg of changedPackages) { - if (changesets.some(c => c.bumps.get(pkg.name))) { - continue; - } - if (pkg.isPrivate) { - continue; - } - yield `- **${pkg.name}**`; - } - }, - ` -See [CONTRIBUTING.md](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#creating-changesets) for more information about how to add changesets. -`, - ); - - output += formatSection( - `## Unexpected Changesets - -The following changeset(s) reference packages that have not been changed in this PR: -`, - function* section() { - for (const c of changesets) { - const missing = Array.from(c.bumps.keys()).filter( - b => !changedNames.has(b), - ); - if (missing.length > 0) { - yield `- **${c.filePath}**: ${missing.join(', ')}`; - } - } - }, - ` -Note that only changes that affect the published package require changesets, for example changes to tests and storybook stories do not require changesets. -`, - ); - - output += formatSection( - `## Unnecessary Changesets - -The following package(s) are private and do not need a changeset: -`, - function* section() { - for (const pkg of changedPackages) { - if (changesets.some(c => c.bumps.get(pkg.name)) && pkg.isPrivate) { - yield `- **${pkg.name}**`; - } - } - }, - ); - - output += formatSection( - `## Changed Packages - -| Package Name | Package Path | Changeset Bump | Current Version | -|:-------------|:-------------|:--------------:|:----------------|`, - function* section() { - const bumpMap = { - undefined: -1, - patch: 0, - minor: 1, - major: 2, - }; - - for (const pkg of changedPackages) { - const maxBump = - changesets - .map(c => c.bumps.get(pkg.name)) - .reduce( - (max, bump) => (bumpMap[bump] > bumpMap[max] ? bump : max), - undefined, - ) ?? 'none'; - yield `| ${pkg.name} | ${pkg.path} | **${maxBump}** | \`v${pkg.version}\` |`; - } - }, - ); - - return output; -} - -async function main() { - const [diffRef = 'origin/master'] = process.argv.slice(2); - const changedFiles = await listChangedFiles(diffRef); - const packages = await listPackages(); - - const changesets = await loadChangesets(changedFiles); - const changedPackages = await listChangedPackages(changedFiles, packages); - - process.stderr.write( - JSON.stringify( - { - changesets, - changedPackages, - }, - null, - 2, - ), - ); - process.stderr.write('\n'); - - const summary = formatSummary(changedPackages, changesets); - process.stdout.write(summary); -} - -main().catch(error => { - console.error(error.stack); - process.exit(1); -}); From 4120513412ad0ee58242fd36c4092a756cae93fc Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Fri, 17 Feb 2023 10:07:21 -0500 Subject: [PATCH 248/417] adds @backstage/plugin-todo-backend to dependencies for plugin/todo-backend Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- .changeset/bright-kids-raise.md | 5 ++ .changeset/new-waves-sing.md | 6 -- packages/backend-next/src/index.ts | 4 +- plugins/todo-backend/api-report.md | 17 ++-- plugins/todo-backend/package.json | 1 + plugins/todo-backend/src/index.ts | 1 + .../src/lib/TodoReader/TodoScmReader.ts | 30 ++++++- .../todo-backend/src/lib/TodoReader/index.ts | 2 +- plugins/todo-backend/src/plugin.ts | 56 ++---------- .../src/service/TodoReaderService.ts | 52 +++++------ plugins/todo-backend/src/service/index.ts | 8 +- plugins/todo-backend/src/service/plugin.ts | 89 ------------------- 12 files changed, 78 insertions(+), 193 deletions(-) create mode 100644 .changeset/bright-kids-raise.md delete mode 100644 .changeset/new-waves-sing.md delete mode 100644 plugins/todo-backend/src/service/plugin.ts diff --git a/.changeset/bright-kids-raise.md b/.changeset/bright-kids-raise.md new file mode 100644 index 0000000000..e0d69e0c71 --- /dev/null +++ b/.changeset/bright-kids-raise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-todo-backend': patch +--- + +todo-backend is now exposed as a plugin which uses the new plugin system diff --git a/.changeset/new-waves-sing.md b/.changeset/new-waves-sing.md deleted file mode 100644 index 124a508bde..0000000000 --- a/.changeset/new-waves-sing.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-todo-backend': minor -'example-backend-next': patch ---- - -Expose the todos-backend plugin using the new system, add the new entrypoint for todos-backend into the experimental backend diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index a2f542afb1..f4979760cf 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -18,12 +18,12 @@ import { catalogPlugin } from '@backstage/plugin-catalog-backend'; import { catalogModuleTemplateKind } from '@backstage/plugin-scaffolder-backend'; import { createBackend } from '@backstage/backend-defaults'; import { appPlugin } from '@backstage/plugin-app-backend'; -import { todosPlugin } from '@backstage/plugin-todo-backend'; +import { todoPlugin } from '@backstage/plugin-todo-backend'; const backend = createBackend(); backend.add(catalogPlugin()); backend.add(catalogModuleTemplateKind()); backend.add(appPlugin({ appPackageName: 'example-app' })); -backend.add(todosPlugin()); +backend.add(todoPlugin()); backend.start(); diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index 7492865ee4..3908d2475b 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -8,9 +8,9 @@ import { CatalogApi } from '@backstage/catalog-client'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import express from 'express'; -import type { HttpRouterService } from '@backstage/backend-plugin-api'; import { Logger } from 'winston'; import { ScmIntegrations } from '@backstage/integration'; +import { ServiceRef } from '@backstage/backend-plugin-api'; import { UrlReader } from '@backstage/backend-common'; // @public (undocumented) @@ -90,6 +90,9 @@ export type TodoParserResult = { lineNumber: number; }; +// @alpha +export const todoPlugin: () => BackendFeature; + // @public (undocumented) export interface TodoReader { readTodos(options: ReadTodosOptions): Promise; @@ -136,6 +139,9 @@ export type TodoScmReaderOptions = { filePathFilter?: (filePath: string) => boolean; }; +// @alpha (undocumented) +export const todoScmReaderRef: ServiceRef; + // @public (undocumented) export interface TodoService { // (undocumented) @@ -146,13 +152,4 @@ export interface TodoService { }, ): Promise; } - -// @alpha (undocumented) -export const todosPlugin: () => BackendFeature; - -// @alpha (undocumented) -export type TodosPluginDependencies = { - todoReader: TodoService; - http: HttpRouterService; -}; ``` diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 6a3b22aab4..51c3f8ede8 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -30,6 +30,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", diff --git a/plugins/todo-backend/src/index.ts b/plugins/todo-backend/src/index.ts index 973c91df44..b1654327d6 100644 --- a/plugins/todo-backend/src/index.ts +++ b/plugins/todo-backend/src/index.ts @@ -22,3 +22,4 @@ export * from './lib'; export * from './service'; +export * from './plugin'; diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts index 2696f0d54b..d364316ae1 100644 --- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts +++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { UrlReader } from '@backstage/backend-common'; +import { loggerToWinstonLogger, UrlReader } from '@backstage/backend-common'; import { ScmIntegrations } from '@backstage/integration'; import { Logger } from 'winston'; @@ -28,6 +28,11 @@ import { import { Config } from '@backstage/config'; import { createTodoParser } from './createTodoParser'; import path from 'path'; +import { + coreServices, + createServiceFactory, + createServiceRef, +} from '@backstage/backend-plugin-api'; const excludedExtensions = [ '.png', @@ -167,3 +172,26 @@ export class TodoScmReader implements TodoReader { return { result: { items: todos }, etag: tree.etag }; } } + +/** + * @alpha + */ +export const todoScmReaderRef = createServiceRef({ + id: 'todoScmReaderFactory', + defaultFactory: async service => + createServiceFactory({ + service, + deps: { + reader: coreServices.urlReader, + config: coreServices.config, + logger: coreServices.logger, + }, + factory: async ({ reader, config, logger }) => { + const winstonLogger = loggerToWinstonLogger(logger); + return TodoScmReader.fromConfig(config, { + logger: winstonLogger, + reader, + }); + }, + }), +}); diff --git a/plugins/todo-backend/src/lib/TodoReader/index.ts b/plugins/todo-backend/src/lib/TodoReader/index.ts index d0537861da..a56d5805d5 100644 --- a/plugins/todo-backend/src/lib/TodoReader/index.ts +++ b/plugins/todo-backend/src/lib/TodoReader/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export { TodoScmReader } from './TodoScmReader'; +export { TodoScmReader, todoScmReaderRef } from './TodoScmReader'; export type { TodoScmReaderOptions } from './TodoScmReader'; export { createTodoParser } from './createTodoParser'; export type { TodoParserOptions } from './createTodoParser'; diff --git a/plugins/todo-backend/src/plugin.ts b/plugins/todo-backend/src/plugin.ts index 49e8d354b1..cb25d3ddf0 100644 --- a/plugins/todo-backend/src/plugin.ts +++ b/plugins/todo-backend/src/plugin.ts @@ -18,23 +18,15 @@ import { createBackendPlugin, coreServices, } from '@backstage/backend-plugin-api'; -import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; -import { InputError } from '@backstage/errors'; -import express, { Router } from 'express'; -import { - getBearerToken, - parseFilterParam, - parseIntegerParam, - parseOrderByParam, -} from './lib/utils'; + import { todoReaderServiceRef } from './service/TodoReaderService'; -import { TODO_FIELDS } from './service/types'; +import { createRouter } from './service/router'; /** * The Todos plugin is responsible for aggregating todo comments within source. * @alpha */ -export const todosPlugin = createBackendPlugin({ +export const todoPlugin = createBackendPlugin({ pluginId: 'todo-backend', register(env) { env.registerInit({ @@ -43,43 +35,11 @@ export const todosPlugin = createBackendPlugin({ http: coreServices.httpRouter, }, async init({ http, todoReader }) { - const router = Router(); - router.use(express.json()); - - router.get('/v1/todos', async (req, res) => { - const offset = parseIntegerParam(req.query.offset, 'offset query'); - const limit = parseIntegerParam(req.query.limit, 'limit query'); - const orderBy = parseOrderByParam(req.query.orderBy, TODO_FIELDS); - const filters = parseFilterParam(req.query.filter, TODO_FIELDS); - - const entityRef = req.query.entity; - if (entityRef && typeof entityRef !== 'string') { - throw new InputError(`entity query must be a string`); - } - let entity: CompoundEntityRef | undefined = undefined; - if (entityRef) { - try { - entity = parseEntityRef(entityRef); - } catch (error) { - throw new InputError(`Invalid entity ref, ${error}`); - } - } - - const todos = await todoReader.listTodos( - { - entity, - offset, - limit, - orderBy, - filters, - }, - { - token: getBearerToken(req.headers.authorization), - }, - ); - res.json(todos); - }); - http.use(router); + http.use( + await createRouter({ + todoService: todoReader, + }), + ); }, }); }, diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index 93908c0f9f..b3ed793d38 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -20,15 +20,15 @@ import { getEntitySourceLocation, stringifyEntityRef, } from '@backstage/catalog-model'; -import { TodoReader, TodoScmReader } from '../lib'; -import { ListTodosRequest, ListTodosResponse, TodoService } from './types'; import { - coreServices, createServiceFactory, createServiceRef, + ServiceRef, } from '@backstage/backend-plugin-api'; import { catalogServiceRef } from '@backstage/plugin-catalog-node'; -import { loggerToWinstonLogger } from '@backstage/backend-common'; + +import { TodoReader, todoScmReaderRef } from '../lib'; +import { ListTodosRequest, ListTodosResponse, TodoService } from './types'; const DEFAULT_DEFAULT_PAGE_SIZE = 10; const DEFAULT_MAX_PAGE_SIZE = 50; @@ -138,28 +138,22 @@ export class TodoReaderService implements TodoService { } } -export const todoReaderServiceRef = createServiceRef({ - id: 'todo-client', - defaultFactory: async service => - createServiceFactory({ - service, - deps: { - catalogApi: catalogServiceRef, - logger: coreServices.logger, - reader: coreServices.urlReader, - config: coreServices.config, - }, - async factory({ catalogApi, logger, reader, config }) { - const winstonLogger = loggerToWinstonLogger(logger); - const todoReader = TodoScmReader.fromConfig(config, { - reader: reader, - logger: winstonLogger, - }); - return new TodoReaderService({ - catalogClient: catalogApi, - todoReader, - // TODO: override defaults here - }); - }, - }), -}); +export const todoReaderServiceRef: ServiceRef = + createServiceRef({ + id: 'todo.client', + defaultFactory: async service => + createServiceFactory({ + service, + deps: { + catalogApi: catalogServiceRef, + todoReader: todoScmReaderRef, + }, + async factory({ catalogApi, todoReader }) { + const todoReaderService = new TodoReaderService({ + catalogClient: catalogApi, + todoReader, + }); + return todoReaderService; + }, + }), + }); diff --git a/plugins/todo-backend/src/service/index.ts b/plugins/todo-backend/src/service/index.ts index 89a6939cda..380d95dbe1 100644 --- a/plugins/todo-backend/src/service/index.ts +++ b/plugins/todo-backend/src/service/index.ts @@ -16,12 +16,6 @@ export { createRouter } from './router'; export type { RouterOptions } from './router'; -export type { - TodoService, - ListTodosRequest, - ListTodosResponse, - TodosPluginDependencies, -} from './types'; +export type { TodoService, ListTodosRequest, ListTodosResponse } from './types'; export { TodoReaderService } from './TodoReaderService'; export type { TodoReaderServiceOptions } from './TodoReaderService'; -export { todosPlugin } from './plugin'; diff --git a/plugins/todo-backend/src/service/plugin.ts b/plugins/todo-backend/src/service/plugin.ts deleted file mode 100644 index 6c5fd3bf6c..0000000000 --- a/plugins/todo-backend/src/service/plugin.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2023 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - createBackendPlugin, - coreServices, -} from '@backstage/backend-plugin-api'; -import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; -import { InputError } from '@backstage/errors'; -import express, { Router } from 'express'; -import { - getBearerToken, - parseFilterParam, - parseIntegerParam, - parseOrderByParam, -} from '../lib/utils'; -import { todoReaderServiceRef } from './TodoReaderService'; -import { TODO_FIELDS } from './types'; -import type { TodosPluginDependencies } from './types'; - -const todosPluginInit = async (params: TodosPluginDependencies) => { - const { http, todoReader } = params; - const router = Router(); - router.use(express.json()); - - router.get('/v1/todos', async (req, res) => { - const offset = parseIntegerParam(req.query.offset, 'offset query'); - const limit = parseIntegerParam(req.query.limit, 'limit query'); - const orderBy = parseOrderByParam(req.query.orderBy, TODO_FIELDS); - const filters = parseFilterParam(req.query.filter, TODO_FIELDS); - - const entityRef = req.query.entity; - if (entityRef && typeof entityRef !== 'string') { - throw new InputError(`entity query must be a string`); - } - let entity: CompoundEntityRef | undefined = undefined; - if (entityRef) { - try { - entity = parseEntityRef(entityRef); - } catch (error) { - throw new InputError(`Invalid entity ref, ${error}`); - } - } - - const todos = await todoReader.listTodos( - { - entity, - offset, - limit, - orderBy, - filters, - }, - { - token: getBearerToken(req.headers.authorization), - }, - ); - res.json(todos); - }); - http.use(router); -}; - -/** - * @alpha - */ -export const todosPlugin = createBackendPlugin({ - pluginId: 'todo-backend', - register(env) { - env.registerInit({ - deps: { - todoReader: todoReaderServiceRef, - http: coreServices.httpRouter, - }, - init: todosPluginInit, - }); - }, -}); From bfcac3907c036d740418d8e1aeb59e4cbc686406 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Fri, 17 Feb 2023 10:27:08 -0500 Subject: [PATCH 249/417] update yarn.lock Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- yarn.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn.lock b/yarn.lock index 7d00ad8f19..8404d7958f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8376,6 +8376,7 @@ __metadata: resolution: "@backstage/plugin-todo-backend@workspace:plugins/todo-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" From 9d00cd45586e8fc6afe1e4a41c9722bd6c03573d Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 15:32:06 +0100 Subject: [PATCH 250/417] Set version to 0.0.0 for now Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 059235caf3..8334b14b00 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-octopus-deploy", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", From 95d60d60d4e4f654dc7d2450c9fe4c66d2af485f Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 15:41:10 +0100 Subject: [PATCH 251/417] Don't trust user input Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/src/api/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/octopus-deploy/src/api/index.ts b/plugins/octopus-deploy/src/api/index.ts index dcdd881c10..8a29415dcc 100644 --- a/plugins/octopus-deploy/src/api/index.ts +++ b/plugins/octopus-deploy/src/api/index.ts @@ -117,6 +117,11 @@ export class OctopusDeployClient implements OctopusDeployApi { private async getApiUrl(projectId: string, releaseHistoryCount: number) { const proxyUrl = await this.discoveryApi.getBaseUrl('proxy'); - return `${proxyUrl}${this.proxyPathBase}/projects/${projectId}/progression?releaseHistoryCount=${releaseHistoryCount}`; + const queryParameters = new URLSearchParams({ + releaseHistoryCount: releaseHistoryCount.toString(), + }); + return `${proxyUrl}${this.proxyPathBase}/projects/${encodeURIComponent( + projectId, + )}/progression?releaseHistoryCount=${queryParameters}`; } } From 4335910a6186e08fc86a7c56c81f1aa79c495be1 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 15:41:56 +0100 Subject: [PATCH 252/417] Remove unnecessary div Signed-off-by: Jonathan Mezach --- .../src/components/ReleaseTable/ReleaseTable.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx b/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx index be2a68a687..dfda291e1a 100644 --- a/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx +++ b/plugins/octopus-deploy/src/components/ReleaseTable/ReleaseTable.tsx @@ -96,11 +96,7 @@ export const ReleaseTable = ({ error, }: ReleaseTableProps) => { if (error) { - return ( -
    - -
    - ); + return ; } const columns: TableColumn[] = [ From bf072ab2e890867e8fcabd3562f9a1cd915c7b69 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 15:42:31 +0100 Subject: [PATCH 253/417] Expose annotation constant in API Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/api-report.md | 3 +++ plugins/octopus-deploy/src/constants.ts | 2 ++ plugins/octopus-deploy/src/index.ts | 2 ++ 3 files changed, 7 insertions(+) diff --git a/plugins/octopus-deploy/api-report.md b/plugins/octopus-deploy/api-report.md index 563e7ebea4..48487c46c9 100644 --- a/plugins/octopus-deploy/api-report.md +++ b/plugins/octopus-deploy/api-report.md @@ -19,6 +19,9 @@ export const EntityOctopusDeployContent: (props: { // @public (undocumented) export const isOctopusDeployAvailable: (entity: Entity) => boolean; +// @public (undocumented) +export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id'; + // @public (undocumented) export interface OctopusDeployApi { // (undocumented) diff --git a/plugins/octopus-deploy/src/constants.ts b/plugins/octopus-deploy/src/constants.ts index 391dacb42c..3bdc48252f 100644 --- a/plugins/octopus-deploy/src/constants.ts +++ b/plugins/octopus-deploy/src/constants.ts @@ -13,4 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** @public */ export const OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION = 'octopus.com/project-id'; diff --git a/plugins/octopus-deploy/src/index.ts b/plugins/octopus-deploy/src/index.ts index f3696853df..e3264efaf0 100644 --- a/plugins/octopus-deploy/src/index.ts +++ b/plugins/octopus-deploy/src/index.ts @@ -20,3 +20,5 @@ export { } from './plugin'; export * from './api'; + +export { OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION } from './constants'; From 2f5f5a742dc581c857f71922e8796c5761f97968 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 15:43:26 +0100 Subject: [PATCH 254/417] Remove commented out code Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/src/plugin.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/plugins/octopus-deploy/src/plugin.ts b/plugins/octopus-deploy/src/plugin.ts index 15bb32c9bd..f2ca924032 100644 --- a/plugins/octopus-deploy/src/plugin.ts +++ b/plugins/octopus-deploy/src/plugin.ts @@ -45,17 +45,6 @@ export const octopusDeployPlugin = createPlugin({ ], }); -/* -export const OctopusDeployPage = octopusDeployPlugin.provide( - createRoutableExtension({ - name: 'OctopusDeployPage', - component: () => - import('./components/ExampleComponent').then(m => m.ExampleComponent), - mountPoint: rootRouteRef, - }), -); -*/ - /** @public */ export const EntityOctopusDeployContent = octopusDeployPlugin.provide( createRoutableExtension({ From 0741521aa9480747fb620784c463b5538c12dd58 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 16:03:17 +0100 Subject: [PATCH 255/417] Use constant instead of hardcoded value Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts index 96ac4d19f7..e59a32235f 100644 --- a/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts +++ b/plugins/octopus-deploy/src/utils/getAnnotationFromEntity.ts @@ -22,7 +22,7 @@ export function getAnnotationFromEntity(entity: Entity): string { entity.metadata.annotations?.[OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION]; if (!annotation) { throw new Error( - 'Value for annotation octopus.com/project-id was not found', + `Value for annotation ${OCTOPUS_DEPLOY_PROJECT_ID_ANNOTATION} was not found`, ); } From ec60e69df4514ee63d4a0f8779584d2f4be587b9 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 17:01:46 +0100 Subject: [PATCH 256/417] Use the fetchApi Fix an issue previously introduced Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/src/api/index.ts | 15 ++++++--------- plugins/octopus-deploy/src/plugin.ts | 8 ++++---- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/plugins/octopus-deploy/src/api/index.ts b/plugins/octopus-deploy/src/api/index.ts index 8a29415dcc..c1a2711b09 100644 --- a/plugins/octopus-deploy/src/api/index.ts +++ b/plugins/octopus-deploy/src/api/index.ts @@ -16,7 +16,7 @@ import { createApiRef, DiscoveryApi, - IdentityApi, + FetchApi, } from '@backstage/core-plugin-api'; /** @public */ @@ -58,7 +58,7 @@ const DEFAULT_PROXY_PATH_BASE = '/octopus-deploy'; /** @public */ export type Options = { discoveryApi: DiscoveryApi; - identityApi: IdentityApi; + fetchApi: FetchApi; /** * Path to use for requests via the proxy, defaults to /octopus-deploy */ @@ -76,12 +76,12 @@ export interface OctopusDeployApi { /** @public */ export class OctopusDeployClient implements OctopusDeployApi { private readonly discoveryApi: DiscoveryApi; - private readonly identityApi: IdentityApi; + private readonly fetchApi: FetchApi; private readonly proxyPathBase: string; constructor(options: Options) { this.discoveryApi = options.discoveryApi; - this.identityApi = options.identityApi; + this.fetchApi = options.fetchApi; this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE; } @@ -91,10 +91,7 @@ export class OctopusDeployClient implements OctopusDeployApi { ): Promise { const url = await this.getApiUrl(projectId, releaseHistoryCount); - const { token: idToken } = await this.identityApi.getCredentials(); - const response = await fetch(url, { - headers: idToken ? { Authorization: `Bearer ${idToken}` } : {}, - }); + const response = await this.fetchApi.fetch(url); let responseJson; @@ -122,6 +119,6 @@ export class OctopusDeployClient implements OctopusDeployApi { }); return `${proxyUrl}${this.proxyPathBase}/projects/${encodeURIComponent( projectId, - )}/progression?releaseHistoryCount=${queryParameters}`; + )}/progression?${queryParameters}`; } } diff --git a/plugins/octopus-deploy/src/plugin.ts b/plugins/octopus-deploy/src/plugin.ts index f2ca924032..9365f93bdb 100644 --- a/plugins/octopus-deploy/src/plugin.ts +++ b/plugins/octopus-deploy/src/plugin.ts @@ -23,7 +23,7 @@ import { createPlugin, createRoutableExtension, discoveryApiRef, - identityApiRef, + fetchApiRef, } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; @@ -38,9 +38,9 @@ export const octopusDeployPlugin = createPlugin({ apis: [ createApiFactory({ api: octopusDeployApiRef, - deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef }, - factory: ({ discoveryApi, identityApi }) => - new OctopusDeployClient({ discoveryApi, identityApi }), + deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef }, + factory: ({ discoveryApi, fetchApi }) => + new OctopusDeployClient({ discoveryApi, fetchApi }), }), ], }); From d85821f0a8127aae2c6261212aeb81f6aaacec09 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Fri, 17 Feb 2023 17:15:27 +0100 Subject: [PATCH 257/417] Removed options type Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/api-report.md | 15 ++++++--------- plugins/octopus-deploy/src/api/index.ts | 16 +++++----------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/plugins/octopus-deploy/api-report.md b/plugins/octopus-deploy/api-report.md index 48487c46c9..82512ebcef 100644 --- a/plugins/octopus-deploy/api-report.md +++ b/plugins/octopus-deploy/api-report.md @@ -9,7 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; -import { IdentityApi } from '@backstage/core-plugin-api'; +import { FetchApi } from '@backstage/core-plugin-api'; // @public (undocumented) export const EntityOctopusDeployContent: (props: { @@ -36,7 +36,11 @@ export const octopusDeployApiRef: ApiRef; // @public (undocumented) export class OctopusDeployClient implements OctopusDeployApi { - constructor(options: Options); + constructor(options: { + discoveryApi: DiscoveryApi; + fetchApi: FetchApi; + proxyPathBase?: string; + }); // (undocumented) getReleaseProgression( projectId: string, @@ -78,12 +82,5 @@ export type OctopusReleaseProgression = { }; }; -// @public (undocumented) -export type Options = { - discoveryApi: DiscoveryApi; - identityApi: IdentityApi; - proxyPathBase?: string; -}; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/octopus-deploy/src/api/index.ts b/plugins/octopus-deploy/src/api/index.ts index c1a2711b09..9cba49d6c0 100644 --- a/plugins/octopus-deploy/src/api/index.ts +++ b/plugins/octopus-deploy/src/api/index.ts @@ -55,16 +55,6 @@ export const octopusDeployApiRef = createApiRef({ const DEFAULT_PROXY_PATH_BASE = '/octopus-deploy'; -/** @public */ -export type Options = { - discoveryApi: DiscoveryApi; - fetchApi: FetchApi; - /** - * Path to use for requests via the proxy, defaults to /octopus-deploy - */ - proxyPathBase?: string; -}; - /** @public */ export interface OctopusDeployApi { getReleaseProgression( @@ -79,7 +69,11 @@ export class OctopusDeployClient implements OctopusDeployApi { private readonly fetchApi: FetchApi; private readonly proxyPathBase: string; - constructor(options: Options) { + constructor(options: { + discoveryApi: DiscoveryApi; + fetchApi: FetchApi; + proxyPathBase?: string; + }) { this.discoveryApi = options.discoveryApi; this.fetchApi = options.fetchApi; this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE; From bfe350ef4ce20f4f94a37be970f31c395c24669d Mon Sep 17 00:00:00 2001 From: Knut Borchers Date: Sat, 18 Feb 2023 18:02:46 +0100 Subject: [PATCH 258/417] fix: Prevent deletion of non-empty directories Signed-off-by: Knut Borchers --- .changeset/purple-days-film.md | 5 +++++ .../src/stages/publish/helpers.test.ts | 10 ++++++++++ plugins/techdocs-node/src/stages/publish/helpers.ts | 13 +++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 .changeset/purple-days-film.md diff --git a/.changeset/purple-days-film.md b/.changeset/purple-days-film.md new file mode 100644 index 0000000000..09d760c33e --- /dev/null +++ b/.changeset/purple-days-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-node': patch +--- + +Fixed bug that prevented deletion of stale files when non-empty directories where tried to be deleted as well. diff --git a/plugins/techdocs-node/src/stages/publish/helpers.test.ts b/plugins/techdocs-node/src/stages/publish/helpers.test.ts index fa934d6dd9..7b303b3bf5 100644 --- a/plugins/techdocs-node/src/stages/publish/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/publish/helpers.test.ts @@ -158,6 +158,16 @@ describe('getStaleFiles', () => { expect(staleFiles).toHaveLength(1); expect(staleFiles).toEqual(expect.arrayContaining(['stale_file.png'])); }); + + it('should not return directories as stale files if they are parent directories of new files', () => { + const oldFiles = [...defaultFiles, 'default/Component/backstage/foo']; + const newFiles = [ + ...defaultFiles, + 'default/Component/backstage/foo/bar/index.html', + ]; + const staleFiles = getStaleFiles(newFiles, oldFiles); + expect(staleFiles).toHaveLength(0); + }); }); describe('getCloudPathForLocalPath', () => { diff --git a/plugins/techdocs-node/src/stages/publish/helpers.ts b/plugins/techdocs-node/src/stages/publish/helpers.ts index decefae187..0b9384dba3 100644 --- a/plugins/techdocs-node/src/stages/publish/helpers.ts +++ b/plugins/techdocs-node/src/stages/publish/helpers.ts @@ -169,8 +169,21 @@ export const getStaleFiles = ( oldFiles: string[], ): string[] => { const staleFiles = new Set(oldFiles); + const removedParentDirs = new Set(); newFiles.forEach(newFile => { staleFiles.delete(newFile); + + // We have to traverse through the directory hierarchy of a new file and + // ensure that we won't try to delete one of the parent directories. + let parentDir = newFile.substring(0, newFile.lastIndexOf('/')); + while ( + !removedParentDirs.has(parentDir) && + parentDir.length >= newFile.indexOf('/') + ) { + staleFiles.delete(parentDir); + removedParentDirs.add(parentDir); + parentDir = parentDir.substring(0, parentDir.lastIndexOf('/')); + } }); return Array.from(staleFiles); }; From d41a2b74282c13ef0e825025c121da11a2cf9ef5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 19 Feb 2023 01:32:46 +0000 Subject: [PATCH 259/417] fix(deps): update dependency @roadiehq/backstage-plugin-travis-ci to v2.1.4 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index f322cca29b..dfebd4674b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12971,8 +12971,8 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-travis-ci@npm:^2.0.5": - version: 2.1.3 - resolution: "@roadiehq/backstage-plugin-travis-ci@npm:2.1.3" + version: 2.1.4 + resolution: "@roadiehq/backstage-plugin-travis-ci@npm:2.1.4" dependencies: "@backstage/catalog-model": ^1.1.5 "@backstage/core-components": ^0.12.3 @@ -12992,7 +12992,7 @@ __metadata: react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 8051bd38465f73c1d09c7a88fe86f3c32fcd8d32924d7a5c0100cad0b6fba5e48684dc4b15ebdbbdc8f351c9e05286e1546b0a4499ad1385848e205737354d89 + checksum: 11e2823352c8e0d23ef9d577e8802d33e2c6e92bca0b269228224132f01ddced463436b43891dfd6b9ad4b4f7247291cb293426a899db87292c5500885029c9d languageName: node linkType: hard From 8d2d36509f60088d6038d1912a6e5d0f30617ea3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 19 Feb 2023 02:44:45 +0000 Subject: [PATCH 260/417] fix(deps): update dependency @tanstack/react-query to v4.24.9 Signed-off-by: Renovate Bot --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index dfebd4674b..f454914478 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13631,18 +13631,18 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:4.24.6": - version: 4.24.6 - resolution: "@tanstack/query-core@npm:4.24.6" - checksum: 495dff04f27d72174051f97676fce0fbe322bca966edb7f174f0005a3363ac0300c31eb06255dafa7ee519a430840542379f5ec9f6846903b6bb878e46c33656 +"@tanstack/query-core@npm:4.24.9": + version: 4.24.9 + resolution: "@tanstack/query-core@npm:4.24.9" + checksum: 7b84e960d82c046c9eef6083cbc13b21c2ed8552fe8a5f092a66ca2586af66b770ca71ad838135ef49ac8b990e5f85d34a1d8b8de13fffb3abb0fb780a64a532 languageName: node linkType: hard "@tanstack/react-query@npm:^4.1.3": - version: 4.24.6 - resolution: "@tanstack/react-query@npm:4.24.6" + version: 4.24.9 + resolution: "@tanstack/react-query@npm:4.24.9" dependencies: - "@tanstack/query-core": 4.24.6 + "@tanstack/query-core": 4.24.9 use-sync-external-store: ^1.2.0 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -13653,7 +13653,7 @@ __metadata: optional: true react-native: optional: true - checksum: 250bc2cba8dd7da61680a8e360fac87ee057d079ee3be950c76dbc063f941119817634857c1cb0d9b12042dd5d4fbe847c02af5dfb89ae8daa0f9339f87ad605 + checksum: 409c945c5043d11fa2f3c219254df5b0505bdf7d9dc94821f5db495d87a38fe27e0a373144446cef42fc829d1449a64e3fa873adf37e8abe15562e5832d59516 languageName: node linkType: hard From b3b73ce486cb2db8665ab6eba5e7c759b7116970 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 19 Feb 2023 03:38:17 +0000 Subject: [PATCH 261/417] fix(deps): update dependency @types/passport to v1.0.12 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index f454914478..eb2240ecbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15140,11 +15140,11 @@ __metadata: linkType: hard "@types/passport@npm:*, @types/passport@npm:^1.0.3": - version: 1.0.11 - resolution: "@types/passport@npm:1.0.11" + version: 1.0.12 + resolution: "@types/passport@npm:1.0.12" dependencies: "@types/express": "*" - checksum: 7fea92aeb0d05bd872c17deadc1f1219dbdb23bae1b8f50e1c432ef755bce2b5f3fd60af76c38815f1fbaa047960d3638a4144221c4330457091be1f6e492168 + checksum: 2bce41b248566d8c2aeafcb38f105e3521d42a572e92da9edc5eb669f1b3cb02e5911c9d124191f67d432b677562a885b6ad7f56320c712df1e87ba7619eb8a4 languageName: node linkType: hard From 3d97900cee0ea30fe29d4cd67558707b97cf2dd2 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Sun, 19 Feb 2023 14:46:27 -0500 Subject: [PATCH 262/417] refactor: Export pages directly from index file Signed-off-by: Carlos Esteban Lopez --- .../src/pages/community/_community.tsx | 268 ----------------- microsite-next/src/pages/community/index.tsx | 269 +++++++++++++++++- microsite-next/src/pages/demos/_demos.tsx | 204 ------------- microsite-next/src/pages/demos/index.tsx | 205 ++++++++++++- microsite-next/src/pages/plugins/_plugins.tsx | 90 ------ microsite-next/src/pages/plugins/index.tsx | 86 +++++- 6 files changed, 557 insertions(+), 565 deletions(-) delete mode 100644 microsite-next/src/pages/community/_community.tsx delete mode 100644 microsite-next/src/pages/demos/_demos.tsx delete mode 100644 microsite-next/src/pages/plugins/_plugins.tsx diff --git a/microsite-next/src/pages/community/_community.tsx b/microsite-next/src/pages/community/_community.tsx deleted file mode 100644 index 082d656454..0000000000 --- a/microsite-next/src/pages/community/_community.tsx +++ /dev/null @@ -1,268 +0,0 @@ -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { BannerSection } from '@site/src/components/banner-section/banner-section'; -import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; -import Layout from '@theme/Layout'; -import { clsx } from 'clsx'; -import React from 'react'; - -import communityStyles from './community.module.scss'; -import { ContentBlock } from '../../components/content-block/content-block'; - -interface ICollectionItem { - title?: string; - content: React.ReactNode; - label: string; - link: string; -} - -export function Community() { - const { siteConfig } = useDocusaurusContext(); - - //#region Collection Data - const communityListItems: ICollectionItem[] = [ - { - content: 'Chat and get support on our', - label: 'Discord', - link: 'https://discord.gg/MUpMjP2', - }, - { - content: 'Get into contributing with the', - label: 'Good First Issues', - link: 'https://github.com/backstage/backstage/contribute', - }, - { - content: 'Subscribe to the', - label: 'Community newsletter', - link: 'https://info.backstage.spotify.com/newsletter_subscribe', - }, - { - content: 'Join the', - label: 'Twitter community', - link: 'https://twitter.com/i/communities/1494019781716062215', - }, - ]; - - const officialInitiatives: ICollectionItem[] = [ - { - title: 'Community sessions', - content: - 'Maintainers and adopters meet monthly to share updates, demos, and ideas. Yep, all sessions are recorded!', - link: '/on-demand', - label: 'Join a session', - }, - { - title: 'Newsletter', - content: - "The official monthly Backstage newsletter. Don't miss the latest news from your favorite project!", - link: 'https://info.backstage.spotify.com/newsletter_subscribe', - label: 'Subscribe', - }, - { - title: 'Contributor Spotlight', - content: - "A recognition for valuable community work. Nominate contributing members for their efforts! We'll put them in the spotlight ❤️", - link: '/nominate', - label: 'Nominate now', - }, - ]; - - const communityInitiatives: ICollectionItem[] = [ - { - title: 'Open Mic Meetup', - content: ( - <> - A casual get together of Backstage users sharing their experiences and - helping each other. Hosted by{' '} - Roadie.io and{' '} - Frontside Software. - - ), - link: 'https://backstage-openmic.com/', - label: 'Learn more', - }, - { - title: 'Backstage Weekly Newsletter', - content: ( - <> - A weekly newsletter with news, updates and things community from your - friends at Roadie.io. - - ), - link: 'https://roadie.io/backstage-weekly/', - label: 'Learn more', - }, - ]; - - const trainingNCertifications: ICollectionItem[] = [ - { - title: 'Open Mic Meetup', - content: - 'This is a course produced and curated by the Linux Foundation. This course introduces you to Backstage and how to get started with the project.', - link: 'https://training.linuxfoundation.org/training/introduction-to-backstage-developer-portals-made-easy-lfs142x/', - label: 'Learn more', - }, - ]; - - const partners: { name: string; url: string; logo: string }[] = [ - { - name: 'Frontside Software', - url: 'https://frontside.com/backstage/', - logo: 'img/partner-logo-frontside.png', - }, - { - name: 'Roadie', - url: 'https://roadie.io/', - logo: 'img/partner-logo-roadie.png', - }, - { - name: 'ThoughtWorks', - url: 'https://www.thoughtworks.com', - logo: 'img/partner-logo-thoughtworks.png', - }, - { - name: 'VMWare', - url: 'https://www.vmware.com', - logo: 'img/partner-logo-vmware.png', - }, - ]; - //#endregion - - return ( - -
    - - - Backstage Community} - > - Join the vibrant community around Backstage through social media - and different meetups. To ensure that you have a welcoming - environment, we follow the - - {' '} - CNCF Code of Conduct{' '} - - in everything we do. - - - -
      - {communityListItems.map( - ({ content: text, link, label }, index) => ( -
    • -

      - {text} {label} -

      -
    • - ), - )} -
    -
    -
    -
    - - - -

    Offical Backstage initiatives

    - -

    Stay tuned to the latest developments

    - - } - > - {officialInitiatives.map( - ({ title, content, link, label }, index) => ( - - {content} - - ), - )} -
    -
    - - - Community initiatives} - > - {communityInitiatives.map( - ({ title, content, link, label }, index) => ( - -

    {content}

    -
    - ), - )} -
    -
    - - - Trainings and Certifications - } - > - {trainingNCertifications.map( - ({ title, content, link, label }, index) => ( - -

    {content}

    -
    - ), - )} -
    -
    - - - Commercial Partners} - > - {partners.map(({ name, url, logo }, index) => ( -
    - - {name} - -
    - ))} -
    -
    -
    -
    - ); -} diff --git a/microsite-next/src/pages/community/index.tsx b/microsite-next/src/pages/community/index.tsx index 474352685a..595e2b01c8 100644 --- a/microsite-next/src/pages/community/index.tsx +++ b/microsite-next/src/pages/community/index.tsx @@ -1,3 +1,270 @@ -import { Community } from './_community'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import { BannerSection } from '@site/src/components/banner-section/banner-section'; +import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; +import Layout from '@theme/Layout'; +import { clsx } from 'clsx'; +import React from 'react'; + +import { ContentBlock } from '../../components/content-block/content-block'; +import communityStyles from './community.module.scss'; + +interface ICollectionItem { + title?: string; + content: React.ReactNode; + label: string; + link: string; +} + +const Community = () => { + const { siteConfig } = useDocusaurusContext(); + + //#region Collection Data + const communityListItems: ICollectionItem[] = [ + { + content: 'Chat and get support on our', + label: 'Discord', + link: 'https://discord.gg/MUpMjP2', + }, + { + content: 'Get into contributing with the', + label: 'Good First Issues', + link: 'https://github.com/backstage/backstage/contribute', + }, + { + content: 'Subscribe to the', + label: 'Community newsletter', + link: 'https://info.backstage.spotify.com/newsletter_subscribe', + }, + { + content: 'Join the', + label: 'Twitter community', + link: 'https://twitter.com/i/communities/1494019781716062215', + }, + ]; + + const officialInitiatives: ICollectionItem[] = [ + { + title: 'Community sessions', + content: + 'Maintainers and adopters meet monthly to share updates, demos, and ideas. Yep, all sessions are recorded!', + link: '/on-demand', + label: 'Join a session', + }, + { + title: 'Newsletter', + content: + "The official monthly Backstage newsletter. Don't miss the latest news from your favorite project!", + link: 'https://info.backstage.spotify.com/newsletter_subscribe', + label: 'Subscribe', + }, + { + title: 'Contributor Spotlight', + content: + "A recognition for valuable community work. Nominate contributing members for their efforts! We'll put them in the spotlight ❤️", + link: '/nominate', + label: 'Nominate now', + }, + ]; + + const communityInitiatives: ICollectionItem[] = [ + { + title: 'Open Mic Meetup', + content: ( + <> + A casual get together of Backstage users sharing their experiences and + helping each other. Hosted by{' '} + Roadie.io and{' '} + Frontside Software. + + ), + link: 'https://backstage-openmic.com/', + label: 'Learn more', + }, + { + title: 'Backstage Weekly Newsletter', + content: ( + <> + A weekly newsletter with news, updates and things community from your + friends at Roadie.io. + + ), + link: 'https://roadie.io/backstage-weekly/', + label: 'Learn more', + }, + ]; + + const trainingNCertifications: ICollectionItem[] = [ + { + title: 'Open Mic Meetup', + content: + 'This is a course produced and curated by the Linux Foundation. This course introduces you to Backstage and how to get started with the project.', + link: 'https://training.linuxfoundation.org/training/introduction-to-backstage-developer-portals-made-easy-lfs142x/', + label: 'Learn more', + }, + ]; + + const partners: { name: string; url: string; logo: string }[] = [ + { + name: 'Frontside Software', + url: 'https://frontside.com/backstage/', + logo: 'img/partner-logo-frontside.png', + }, + { + name: 'Roadie', + url: 'https://roadie.io/', + logo: 'img/partner-logo-roadie.png', + }, + { + name: 'ThoughtWorks', + url: 'https://www.thoughtworks.com', + logo: 'img/partner-logo-thoughtworks.png', + }, + { + name: 'VMWare', + url: 'https://www.vmware.com', + logo: 'img/partner-logo-vmware.png', + }, + ]; + //#endregion + + return ( + +
    + + + Backstage Community} + > + Join the vibrant community around Backstage through social media + and different meetups. To ensure that you have a welcoming + environment, we follow the + + {' '} + CNCF Code of Conduct{' '} + + in everything we do. + + + +
      + {communityListItems.map( + ({ content: text, link, label }, index) => ( +
    • +

      + {text} {label} +

      +
    • + ), + )} +
    +
    +
    +
    + + + +

    Offical Backstage initiatives

    + +

    Stay tuned to the latest developments

    + + } + > + {officialInitiatives.map( + ({ title, content, link, label }, index) => ( + + {content} + + ), + )} +
    +
    + + + Community initiatives} + > + {communityInitiatives.map( + ({ title, content, link, label }, index) => ( + +

    {content}

    +
    + ), + )} +
    +
    + + + Trainings and Certifications + } + > + {trainingNCertifications.map( + ({ title, content, link, label }, index) => ( + +

    {content}

    +
    + ), + )} +
    +
    + + + Commercial Partners} + > + {partners.map(({ name, url, logo }, index) => ( +
    + + {name} + +
    + ))} +
    +
    +
    +
    + ); +}; export default Community; diff --git a/microsite-next/src/pages/demos/_demos.tsx b/microsite-next/src/pages/demos/_demos.tsx deleted file mode 100644 index 65c04c5282..0000000000 --- a/microsite-next/src/pages/demos/_demos.tsx +++ /dev/null @@ -1,204 +0,0 @@ -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { BannerSection } from '@site/src/components/banner-section/banner-section'; -import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; -import { ContentBlock } from '@site/src/components/content-block/content-block'; -import Layout from '@theme/Layout'; -import { clsx } from 'clsx'; -import React from 'react'; - -import demosStyles from './demos.module.scss'; - -interface IDemoItem { - title: string; - content: React.ReactNode; - actionItemLink?: string; - media: { - type: 'image' | 'video'; - link: string; - }; -} - -export function Demos() { - const { siteConfig } = useDocusaurusContext(); - - //#region Collection Data - const demoItems: IDemoItem[] = [ - { - title: 'See us in action', - content: ( - <> -

    - Watch the videos below to get an introduction to Backstage and to - see how we use different plugins to customize{' '} - - our internal version of Backstage at Spotify - -

    -

    - To see how other companies have already started using Backstage, - watch these presentations from{' '} - Expedia,{' '} - Zalando, and{' '} - TELUS. For - more, join our{' '} - - Community Sessions - -

    -

    - To explore the UI and basic features of Backstage firsthand, go to:{' '} - demo.backstage.io. (Tip:{' '} - click “All” to view all the example components in the software - catalog.) -

    - - ), - media: { - type: 'image', - link: `${siteConfig.baseUrl}img/demo-screen.png`, - }, - }, - { - title: 'Introduction to Backstage', - content: - 'Backstage is an open source platform for building developer portals. We’ve been using our homegrown version at Spotify for years — so it’s already packed with features. (We have over 120 internal plugins, built by 60 different teams.) In this live demo recording, Stefan Ålund, product manager for Backstage, tells the origin story of Backstage and gives you a tour of how we use it here at Spotify.', - actionItemLink: 'https://www.youtube.com/watch?v=1XtJ5FAOjPk', - media: { - type: 'video', - link: 'https://www.youtube.com/embed/1XtJ5FAOjPk', - }, - }, - { - title: 'Control cloud costs', - content: ( - <> -

    - How do you control cloud costs while maintaining the speed and - independence of your development teams? With the{' '} - Cost Insights plugin{' '} - for Backstage, managing cloud costs becomes just another part of an - engineer’s daily development process. They get a clear view of their - spending — and can decide for themselves how they want to optimize - it. Learn more about the{' '} - - Cost Insights plugin - -

    - - ), - actionItemLink: 'https://youtu.be/YLAd5hdXR_Q', - media: { - type: 'video', - link: 'https://www.youtube.com/embed/YLAd5hdXR_Q', - }, - }, - { - title: 'Make documentation easy', - content: ( - <> -

    - Documentation! Everyone needs it, no one wants to create it, and no - one can ever find it. Backstage follows a “docs like code” approach: - you write documentation in Markdown files right alongside your code. - This makes documentation easier to create, maintain, find — and, you - know, actually use. This demo video showcases Spotify’s internal - version of TechDocs. Learn more about{' '} - - TechDocs - - . -

    - - ), - actionItemLink: 'https://youtu.be/mOLCgdPw1iA', - media: { - type: 'video', - link: 'https://www.youtube.com/embed/mOLCgdPw1iA', - }, - }, - { - title: 'Manage your tech health', - content: - 'Instead of manually updating a spreadsheet, what if you had a beautiful dashboard that could give you an instant, interactive picture of your entire org’s tech stack? That’s how we do it at Spotify. With our Tech Insights plugin for Backstage, anyone at Spotify can see which version of which software anyone else at Spotify is using — and a whole a lot more. From managing migrations to fighting tech entropy, Backstage makes managing our tech health actually kind of pleasant.', - actionItemLink: - 'https://www.youtube.com/watch?v=K3xz6VAbgH8&list=PLf1KFlSkDLIBtMGwRDfaVlKMqTMrjD2yO&index=6', - media: { - type: 'video', - link: 'https://www.youtube.com/embed/K3xz6VAbgH8', - }, - }, - { - title: 'Create a microservice', - content: - 'You’re a Spotify engineer about to build a new microservice (or any component) using Spring Boot. Where do you start? Search for a quick start guide online? Create an empty repo on GitHub? Copy and paste an old project? Nope. Just go to Backstage, and you’ll be up and running in two minutes — with a “Hello World” app, CI, and documentation all automatically set up and configured in a standardized way.', - actionItemLink: 'https://www.youtube.com/watch?v=U1iwe3L5pzc', - media: { - type: 'video', - link: 'https://www.youtube.com/embed/U1iwe3L5pzc', - }, - }, - { - title: 'Search all your services', - content: - 'All of Spotify’s services are automatically indexed in Backstage. So our engineers can stop playing detective — no more spamming Slack channels asking if anyone knows who owns a particular service and where you can find its API, only to discover that the owner went on sabbatical three months ago and you have to hunt them down on a mountain in Tibet where they’re on a 12-day silent meditation retreat. At Spotify, anyone can always find anyone else’s service, inspect its APIs, and contact its current owner — all with one search.', - actionItemLink: 'https://www.youtube.com/watch?v=vcDL9tOv7Eo', - media: { - type: 'video', - link: 'https://www.youtube.com/embed/vcDL9tOv7Eo', - }, - }, - { - title: 'Manage data pipelines', - content: - 'We manage a lot of data pipelines (also known as workflows) here at Spotify. So, of course, we made a great workflows plugin for our version of Backstage. All our workflow tools — including a scheduler, log inspector, data lineage graph, and configurable alerts — are integrated into one simple interface.', - actionItemLink: 'https://www.youtube.com/watch?v=rH46MLNZIPM', - media: { - type: 'video', - link: 'https://www.youtube.com/embed/rH46MLNZIPM', - }, - }, - ]; - //#endregion - - return ( - -
    - {demoItems.map((demoItem, index) => ( - - - {demoItem.title}} - actionButtons={[ - { - link: demoItem.actionItemLink, - label: 'WATCH NOW', - }, - ]} - > - {demoItem.content} - - -
    - {demoItem.media.type === 'image' ? ( - {demoItem.title} - ) : ( - - )} -
    -
    -
    - ))} -
    -
    - ); -} diff --git a/microsite-next/src/pages/demos/index.tsx b/microsite-next/src/pages/demos/index.tsx index db9298c0c6..d112ca2c49 100644 --- a/microsite-next/src/pages/demos/index.tsx +++ b/microsite-next/src/pages/demos/index.tsx @@ -1,3 +1,206 @@ -import { Demos } from './_demos'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import { BannerSection } from '@site/src/components/banner-section/banner-section'; +import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; +import { ContentBlock } from '@site/src/components/content-block/content-block'; +import Layout from '@theme/Layout'; +import { clsx } from 'clsx'; +import React from 'react'; + +import demosStyles from './demos.module.scss'; + +interface IDemoItem { + title: string; + content: React.ReactNode; + actionItemLink?: string; + media: { + type: 'image' | 'video'; + link: string; + }; +} + +const Demos = () => { + const { siteConfig } = useDocusaurusContext(); + + //#region Collection Data + const demoItems: IDemoItem[] = [ + { + title: 'See us in action', + content: ( + <> +

    + Watch the videos below to get an introduction to Backstage and to + see how we use different plugins to customize{' '} + + our internal version of Backstage at Spotify + +

    +

    + To see how other companies have already started using Backstage, + watch these presentations from{' '} + Expedia,{' '} + Zalando, and{' '} + TELUS. For + more, join our{' '} + + Community Sessions + +

    +

    + To explore the UI and basic features of Backstage firsthand, go to:{' '} + demo.backstage.io. (Tip:{' '} + click “All” to view all the example components in the software + catalog.) +

    + + ), + media: { + type: 'image', + link: `${siteConfig.baseUrl}img/demo-screen.png`, + }, + }, + { + title: 'Introduction to Backstage', + content: + 'Backstage is an open source platform for building developer portals. We’ve been using our homegrown version at Spotify for years — so it’s already packed with features. (We have over 120 internal plugins, built by 60 different teams.) In this live demo recording, Stefan Ålund, product manager for Backstage, tells the origin story of Backstage and gives you a tour of how we use it here at Spotify.', + actionItemLink: 'https://www.youtube.com/watch?v=1XtJ5FAOjPk', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/1XtJ5FAOjPk', + }, + }, + { + title: 'Control cloud costs', + content: ( + <> +

    + How do you control cloud costs while maintaining the speed and + independence of your development teams? With the{' '} + Cost Insights plugin{' '} + for Backstage, managing cloud costs becomes just another part of an + engineer’s daily development process. They get a clear view of their + spending — and can decide for themselves how they want to optimize + it. Learn more about the{' '} + + Cost Insights plugin + +

    + + ), + actionItemLink: 'https://youtu.be/YLAd5hdXR_Q', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/YLAd5hdXR_Q', + }, + }, + { + title: 'Make documentation easy', + content: ( + <> +

    + Documentation! Everyone needs it, no one wants to create it, and no + one can ever find it. Backstage follows a “docs like code” approach: + you write documentation in Markdown files right alongside your code. + This makes documentation easier to create, maintain, find — and, you + know, actually use. This demo video showcases Spotify’s internal + version of TechDocs. Learn more about{' '} + + TechDocs + + . +

    + + ), + actionItemLink: 'https://youtu.be/mOLCgdPw1iA', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/mOLCgdPw1iA', + }, + }, + { + title: 'Manage your tech health', + content: + 'Instead of manually updating a spreadsheet, what if you had a beautiful dashboard that could give you an instant, interactive picture of your entire org’s tech stack? That’s how we do it at Spotify. With our Tech Insights plugin for Backstage, anyone at Spotify can see which version of which software anyone else at Spotify is using — and a whole a lot more. From managing migrations to fighting tech entropy, Backstage makes managing our tech health actually kind of pleasant.', + actionItemLink: + 'https://www.youtube.com/watch?v=K3xz6VAbgH8&list=PLf1KFlSkDLIBtMGwRDfaVlKMqTMrjD2yO&index=6', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/K3xz6VAbgH8', + }, + }, + { + title: 'Create a microservice', + content: + 'You’re a Spotify engineer about to build a new microservice (or any component) using Spring Boot. Where do you start? Search for a quick start guide online? Create an empty repo on GitHub? Copy and paste an old project? Nope. Just go to Backstage, and you’ll be up and running in two minutes — with a “Hello World” app, CI, and documentation all automatically set up and configured in a standardized way.', + actionItemLink: 'https://www.youtube.com/watch?v=U1iwe3L5pzc', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/U1iwe3L5pzc', + }, + }, + { + title: 'Search all your services', + content: + 'All of Spotify’s services are automatically indexed in Backstage. So our engineers can stop playing detective — no more spamming Slack channels asking if anyone knows who owns a particular service and where you can find its API, only to discover that the owner went on sabbatical three months ago and you have to hunt them down on a mountain in Tibet where they’re on a 12-day silent meditation retreat. At Spotify, anyone can always find anyone else’s service, inspect its APIs, and contact its current owner — all with one search.', + actionItemLink: 'https://www.youtube.com/watch?v=vcDL9tOv7Eo', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/vcDL9tOv7Eo', + }, + }, + { + title: 'Manage data pipelines', + content: + 'We manage a lot of data pipelines (also known as workflows) here at Spotify. So, of course, we made a great workflows plugin for our version of Backstage. All our workflow tools — including a scheduler, log inspector, data lineage graph, and configurable alerts — are integrated into one simple interface.', + actionItemLink: 'https://www.youtube.com/watch?v=rH46MLNZIPM', + media: { + type: 'video', + link: 'https://www.youtube.com/embed/rH46MLNZIPM', + }, + }, + ]; + //#endregion + + return ( + +
    + {demoItems.map((demoItem, index) => ( + + + {demoItem.title}} + actionButtons={[ + { + link: demoItem.actionItemLink, + label: 'WATCH NOW', + }, + ]} + > + {demoItem.content} + + +
    + {demoItem.media.type === 'image' ? ( + {demoItem.title} + ) : ( + + )} +
    +
    +
    + ))} +
    +
    + ); +}; export default Demos; diff --git a/microsite-next/src/pages/plugins/_plugins.tsx b/microsite-next/src/pages/plugins/_plugins.tsx deleted file mode 100644 index 2e165ba60b..0000000000 --- a/microsite-next/src/pages/plugins/_plugins.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import Layout from '@theme/Layout'; -import clsx from 'clsx'; -import React from 'react'; - -import { IPluginData, PluginCard } from './_plugin-card'; -import pluginsStyles from './plugins.module.scss'; - -//#region Plugin data import -const maxDescLength = 160; - -const truncatePluginDescription = (pluginData: IPluginData) => - pluginData.description.length > maxDescLength - ? { - ...pluginData, - description: pluginData.description.slice(0, maxDescLength) + '...', - } - : pluginData; - -const pluginsContext = require.context( - '../../../../microsite/data/plugins', - false, - /\.ya?ml/, -); - -const plugins = pluginsContext.keys().reduce( - (acum, id) => { - const pluginData: IPluginData = pluginsContext(id).default; - - acum[ - pluginData.category === 'Core Feature' ? 'corePlugins' : 'otherPlugins' - ].push(truncatePluginDescription(pluginData)); - - return acum; - }, - { corePlugins: [] as IPluginData[], otherPlugins: [] as IPluginData[] }, -); - -plugins.corePlugins.sort((a, b) => a.order - b.order); -plugins.otherPlugins.sort((a, b) => a.order - b.order); -//#endregion - -export function Plugins() { - const { siteConfig } = useDocusaurusContext(); - - return ( - -
    -
    -
    -

    Plugin Marketplace

    - -

    - Open source plugins that you can add to your Backstage deployment. - Learn how to build a plugin. -

    -
    - - - Add to Marketplace - -
    - -
    - -

    Core Features

    - -
    - {plugins.corePlugins.map(pluginData => ( - - ))} -
    - -

    All Plugins

    - -
    - {plugins.otherPlugins.map(pluginData => ( - - ))} -
    -
    -
    - ); -} diff --git a/microsite-next/src/pages/plugins/index.tsx b/microsite-next/src/pages/plugins/index.tsx index d95494d73d..6f19864f93 100644 --- a/microsite-next/src/pages/plugins/index.tsx +++ b/microsite-next/src/pages/plugins/index.tsx @@ -1,3 +1,87 @@ -import { Plugins } from './_plugins'; +import Link from '@docusaurus/Link'; +import Layout from '@theme/Layout'; +import clsx from 'clsx'; +import React from 'react'; + +import { IPluginData, PluginCard } from './_plugin-card'; +import pluginsStyles from './plugins.module.scss'; + +//#region Plugin data import +const maxDescLength = 160; + +const truncatePluginDescription = (pluginData: IPluginData) => + pluginData.description.length > maxDescLength + ? { + ...pluginData, + description: pluginData.description.slice(0, maxDescLength) + '...', + } + : pluginData; + +const pluginsContext = require.context( + '../../../../microsite/data/plugins', + false, + /\.ya?ml/, +); + +const plugins = pluginsContext.keys().reduce( + (acum, id) => { + const pluginData: IPluginData = pluginsContext(id).default; + + acum[ + pluginData.category === 'Core Feature' ? 'corePlugins' : 'otherPlugins' + ].push(truncatePluginDescription(pluginData)); + + return acum; + }, + { corePlugins: [] as IPluginData[], otherPlugins: [] as IPluginData[] }, +); + +plugins.corePlugins.sort((a, b) => a.order - b.order); +plugins.otherPlugins.sort((a, b) => a.order - b.order); +//#endregion + +const Plugins = () => ( + +
    +
    +
    +

    Plugin Marketplace

    + +

    + Open source plugins that you can add to your Backstage deployment. + Learn how to build a plugin. +

    +
    + + + Add to Marketplace + +
    + +
    + +

    Core Features

    + +
    + {plugins.corePlugins.map(pluginData => ( + + ))} +
    + +

    All Plugins

    + +
    + {plugins.otherPlugins.map(pluginData => ( + + ))} +
    +
    +
    +); export default Plugins; From c6c78b4acbe6c9b0918194dd4b35a9d9bd60d773 Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Mon, 20 Feb 2023 08:48:06 +0200 Subject: [PATCH 263/417] fix: catalog:fetch to throw error for null entity fixes #16447 Signed-off-by: Heikki Hellgren --- .changeset/eight-radios-bake.md | 5 +++++ .../actions/builtin/catalog/fetch.test.ts | 20 ++++++++++++++++++- .../actions/builtin/catalog/fetch.ts | 5 +++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 .changeset/eight-radios-bake.md diff --git a/.changeset/eight-radios-bake.md b/.changeset/eight-radios-bake.md new file mode 100644 index 0000000000..173739a625 --- /dev/null +++ b/.changeset/eight-radios-bake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +throw error from catalog:fetch scaffolder action when entity is null and optional is false diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts index f8bdf2bdcb..52c76c8769 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.test.ts @@ -90,7 +90,7 @@ describe('catalog:fetch', () => { expect(mockContext.output).toHaveBeenCalledWith('entity', null); }); - it('should throw error if entity not in catalog and optional is false', async () => { + it('should throw error if entity fetch fails from catalog and optional is false', async () => { getEntityByRef.mockImplementationOnce(() => { throw new Error('Not found'); }); @@ -109,4 +109,22 @@ describe('catalog:fetch', () => { }); expect(mockContext.output).not.toHaveBeenCalled(); }); + + it('should throw error if entity not in catalog and optional is false', async () => { + getEntityByRef.mockReturnValueOnce(null); + + await expect( + action.handler({ + ...mockContext, + input: { + entityRef: 'component:default/test', + }, + }), + ).rejects.toThrow('Entity component:default/test not found'); + + expect(getEntityByRef).toHaveBeenCalledWith('component:default/test', { + token: 'secret', + }); + expect(mockContext.output).not.toHaveBeenCalled(); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts index 913bf32cce..17e510ce64 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/fetch.ts @@ -93,6 +93,11 @@ export function createFetchCatalogEntityAction(options: { throw e; } } + + if (!entity && !optional) { + throw new Error(`Entity ${entityRef} not found`); + } + ctx.output('entity', entity ?? null); }, }); From 00e67af3426b15f5ff064237738f949529995ddc Mon Sep 17 00:00:00 2001 From: MaeIsBad <26093674+MaeIsBad@users.noreply.github.com> Date: Mon, 20 Feb 2023 09:51:06 +0100 Subject: [PATCH 264/417] Fix spelling mistake in techdocs Signed-off-by: MaeIsBad <26093674+MaeIsBad@users.noreply.github.com> --- docs/features/techdocs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index 38a0143bea..e95db2fad0 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -51,7 +51,7 @@ techdocs: # techdocs.builder can be either 'local' or 'external'. # Using the default build strategy, if builder is set to 'local' and you open a TechDocs page, - # techdocs-backend will try to generate the docs, publish to storage and show the generated docs afterwords. + # techdocs-backend will try to generate the docs, publish to storage and show the generated docs afterwards. # This is the "Basic" setup of the TechDocs Architecture. # Using the default build strategy, if builder is set to 'external' (or anything other than 'local'), techdocs-backend # will only fetch the docs and will NOT try to generate and publish. From 2bba72864becddd08d92a9d9e6fe1f6b34b5534b Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Mon, 20 Feb 2023 10:58:57 +0100 Subject: [PATCH 265/417] Add missing dependency Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/package.json | 1 + yarn.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 8334b14b00..d35a178f5e 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -25,6 +25,7 @@ "dependencies": { "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", "@backstage/theme": "workspace:^", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", diff --git a/yarn.lock b/yarn.lock index c732c8c21d..96b7078aaa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6958,6 +6958,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@material-ui/core": ^4.9.13 From 5326529f16cc22fd6fb8ec8b4e33c9945b5ce2f9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 10:36:26 +0000 Subject: [PATCH 266/417] fix(deps): update dependency @google-cloud/firestore to v6.4.3 Signed-off-by: Renovate Bot --- yarn.lock | 95 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/yarn.lock b/yarn.lock index 956b4705bb..28731b96fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2224,12 +2224,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.18.10, @babel/parser@npm:^7.19.1, @babel/parser@npm:^7.9.4": - version: 7.19.1 - resolution: "@babel/parser@npm:7.19.1" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.18.10, @babel/parser@npm:^7.19.1, @babel/parser@npm:^7.20.15": + version: 7.20.15 + resolution: "@babel/parser@npm:7.20.15" bin: parser: ./bin/babel-parser.js - checksum: b1e0acb346b2a533c857e1e97ac0886cdcbd76aafef67835a2b23f760c10568eb53ad8a27dd5f862d8ba4e583742e6067f107281ccbd68959d61bc61e4ddaa51 + checksum: 1d0f47ca67ff2652f1c0ff1570bed8deccbc4b53509e7cd73476af9cc7ed23480c99f1179bd6d0be01612368b92b39e206d330ad6054009d699934848a89298b languageName: node linkType: hard @@ -9747,14 +9747,14 @@ __metadata: linkType: hard "@google-cloud/firestore@npm:^6.0.0": - version: 6.4.2 - resolution: "@google-cloud/firestore@npm:6.4.2" + version: 6.4.3 + resolution: "@google-cloud/firestore@npm:6.4.3" dependencies: fast-deep-equal: ^3.1.1 functional-red-black-tree: ^1.0.1 - google-gax: ^3.5.2 + google-gax: ^3.5.3 protobufjs: ^7.0.0 - checksum: c259f59905d4939f0b1fff2fdfa3db38a0436454af9e4a8939ea951ee700d5f801375ed090e77f610fbf3f02db1aeba9d70437eb6a8ca6f0ba2088c8964c58d0 + checksum: 8bbde2c9bad94459c231d41855e65866b2383f20e2741aa93d86204370172dd62af94e1eb66d977e000e0c7292c986eb25fe967db7ee847593fd9a68c9fb91e3 languageName: node linkType: hard @@ -10595,13 +10595,13 @@ __metadata: languageName: node linkType: hard -"@grpc/grpc-js@npm:~1.7.0": - version: 1.7.0 - resolution: "@grpc/grpc-js@npm:1.7.0" +"@grpc/grpc-js@npm:~1.8.0": + version: 1.8.9 + resolution: "@grpc/grpc-js@npm:1.8.9" dependencies: "@grpc/proto-loader": ^0.7.0 "@types/node": ">=12.12.47" - checksum: 22eee49f9f5aea1abf9566426d993fe4457c94c2afacd3dfb932cc46dbc06ad6ce8f1422fac357d592dd0c75a5cf03405ea15310064ab3c45e1e418f22c48c2b + checksum: 40408af0c0e2b61dbb0fe1c246ae30404c89c601f3e9f9f8447f82d01d8dc0c8befccf2afe9ded07dfc8bd89c927bcbfb5925d4b1ae887299112b2ab549f519c languageName: node linkType: hard @@ -11160,6 +11160,15 @@ __metadata: languageName: node linkType: hard +"@jsdoc/salty@npm:^0.2.1": + version: 0.2.3 + resolution: "@jsdoc/salty@npm:0.2.3" + dependencies: + lodash: ^4.17.21 + checksum: d2b29089e6ba942bf3228087d35379ada248c34f136357d1a4bf5c0350a0d5bde0f90dc68d5e7271728bac1951f85fe749075df0a32a9d584ad5d198492bf7f1 + languageName: node + linkType: hard + "@juggle/resize-observer@npm:^3.3.1": version: 3.3.1 resolution: "@juggle/resize-observer@npm:3.3.1" @@ -15366,6 +15375,16 @@ __metadata: languageName: node linkType: hard +"@types/rimraf@npm:^3.0.2": + version: 3.0.2 + resolution: "@types/rimraf@npm:3.0.2" + dependencies: + "@types/glob": "*" + "@types/node": "*" + checksum: b47fa302f46434cba704d20465861ad250df79467d3d289f9d6490d3aeeb41e8cb32dd80bd1a8fd833d1e185ac719fbf9be12e05ad9ce9be094d8ee8f1405347 + languageName: node + linkType: hard + "@types/rollup-plugin-peer-deps-external@npm:^2.2.0": version: 2.2.1 resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.1" @@ -24037,13 +24056,14 @@ __metadata: languageName: node linkType: hard -"google-gax@npm:^3.5.2": - version: 3.5.2 - resolution: "google-gax@npm:3.5.2" +"google-gax@npm:^3.5.2, google-gax@npm:^3.5.3": + version: 3.5.7 + resolution: "google-gax@npm:3.5.7" dependencies: - "@grpc/grpc-js": ~1.7.0 + "@grpc/grpc-js": ~1.8.0 "@grpc/proto-loader": ^0.7.0 "@types/long": ^4.0.0 + "@types/rimraf": ^3.0.2 abort-controller: ^3.0.0 duplexify: ^4.0.0 fast-text-encoding: ^1.0.3 @@ -24052,13 +24072,13 @@ __metadata: node-fetch: ^2.6.1 object-hash: ^3.0.0 proto3-json-serializer: ^1.0.0 - protobufjs: 7.1.2 - protobufjs-cli: 1.0.2 + protobufjs: 7.2.2 + protobufjs-cli: 1.1.1 retry-request: ^5.0.0 bin: compileProtos: build/tools/compileProtos.js minifyProtoJson: build/tools/minify.js - checksum: 619a961acba742c30eaba85f5e0fb5903f8fc6713e26bf1736549cbbd43d7fac3ba3379dbc96850117263199ea8e3e74635b078e9464c7fadbbcba8822949135 + checksum: 1f3c647fc1ddc00a6a017be0f83b89691997358720763db13a69a94c7a74f6d31a49b0fd56f7bab18689914c784328901b118bdf150d742719995c705d0fa65d languageName: node linkType: hard @@ -26972,11 +26992,12 @@ __metadata: languageName: node linkType: hard -"jsdoc@npm:^3.6.3": - version: 3.6.11 - resolution: "jsdoc@npm:3.6.11" +"jsdoc@npm:^4.0.0": + version: 4.0.2 + resolution: "jsdoc@npm:4.0.2" dependencies: - "@babel/parser": ^7.9.4 + "@babel/parser": ^7.20.15 + "@jsdoc/salty": ^0.2.1 "@types/markdown-it": ^12.2.3 bluebird: ^3.7.2 catharsis: ^0.9.0 @@ -26989,11 +27010,10 @@ __metadata: mkdirp: ^1.0.4 requizzle: ^0.2.3 strip-json-comments: ^3.1.0 - taffydb: 2.6.2 underscore: ~1.13.2 bin: jsdoc: jsdoc.js - checksum: 7920b5cba6200c8f56c9ac2ac5e89d06b6581dd1ce22e66976409fad8b68c16bfd8cd30fe9af58baeacc9f6bd9ba06d901ca4f5e234944f42a3c37e55e4ddcf0 + checksum: 04bf5ab005349b7581bd0e72ed99933eb71a41dcb47235b486b7d9146fbdf212a53e0cc044abe48ccf46012bd812dc1dfc007c6d679660ebdd053cd000242515 languageName: node linkType: hard @@ -32588,16 +32608,16 @@ __metadata: languageName: node linkType: hard -"protobufjs-cli@npm:1.0.2": - version: 1.0.2 - resolution: "protobufjs-cli@npm:1.0.2" +"protobufjs-cli@npm:1.1.1": + version: 1.1.1 + resolution: "protobufjs-cli@npm:1.1.1" dependencies: chalk: ^4.0.0 escodegen: ^1.13.0 espree: ^9.0.0 estraverse: ^5.1.0 glob: ^8.0.0 - jsdoc: ^3.6.3 + jsdoc: ^4.0.0 minimist: ^1.2.0 semver: ^7.1.2 tmp: ^0.2.1 @@ -32607,13 +32627,13 @@ __metadata: bin: pbjs: bin/pbjs pbts: bin/pbts - checksum: 75dfa8bb76ea390c4f4926120439892fce6c730ec56960e85d5f03cac9c390fd7467d1254833542d722616ab4cb64a622e6de2fb7c75e7c42972878ae447b773 + checksum: 124a2cb10d6fccdd6e8f2984b0f7d9a351d9c1efd17f237acd4a9e7c4b82d63265364b1c86bfa5c6a6fa17d7119182c4c323a8972c0078e1ac5c5f653d096f9b languageName: node linkType: hard -"protobufjs@npm:7.1.2, protobufjs@npm:^7.0.0": - version: 7.1.2 - resolution: "protobufjs@npm:7.1.2" +"protobufjs@npm:7.2.2, protobufjs@npm:^7.0.0": + version: 7.2.2 + resolution: "protobufjs@npm:7.2.2" dependencies: "@protobufjs/aspromise": ^1.1.2 "@protobufjs/base64": ^1.1.2 @@ -32627,7 +32647,7 @@ __metadata: "@protobufjs/utf8": ^1.1.0 "@types/node": ">=13.7.0" long: ^5.0.0 - checksum: ae41669b1b0372fb1d49f506f2d1f2b0fb3dc3cece85987b17bcb544e4cef7c8d27f480486cdec324146ad0a5d22a327166a7ea864a9b3e49cc3c92a5d3f6500 + checksum: 86166e8f3e46789fa4d117ae72c17356db36bf87c0e0710d224be32e543b1c378a94e66dc2b1de5af45edfc25f56acfc7e688c50c956426a3ae97bc474f4445c languageName: node linkType: hard @@ -36466,13 +36486,6 @@ __metadata: languageName: node linkType: hard -"taffydb@npm:2.6.2": - version: 2.6.2 - resolution: "taffydb@npm:2.6.2" - checksum: 8fea9cdff71735a40320c4beeb80cb98837076cb89614bc55ac5d67561f35ebae158cfc07a193a1099b5e32746433b2c086b0cd6d56f29aa7c7678e74968335b - languageName: node - linkType: hard - "tapable@npm:^1.0.0": version: 1.1.3 resolution: "tapable@npm:1.1.3" From 5c7203a866591bc5e088291ea960013ce444a9e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 10:37:34 +0000 Subject: [PATCH 267/417] fix(deps): update dependency @keyv/memcache to v1.3.6 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 956b4705bb..efc55c20cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11168,12 +11168,12 @@ __metadata: linkType: hard "@keyv/memcache@npm:^1.3.5": - version: 1.3.5 - resolution: "@keyv/memcache@npm:1.3.5" + version: 1.3.6 + resolution: "@keyv/memcache@npm:1.3.6" dependencies: json-buffer: ^3.0.1 memjs: ^1.3.0 - checksum: c457863aeff1c5886c273eafa5fd79a4287cae1d9d3721b6ce5aa699033428ec8930db044224a6ab63d951cdac2408850737d0adc65f0a502bf04cd7dbe0d15e + checksum: 3360055b6e22d1be7a77341dc99bafb5434d3288dace94067f3307f6d9498f984dcb0d8452a5b2d97ddca8f8c973caf7cc1332e0ffada1c6dbfb0b2a2d42451a languageName: node linkType: hard From 17969f1d70b7e9257e31672fe4f757ffc9f31157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 20 Feb 2023 11:47:47 +0100 Subject: [PATCH 268/417] update react-router MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- yarn.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index 2dab236124..ae630be19a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12787,10 +12787,10 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.2.1": - version: 1.2.1 - resolution: "@remix-run/router@npm:1.2.1" - checksum: 71c947f83e130bf006226332aca395f626ad599b6d35dfe936f6a8f139cf37278bc1b36bce38c30f6062724402358296329f31c385b11ae59b13b76a2716d701 +"@remix-run/router@npm:1.3.2": + version: 1.3.2 + resolution: "@remix-run/router@npm:1.3.2" + checksum: ee2108b87d4a1241cdea137dd7e1741ee679228bd33fd81e22a6bb2940f81186cefe9a85e26d60cc49bbcc1bdbc57d1954b7d4d62f8a51ef69feddfc899f55fa languageName: node linkType: hard @@ -33321,26 +33321,26 @@ __metadata: linkType: hard "react-router-dom-stable@npm:react-router-dom@^6.3.0, react-router-dom@npm:^6.3.0": - version: 6.6.2 - resolution: "react-router-dom@npm:6.6.2" + version: 6.8.1 + resolution: "react-router-dom@npm:6.8.1" dependencies: - "@remix-run/router": 1.2.1 - react-router: 6.6.2 + "@remix-run/router": 1.3.2 + react-router: 6.8.1 peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: e0ee89a2b3768d2eb406ecefedfa24b55428145359b4138f6d38b8a99b60a4f275418910f4cdb12c069ed0237711acced3787b0c7febfa6568d7ea9cd624ff3b + checksum: fb1a9f5c7e4c83536ee7e6493f3c13f6abda66da69f9191fb8b087ab188ecc18a3a32575813a280cbeca67bcb8b0dcb6dbcef7ed599e03f38a44d694f4abcf14 languageName: node linkType: hard -"react-router-stable@npm:react-router@^6.3.0, react-router@npm:6.6.2": - version: 6.6.2 - resolution: "react-router@npm:6.6.2" +"react-router-stable@npm:react-router@^6.3.0, react-router@npm:6.8.1": + version: 6.8.1 + resolution: "react-router@npm:6.8.1" dependencies: - "@remix-run/router": 1.2.1 + "@remix-run/router": 1.3.2 peerDependencies: react: ">=16.8" - checksum: 5960d774bb3a8f697a57ee2e82a3eb0a300b7186a62b27e02773c94f1682e59435bd876d6162a08cc8daf27cac72aaab66d348fcc4d8f59240a63a911cf0050b + checksum: 8e7cc7a516adeb6060911861af99d9b512893c15ec732cbf8574872919be4f3fe439ffa8c0876d1bcbced880d081bfeda3c01cb505b5a243565d10500ee0ac36 languageName: node linkType: hard From cc1df92cdc7d85095fc96de28fec957124359784 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 10:49:02 +0000 Subject: [PATCH 269/417] chore(deps): update creyd/prettier_action action to v4.3 Signed-off-by: Renovate Bot --- .github/workflows/sync_code-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 7b0cbbbb01..b299f314a7 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -25,7 +25,7 @@ jobs: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: Run Prettier on ADOPTERS.md - uses: creyD/prettier_action@v4.2 + uses: creyD/prettier_action@v4.3 with: # Modifies commit only if prettier autofixed the ADOPTERS.md prettier_options: --config docs/prettier.config.js --write ADOPTERS.md From a3241964bc671132a0139eb7a31f3449c0bb4ef9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 11:15:38 +0000 Subject: [PATCH 270/417] fix(deps): update aws-sdk-js-v3 monorepo to v3.272.0 Signed-off-by: Renovate Bot --- yarn.lock | 1234 ++++++++++++++++++++++++++--------------------------- 1 file changed, 617 insertions(+), 617 deletions(-) diff --git a/yarn.lock b/yarn.lock index a4a5521c2c..0d25b852f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -373,13 +373,13 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/abort-controller@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/abort-controller@npm:3.257.0" +"@aws-sdk/abort-controller@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/abort-controller@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: fca54be92f6cbfe8f0675aba19a50960376506a4c9aaa9c44220e8c29a7b3c8c74198537f831c1d4818ec686df97af86d055d8f3265c3a6fde56bbf593241c47 + checksum: 298974b97641732c74272dd645b55c15aaefd891b5a868c279ae2abe3c3e0753e7e6f218e8c3712196ca2d4f19796623cb48f9e9816b5bbbc4eb38247d07d0fe languageName: node linkType: hard @@ -402,477 +402,477 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/client-cognito-identity@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/client-cognito-identity@npm:3.261.0" +"@aws-sdk/client-cognito-identity@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/client-cognito-identity@npm:3.272.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.261.0 - "@aws-sdk/config-resolver": 3.259.0 - "@aws-sdk/credential-provider-node": 3.261.0 - "@aws-sdk/fetch-http-handler": 3.257.0 - "@aws-sdk/hash-node": 3.257.0 - "@aws-sdk/invalid-dependency": 3.257.0 - "@aws-sdk/middleware-content-length": 3.257.0 - "@aws-sdk/middleware-endpoint": 3.257.0 - "@aws-sdk/middleware-host-header": 3.257.0 - "@aws-sdk/middleware-logger": 3.257.0 - "@aws-sdk/middleware-recursion-detection": 3.257.0 - "@aws-sdk/middleware-retry": 3.259.0 - "@aws-sdk/middleware-serde": 3.257.0 - "@aws-sdk/middleware-signing": 3.257.0 - "@aws-sdk/middleware-stack": 3.257.0 - "@aws-sdk/middleware-user-agent": 3.257.0 - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/node-http-handler": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/smithy-client": 3.261.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/client-sts": 3.272.0 + "@aws-sdk/config-resolver": 3.272.0 + "@aws-sdk/credential-provider-node": 3.272.0 + "@aws-sdk/fetch-http-handler": 3.272.0 + "@aws-sdk/hash-node": 3.272.0 + "@aws-sdk/invalid-dependency": 3.272.0 + "@aws-sdk/middleware-content-length": 3.272.0 + "@aws-sdk/middleware-endpoint": 3.272.0 + "@aws-sdk/middleware-host-header": 3.272.0 + "@aws-sdk/middleware-logger": 3.272.0 + "@aws-sdk/middleware-recursion-detection": 3.272.0 + "@aws-sdk/middleware-retry": 3.272.0 + "@aws-sdk/middleware-serde": 3.272.0 + "@aws-sdk/middleware-signing": 3.272.0 + "@aws-sdk/middleware-stack": 3.272.0 + "@aws-sdk/middleware-user-agent": 3.272.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/node-http-handler": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/smithy-client": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.261.0 - "@aws-sdk/util-defaults-mode-node": 3.261.0 - "@aws-sdk/util-endpoints": 3.257.0 - "@aws-sdk/util-retry": 3.257.0 - "@aws-sdk/util-user-agent-browser": 3.257.0 - "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-defaults-mode-browser": 3.272.0 + "@aws-sdk/util-defaults-mode-node": 3.272.0 + "@aws-sdk/util-endpoints": 3.272.0 + "@aws-sdk/util-retry": 3.272.0 + "@aws-sdk/util-user-agent-browser": 3.272.0 + "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: edbaacaa9b2576376aedca110ba6267af25005922e23e9d7c5b0d00572ab758b47493f30bf6223c9462e31b236f7d6194786be0d6e79676726a28d74a6de8989 + checksum: fd17c705b2de99fd1570239b62032525380b5e17799fc15f720196a488889fa10bbccd01952d5694ca8c20249d8a808de86de07d5a1b0d21486964a70d9b6d4d languageName: node linkType: hard "@aws-sdk/client-s3@npm:^3.208.0": - version: 3.261.0 - resolution: "@aws-sdk/client-s3@npm:3.261.0" + version: 3.272.0 + resolution: "@aws-sdk/client-s3@npm:3.272.0" dependencies: "@aws-crypto/sha1-browser": 3.0.0 "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.261.0 - "@aws-sdk/config-resolver": 3.259.0 - "@aws-sdk/credential-provider-node": 3.261.0 - "@aws-sdk/eventstream-serde-browser": 3.258.0 - "@aws-sdk/eventstream-serde-config-resolver": 3.257.0 - "@aws-sdk/eventstream-serde-node": 3.258.0 - "@aws-sdk/fetch-http-handler": 3.257.0 - "@aws-sdk/hash-blob-browser": 3.257.0 - "@aws-sdk/hash-node": 3.257.0 - "@aws-sdk/hash-stream-node": 3.257.0 - "@aws-sdk/invalid-dependency": 3.257.0 - "@aws-sdk/md5-js": 3.258.0 - "@aws-sdk/middleware-bucket-endpoint": 3.259.0 - "@aws-sdk/middleware-content-length": 3.257.0 - "@aws-sdk/middleware-endpoint": 3.257.0 - "@aws-sdk/middleware-expect-continue": 3.257.0 - "@aws-sdk/middleware-flexible-checksums": 3.259.0 - "@aws-sdk/middleware-host-header": 3.257.0 - "@aws-sdk/middleware-location-constraint": 3.257.0 - "@aws-sdk/middleware-logger": 3.257.0 - "@aws-sdk/middleware-recursion-detection": 3.257.0 - "@aws-sdk/middleware-retry": 3.259.0 - "@aws-sdk/middleware-sdk-s3": 3.257.0 - "@aws-sdk/middleware-serde": 3.257.0 - "@aws-sdk/middleware-signing": 3.257.0 - "@aws-sdk/middleware-ssec": 3.257.0 - "@aws-sdk/middleware-stack": 3.257.0 - "@aws-sdk/middleware-user-agent": 3.257.0 - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/node-http-handler": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/signature-v4-multi-region": 3.257.0 - "@aws-sdk/smithy-client": 3.261.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/client-sts": 3.272.0 + "@aws-sdk/config-resolver": 3.272.0 + "@aws-sdk/credential-provider-node": 3.272.0 + "@aws-sdk/eventstream-serde-browser": 3.272.0 + "@aws-sdk/eventstream-serde-config-resolver": 3.272.0 + "@aws-sdk/eventstream-serde-node": 3.272.0 + "@aws-sdk/fetch-http-handler": 3.272.0 + "@aws-sdk/hash-blob-browser": 3.272.0 + "@aws-sdk/hash-node": 3.272.0 + "@aws-sdk/hash-stream-node": 3.272.0 + "@aws-sdk/invalid-dependency": 3.272.0 + "@aws-sdk/md5-js": 3.272.0 + "@aws-sdk/middleware-bucket-endpoint": 3.272.0 + "@aws-sdk/middleware-content-length": 3.272.0 + "@aws-sdk/middleware-endpoint": 3.272.0 + "@aws-sdk/middleware-expect-continue": 3.272.0 + "@aws-sdk/middleware-flexible-checksums": 3.272.0 + "@aws-sdk/middleware-host-header": 3.272.0 + "@aws-sdk/middleware-location-constraint": 3.272.0 + "@aws-sdk/middleware-logger": 3.272.0 + "@aws-sdk/middleware-recursion-detection": 3.272.0 + "@aws-sdk/middleware-retry": 3.272.0 + "@aws-sdk/middleware-sdk-s3": 3.272.0 + "@aws-sdk/middleware-serde": 3.272.0 + "@aws-sdk/middleware-signing": 3.272.0 + "@aws-sdk/middleware-ssec": 3.272.0 + "@aws-sdk/middleware-stack": 3.272.0 + "@aws-sdk/middleware-user-agent": 3.272.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/node-http-handler": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/signature-v4-multi-region": 3.272.0 + "@aws-sdk/smithy-client": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.261.0 - "@aws-sdk/util-defaults-mode-node": 3.261.0 - "@aws-sdk/util-endpoints": 3.257.0 - "@aws-sdk/util-retry": 3.257.0 - "@aws-sdk/util-stream-browser": 3.258.0 - "@aws-sdk/util-stream-node": 3.257.0 - "@aws-sdk/util-user-agent-browser": 3.257.0 - "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-defaults-mode-browser": 3.272.0 + "@aws-sdk/util-defaults-mode-node": 3.272.0 + "@aws-sdk/util-endpoints": 3.272.0 + "@aws-sdk/util-retry": 3.272.0 + "@aws-sdk/util-stream-browser": 3.272.0 + "@aws-sdk/util-stream-node": 3.272.0 + "@aws-sdk/util-user-agent-browser": 3.272.0 + "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 - "@aws-sdk/util-waiter": 3.257.0 + "@aws-sdk/util-waiter": 3.272.0 "@aws-sdk/xml-builder": 3.201.0 fast-xml-parser: 4.0.11 tslib: ^2.3.1 - checksum: 3600a38f6828b4fd3e14adf1f5aeb2fbb6693d43f4dd4f8be384adbf2b2218d50aa034f19c4399dececfa072833fa7ddd680c23c4c8ad30e04c0045f37d859ee + checksum: 34b9c3515a01b75b170c5942fbfe2ac860efae5856dfeb831691a46f086f21a0d0f36fb05e7f8fe3bc4b84f476abd16ea6cd734592b6fb7a2d86aaaad54c4457 languageName: node linkType: hard "@aws-sdk/client-sqs@npm:^3.208.0": - version: 3.261.0 - resolution: "@aws-sdk/client-sqs@npm:3.261.0" + version: 3.272.0 + resolution: "@aws-sdk/client-sqs@npm:3.272.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.261.0 - "@aws-sdk/config-resolver": 3.259.0 - "@aws-sdk/credential-provider-node": 3.261.0 - "@aws-sdk/fetch-http-handler": 3.257.0 - "@aws-sdk/hash-node": 3.257.0 - "@aws-sdk/invalid-dependency": 3.257.0 - "@aws-sdk/md5-js": 3.258.0 - "@aws-sdk/middleware-content-length": 3.257.0 - "@aws-sdk/middleware-endpoint": 3.257.0 - "@aws-sdk/middleware-host-header": 3.257.0 - "@aws-sdk/middleware-logger": 3.257.0 - "@aws-sdk/middleware-recursion-detection": 3.257.0 - "@aws-sdk/middleware-retry": 3.259.0 - "@aws-sdk/middleware-sdk-sqs": 3.257.0 - "@aws-sdk/middleware-serde": 3.257.0 - "@aws-sdk/middleware-signing": 3.257.0 - "@aws-sdk/middleware-stack": 3.257.0 - "@aws-sdk/middleware-user-agent": 3.257.0 - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/node-http-handler": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/smithy-client": 3.261.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/client-sts": 3.272.0 + "@aws-sdk/config-resolver": 3.272.0 + "@aws-sdk/credential-provider-node": 3.272.0 + "@aws-sdk/fetch-http-handler": 3.272.0 + "@aws-sdk/hash-node": 3.272.0 + "@aws-sdk/invalid-dependency": 3.272.0 + "@aws-sdk/md5-js": 3.272.0 + "@aws-sdk/middleware-content-length": 3.272.0 + "@aws-sdk/middleware-endpoint": 3.272.0 + "@aws-sdk/middleware-host-header": 3.272.0 + "@aws-sdk/middleware-logger": 3.272.0 + "@aws-sdk/middleware-recursion-detection": 3.272.0 + "@aws-sdk/middleware-retry": 3.272.0 + "@aws-sdk/middleware-sdk-sqs": 3.272.0 + "@aws-sdk/middleware-serde": 3.272.0 + "@aws-sdk/middleware-signing": 3.272.0 + "@aws-sdk/middleware-stack": 3.272.0 + "@aws-sdk/middleware-user-agent": 3.272.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/node-http-handler": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/smithy-client": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.261.0 - "@aws-sdk/util-defaults-mode-node": 3.261.0 - "@aws-sdk/util-endpoints": 3.257.0 - "@aws-sdk/util-retry": 3.257.0 - "@aws-sdk/util-user-agent-browser": 3.257.0 - "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-defaults-mode-browser": 3.272.0 + "@aws-sdk/util-defaults-mode-node": 3.272.0 + "@aws-sdk/util-endpoints": 3.272.0 + "@aws-sdk/util-retry": 3.272.0 + "@aws-sdk/util-user-agent-browser": 3.272.0 + "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 fast-xml-parser: 4.0.11 tslib: ^2.3.1 - checksum: b15130b021f1af1109236abda0fb83232a37b8cb147bf59e3f09b3f44db6934d19bb3633eeac9c7302b9019714d53d47acc0e66df90ef848f518cf0d11661f15 + checksum: 7188f5b769b98710624bf389475f5eb345fc20fb7078dc9c425c65803aa9006258ba32467ec71dd082832c3af0388ef6fa59aabb76b736eb97fe2f937082b86b languageName: node linkType: hard -"@aws-sdk/client-sso-oidc@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/client-sso-oidc@npm:3.261.0" +"@aws-sdk/client-sso-oidc@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/client-sso-oidc@npm:3.272.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/config-resolver": 3.259.0 - "@aws-sdk/fetch-http-handler": 3.257.0 - "@aws-sdk/hash-node": 3.257.0 - "@aws-sdk/invalid-dependency": 3.257.0 - "@aws-sdk/middleware-content-length": 3.257.0 - "@aws-sdk/middleware-endpoint": 3.257.0 - "@aws-sdk/middleware-host-header": 3.257.0 - "@aws-sdk/middleware-logger": 3.257.0 - "@aws-sdk/middleware-recursion-detection": 3.257.0 - "@aws-sdk/middleware-retry": 3.259.0 - "@aws-sdk/middleware-serde": 3.257.0 - "@aws-sdk/middleware-stack": 3.257.0 - "@aws-sdk/middleware-user-agent": 3.257.0 - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/node-http-handler": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/smithy-client": 3.261.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/config-resolver": 3.272.0 + "@aws-sdk/fetch-http-handler": 3.272.0 + "@aws-sdk/hash-node": 3.272.0 + "@aws-sdk/invalid-dependency": 3.272.0 + "@aws-sdk/middleware-content-length": 3.272.0 + "@aws-sdk/middleware-endpoint": 3.272.0 + "@aws-sdk/middleware-host-header": 3.272.0 + "@aws-sdk/middleware-logger": 3.272.0 + "@aws-sdk/middleware-recursion-detection": 3.272.0 + "@aws-sdk/middleware-retry": 3.272.0 + "@aws-sdk/middleware-serde": 3.272.0 + "@aws-sdk/middleware-stack": 3.272.0 + "@aws-sdk/middleware-user-agent": 3.272.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/node-http-handler": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/smithy-client": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.261.0 - "@aws-sdk/util-defaults-mode-node": 3.261.0 - "@aws-sdk/util-endpoints": 3.257.0 - "@aws-sdk/util-retry": 3.257.0 - "@aws-sdk/util-user-agent-browser": 3.257.0 - "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-defaults-mode-browser": 3.272.0 + "@aws-sdk/util-defaults-mode-node": 3.272.0 + "@aws-sdk/util-endpoints": 3.272.0 + "@aws-sdk/util-retry": 3.272.0 + "@aws-sdk/util-user-agent-browser": 3.272.0 + "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: d33870aed0db77246812b99d05d5536df4b51a36fc0f1717aa883e82c5c8460bb867a6a3b817b06f41e86732390305dced75f99aee1d58ae3635102a89562ae7 + checksum: a1ee61c2fc86a74439e06c98aa10c8246e31579eb480b625321f7dfe8fd26af49bd6ead803da2443700c5943eab5ba90dfc33fc4d9f23b1a680850d73526da4d languageName: node linkType: hard -"@aws-sdk/client-sso@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/client-sso@npm:3.261.0" +"@aws-sdk/client-sso@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/client-sso@npm:3.272.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/config-resolver": 3.259.0 - "@aws-sdk/fetch-http-handler": 3.257.0 - "@aws-sdk/hash-node": 3.257.0 - "@aws-sdk/invalid-dependency": 3.257.0 - "@aws-sdk/middleware-content-length": 3.257.0 - "@aws-sdk/middleware-endpoint": 3.257.0 - "@aws-sdk/middleware-host-header": 3.257.0 - "@aws-sdk/middleware-logger": 3.257.0 - "@aws-sdk/middleware-recursion-detection": 3.257.0 - "@aws-sdk/middleware-retry": 3.259.0 - "@aws-sdk/middleware-serde": 3.257.0 - "@aws-sdk/middleware-stack": 3.257.0 - "@aws-sdk/middleware-user-agent": 3.257.0 - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/node-http-handler": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/smithy-client": 3.261.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/config-resolver": 3.272.0 + "@aws-sdk/fetch-http-handler": 3.272.0 + "@aws-sdk/hash-node": 3.272.0 + "@aws-sdk/invalid-dependency": 3.272.0 + "@aws-sdk/middleware-content-length": 3.272.0 + "@aws-sdk/middleware-endpoint": 3.272.0 + "@aws-sdk/middleware-host-header": 3.272.0 + "@aws-sdk/middleware-logger": 3.272.0 + "@aws-sdk/middleware-recursion-detection": 3.272.0 + "@aws-sdk/middleware-retry": 3.272.0 + "@aws-sdk/middleware-serde": 3.272.0 + "@aws-sdk/middleware-stack": 3.272.0 + "@aws-sdk/middleware-user-agent": 3.272.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/node-http-handler": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/smithy-client": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.261.0 - "@aws-sdk/util-defaults-mode-node": 3.261.0 - "@aws-sdk/util-endpoints": 3.257.0 - "@aws-sdk/util-retry": 3.257.0 - "@aws-sdk/util-user-agent-browser": 3.257.0 - "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-defaults-mode-browser": 3.272.0 + "@aws-sdk/util-defaults-mode-node": 3.272.0 + "@aws-sdk/util-endpoints": 3.272.0 + "@aws-sdk/util-retry": 3.272.0 + "@aws-sdk/util-user-agent-browser": 3.272.0 + "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: aa2b71a0be6c5ca92940eacdb008d89c007b595f8c5cb80ff7c5c697d83e1de44432463f5d20b7074939c806612165c47345b197e8dd1743f523858117a4b70b + checksum: 7549e813ef8088d22a0a1f9c8a42532d2d2050c932fd6e7d4f717aea2cd554938283f3af0f1fe9597b24724c6b2438947b3089452ed9c0dfafb1efad15f3ac60 languageName: node linkType: hard -"@aws-sdk/client-sts@npm:3.261.0, @aws-sdk/client-sts@npm:^3.208.0": - version: 3.261.0 - resolution: "@aws-sdk/client-sts@npm:3.261.0" +"@aws-sdk/client-sts@npm:3.272.0, @aws-sdk/client-sts@npm:^3.208.0": + version: 3.272.0 + resolution: "@aws-sdk/client-sts@npm:3.272.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/config-resolver": 3.259.0 - "@aws-sdk/credential-provider-node": 3.261.0 - "@aws-sdk/fetch-http-handler": 3.257.0 - "@aws-sdk/hash-node": 3.257.0 - "@aws-sdk/invalid-dependency": 3.257.0 - "@aws-sdk/middleware-content-length": 3.257.0 - "@aws-sdk/middleware-endpoint": 3.257.0 - "@aws-sdk/middleware-host-header": 3.257.0 - "@aws-sdk/middleware-logger": 3.257.0 - "@aws-sdk/middleware-recursion-detection": 3.257.0 - "@aws-sdk/middleware-retry": 3.259.0 - "@aws-sdk/middleware-sdk-sts": 3.257.0 - "@aws-sdk/middleware-serde": 3.257.0 - "@aws-sdk/middleware-signing": 3.257.0 - "@aws-sdk/middleware-stack": 3.257.0 - "@aws-sdk/middleware-user-agent": 3.257.0 - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/node-http-handler": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/smithy-client": 3.261.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/config-resolver": 3.272.0 + "@aws-sdk/credential-provider-node": 3.272.0 + "@aws-sdk/fetch-http-handler": 3.272.0 + "@aws-sdk/hash-node": 3.272.0 + "@aws-sdk/invalid-dependency": 3.272.0 + "@aws-sdk/middleware-content-length": 3.272.0 + "@aws-sdk/middleware-endpoint": 3.272.0 + "@aws-sdk/middleware-host-header": 3.272.0 + "@aws-sdk/middleware-logger": 3.272.0 + "@aws-sdk/middleware-recursion-detection": 3.272.0 + "@aws-sdk/middleware-retry": 3.272.0 + "@aws-sdk/middleware-sdk-sts": 3.272.0 + "@aws-sdk/middleware-serde": 3.272.0 + "@aws-sdk/middleware-signing": 3.272.0 + "@aws-sdk/middleware-stack": 3.272.0 + "@aws-sdk/middleware-user-agent": 3.272.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/node-http-handler": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/smithy-client": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.261.0 - "@aws-sdk/util-defaults-mode-node": 3.261.0 - "@aws-sdk/util-endpoints": 3.257.0 - "@aws-sdk/util-retry": 3.257.0 - "@aws-sdk/util-user-agent-browser": 3.257.0 - "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-defaults-mode-browser": 3.272.0 + "@aws-sdk/util-defaults-mode-node": 3.272.0 + "@aws-sdk/util-endpoints": 3.272.0 + "@aws-sdk/util-retry": 3.272.0 + "@aws-sdk/util-user-agent-browser": 3.272.0 + "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 fast-xml-parser: 4.0.11 tslib: ^2.3.1 - checksum: e7be888c97351bb3b52e50de5e6830849c97c9d2b2ad2b14daea66f7dd2e7a4eaae26ccb78aeb874b1719c73a8d8ccf2bb02915eca4cabeb34226e1a10ae1ebd + checksum: 2e3083803a4d64de3148ef49b6dccb1a54d6766a8c60a2002cff32f005159d69d8323e50b7cb6055cb0bd595b8e8f2bc8ccd839ee9ca17c5db47fc6b63b10269 languageName: node linkType: hard -"@aws-sdk/config-resolver@npm:3.259.0": - version: 3.259.0 - resolution: "@aws-sdk/config-resolver@npm:3.259.0" +"@aws-sdk/config-resolver@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/config-resolver@npm:3.272.0" dependencies: - "@aws-sdk/signature-v4": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/signature-v4": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-config-provider": 3.208.0 - "@aws-sdk/util-middleware": 3.257.0 + "@aws-sdk/util-middleware": 3.272.0 tslib: ^2.3.1 - checksum: c461dfd62291c8dbc3394d586aa44a14326c0a9f02e4cc84dfa6569c6003890d21343aaa28a067337949837f7e2c2e3533465e3e2e5f2ee3e42bb30cc69de0d4 + checksum: d2a2fa4f013ad04f50522aec1001efd34c62ababbc809b176d2e31e41828d867de616ff01bfcaa12603b344ca6838ea5946c72d21e5f2573b90828e29bad6e35 languageName: node linkType: hard -"@aws-sdk/credential-provider-cognito-identity@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.261.0" +"@aws-sdk/credential-provider-cognito-identity@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.272.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.261.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/client-cognito-identity": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 678098f0079cef01ed10c7c06f838b30ec50a047dd67cadd898a134347c31d9dfc9cdd18880eeae26f2d1f700b8d5ae120181f0b1889a20da981076edef5c2c6 + checksum: ba19883f08b8c4625d53a9c243eb8a831f51d7764157d86fc9a0343cd02c5fbd41923a21b5579c718c3b490a97eacc83fe398f5f920dcbd3ce41a3326959b652 languageName: node linkType: hard -"@aws-sdk/credential-provider-env@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/credential-provider-env@npm:3.257.0" +"@aws-sdk/credential-provider-env@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-env@npm:3.272.0" dependencies: - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: e268c46ff374eddb5cd5bef62a8b969a5bfd5202e15122ecbd2baa7882c99f75c2e2b6dfc0c294fcfc331e9e2028620c827278f1eec6f7158c30f079ae67dc5f + checksum: 74195ecb608e3e6dedfc40e052bd7d0ef3a9e531ecf404f40d05869e23328bd156e458e9770d30458137438de92efd3dcb9fc3ff5f1319c49b55e057323f3ea6 languageName: node linkType: hard -"@aws-sdk/credential-provider-imds@npm:3.259.0": - version: 3.259.0 - resolution: "@aws-sdk/credential-provider-imds@npm:3.259.0" +"@aws-sdk/credential-provider-imds@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-imds@npm:3.272.0" dependencies: - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 tslib: ^2.3.1 - checksum: 7149bb155e9f169f6d9a4e17d16c683b5eed6f71871230f1c786b884f22fe438b3f29e6179a5538ad540f025d2eb3cfa1a4d9a1bd1e1ec495a539f8d164903da + checksum: c6adfcaa8dada3f99bbbd241aee3e568474c93df97e9b3f5e4feb9b000a91e5b3f0491556f712ebbd4d67de9c77c1072e6d444ac63ad9c6be31cf26acb2bc72c languageName: node linkType: hard -"@aws-sdk/credential-provider-ini@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/credential-provider-ini@npm:3.261.0" +"@aws-sdk/credential-provider-ini@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-ini@npm:3.272.0" dependencies: - "@aws-sdk/credential-provider-env": 3.257.0 - "@aws-sdk/credential-provider-imds": 3.259.0 - "@aws-sdk/credential-provider-process": 3.257.0 - "@aws-sdk/credential-provider-sso": 3.261.0 - "@aws-sdk/credential-provider-web-identity": 3.257.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/shared-ini-file-loader": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/credential-provider-env": 3.272.0 + "@aws-sdk/credential-provider-imds": 3.272.0 + "@aws-sdk/credential-provider-process": 3.272.0 + "@aws-sdk/credential-provider-sso": 3.272.0 + "@aws-sdk/credential-provider-web-identity": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/shared-ini-file-loader": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 72834195a9a2fad9d6a8011d904ed0a59b29c043bcc98e226b2381d123c57b9b528dd924aa2c94283e38cbddb98198892c0f428b363565678ca992276062cc8d + checksum: 06c1dfc6bff09472e11dd7e2c295cfdf71c36af11cb6ba33ce0328aaf9d0baee3f99de8ceec32ff473925b55ad190c9f85f125cf43874c25e22c37e8e3c648d3 languageName: node linkType: hard -"@aws-sdk/credential-provider-node@npm:3.261.0, @aws-sdk/credential-provider-node@npm:^3.208.0": - version: 3.261.0 - resolution: "@aws-sdk/credential-provider-node@npm:3.261.0" +"@aws-sdk/credential-provider-node@npm:3.272.0, @aws-sdk/credential-provider-node@npm:^3.208.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-node@npm:3.272.0" dependencies: - "@aws-sdk/credential-provider-env": 3.257.0 - "@aws-sdk/credential-provider-imds": 3.259.0 - "@aws-sdk/credential-provider-ini": 3.261.0 - "@aws-sdk/credential-provider-process": 3.257.0 - "@aws-sdk/credential-provider-sso": 3.261.0 - "@aws-sdk/credential-provider-web-identity": 3.257.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/shared-ini-file-loader": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/credential-provider-env": 3.272.0 + "@aws-sdk/credential-provider-imds": 3.272.0 + "@aws-sdk/credential-provider-ini": 3.272.0 + "@aws-sdk/credential-provider-process": 3.272.0 + "@aws-sdk/credential-provider-sso": 3.272.0 + "@aws-sdk/credential-provider-web-identity": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/shared-ini-file-loader": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: af393f142f1305438f5ac5be79a120ad1566d57edca8b1577dc0fcfe50bfb31c721de2d04dd49abbf3086676ad5c4b809d136841e2e25451facf9599dda7322c + checksum: 25c5ab8583821f63c7eb1a5257869dd21159d0b7643ff9a9c094e9b5c78c887bc441f1a2f974eaace62c1879d13e7d590bb3ea2623f5a5de822bf773b1aab100 languageName: node linkType: hard -"@aws-sdk/credential-provider-process@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/credential-provider-process@npm:3.257.0" +"@aws-sdk/credential-provider-process@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-process@npm:3.272.0" dependencies: - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/shared-ini-file-loader": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/shared-ini-file-loader": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: cb34261ae87463245e4cc3ddab306201c52a8fbcfedc122ae9782bdf9263ab8fabc33cde028def52d069452a842338033829aaecfec2d0fc00547513a76c9b6f + checksum: fda290aea2417137f333c8ad0a94d7789054b464bdf5f9a7eef06341f88d4bd0c96ca02b84b58e0af2a9c490cee4febf6ee84254dfbff192bfccccbb0c8c1876 languageName: node linkType: hard -"@aws-sdk/credential-provider-sso@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/credential-provider-sso@npm:3.261.0" +"@aws-sdk/credential-provider-sso@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-sso@npm:3.272.0" dependencies: - "@aws-sdk/client-sso": 3.261.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/shared-ini-file-loader": 3.257.0 - "@aws-sdk/token-providers": 3.261.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/client-sso": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/shared-ini-file-loader": 3.272.0 + "@aws-sdk/token-providers": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 0f3fc6ceb69e537f2e5751283aac473dcc5a4f8da798b0340995cb5996ca8201844c2f5b6cdcaa7ce642e1375cbdd039fa4b9962b84f27d500eaaa1f80725199 + checksum: ac1ada61e67f6f0a82ed8507c0218a03fe40e2d1e4ee064578e63573f868195800088dc3e33d58d7d04877e464342987005aceb300e4db9a141080cdc695e46e languageName: node linkType: hard -"@aws-sdk/credential-provider-web-identity@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/credential-provider-web-identity@npm:3.257.0" +"@aws-sdk/credential-provider-web-identity@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/credential-provider-web-identity@npm:3.272.0" dependencies: - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 2d3ee4975af680337cd6a9f25b6eb874201f4787ddc0217f80cb7ebb36c70424108fa8c04e5a9f0f8c2130d06685a3de3938c41b8c78e238b9faeb348c0cd361 + checksum: aad84e2bfd90495ed4eb76b83940729bd2fb652398f7e477cfd8053f9c986132b4ff8682854a91e3f23c7daaab66e1c31320188561104fea710cd87be1221e9d languageName: node linkType: hard "@aws-sdk/credential-providers@npm:^3.208.0": - version: 3.261.0 - resolution: "@aws-sdk/credential-providers@npm:3.261.0" + version: 3.272.0 + resolution: "@aws-sdk/credential-providers@npm:3.272.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.261.0 - "@aws-sdk/client-sso": 3.261.0 - "@aws-sdk/client-sts": 3.261.0 - "@aws-sdk/credential-provider-cognito-identity": 3.261.0 - "@aws-sdk/credential-provider-env": 3.257.0 - "@aws-sdk/credential-provider-imds": 3.259.0 - "@aws-sdk/credential-provider-ini": 3.261.0 - "@aws-sdk/credential-provider-node": 3.261.0 - "@aws-sdk/credential-provider-process": 3.257.0 - "@aws-sdk/credential-provider-sso": 3.261.0 - "@aws-sdk/credential-provider-web-identity": 3.257.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/shared-ini-file-loader": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/client-cognito-identity": 3.272.0 + "@aws-sdk/client-sso": 3.272.0 + "@aws-sdk/client-sts": 3.272.0 + "@aws-sdk/credential-provider-cognito-identity": 3.272.0 + "@aws-sdk/credential-provider-env": 3.272.0 + "@aws-sdk/credential-provider-imds": 3.272.0 + "@aws-sdk/credential-provider-ini": 3.272.0 + "@aws-sdk/credential-provider-node": 3.272.0 + "@aws-sdk/credential-provider-process": 3.272.0 + "@aws-sdk/credential-provider-sso": 3.272.0 + "@aws-sdk/credential-provider-web-identity": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/shared-ini-file-loader": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 56880bab2a99c2c9710622be905091c1316dbcd9ce44c5a567021ce809134cf52d5a920649ab715157b408ff73cf03bdee4da4d410c448ffa72b90bb9a9b03db + checksum: ce311afb81267bc984a9dabffb3df1689cd63c8ed75010163aced4855bf96399a225ae594b494cfcfbb970e9bfe0461576d82a5695065d9e4ca0c82755edd52b languageName: node linkType: hard -"@aws-sdk/eventstream-codec@npm:3.258.0": - version: 3.258.0 - resolution: "@aws-sdk/eventstream-codec@npm:3.258.0" +"@aws-sdk/eventstream-codec@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/eventstream-codec@npm:3.272.0" dependencies: "@aws-crypto/crc32": 3.0.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-hex-encoding": 3.201.0 tslib: ^2.3.1 - checksum: b2fca764b9c105a355a18af565c3a5bbd50ce6cf385b86668c1451f429a1fac31114bf88eec3d4ea2160a368f48e06f6b3ce83d273035e4824464de9c322f9d8 + checksum: bea8599a72657d698de169643950031624e0b61179240c8d8eb3c17f01bfc4579c507a861be6c703f318fcdff4217a4cb4279223cad93fb21e69f4b5d10d6102 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-browser@npm:3.258.0": - version: 3.258.0 - resolution: "@aws-sdk/eventstream-serde-browser@npm:3.258.0" +"@aws-sdk/eventstream-serde-browser@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/eventstream-serde-browser@npm:3.272.0" dependencies: - "@aws-sdk/eventstream-serde-universal": 3.258.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/eventstream-serde-universal": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 3155f6bc39ef914be1950d8ba310029d5f8ffacaf9a516b20da4890d68b2bde6c636367bb4391c12ce4a3518041aca1afae0179aa5d76f9208133e7423bd86d9 + checksum: a4fa42e1a8658eca191f567046741192e6e04f5c58744655ec0112a1d46b57d5ce04432e2fec0e6fe16d486c30abdc58b734ed67879c10e0fcc4820530eaff35 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-config-resolver@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/eventstream-serde-config-resolver@npm:3.257.0" +"@aws-sdk/eventstream-serde-config-resolver@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/eventstream-serde-config-resolver@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 6658916cebfbdc74407cfdf1bda622bd9c7731a5f855b9cfb8870e3dd558f802ccc99ee30e9dcc05109d2a4c253cac799506afad5947c8526ab49973a567c0fb + checksum: feee058288bbf5a97d78dfee5084c2dc224d771499848dcaedbfd671c8889f52329f96ce87c291d29e66b46c8e25923bd55f64d8ed744089fc40723296eb003c languageName: node linkType: hard -"@aws-sdk/eventstream-serde-node@npm:3.258.0": - version: 3.258.0 - resolution: "@aws-sdk/eventstream-serde-node@npm:3.258.0" +"@aws-sdk/eventstream-serde-node@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/eventstream-serde-node@npm:3.272.0" dependencies: - "@aws-sdk/eventstream-serde-universal": 3.258.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/eventstream-serde-universal": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 298b60866c8b10cec812766f0a8f9fba482dcd19b48c0c6dceb5bda10e85a64c5c1216a61d288c0fd3b7be4a6e1dfba4f30a41b01a6bbb60a1cb419b21f0902a + checksum: 02fa0c5f992df253713bbe19515bf898e332e3bc51da28da28bdf2cde584df90689bb9b54afa57354798c8b01e4b592d63fb575d7652fd5df2c00bf1e45e689a languageName: node linkType: hard -"@aws-sdk/eventstream-serde-universal@npm:3.258.0": - version: 3.258.0 - resolution: "@aws-sdk/eventstream-serde-universal@npm:3.258.0" +"@aws-sdk/eventstream-serde-universal@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/eventstream-serde-universal@npm:3.272.0" dependencies: - "@aws-sdk/eventstream-codec": 3.258.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/eventstream-codec": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 038ed604878f31478c2b00e86fdeeeee38905349be2fbf8104954d176b94996863e5e6e8a15c4849acac7ccaa537718762c1619d436ccef87c8a8b0bbf9d68cb + checksum: 3d8031e84af1a0cdf5f22f98aee868cd62b6fa87e432231bbe32a400874dc44b030cffdf9dce3194281bf04a1669b23bf8ce16759123ba10980676fe9388e63b languageName: node linkType: hard @@ -889,61 +889,61 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/fetch-http-handler@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/fetch-http-handler@npm:3.257.0" +"@aws-sdk/fetch-http-handler@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/fetch-http-handler@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/querystring-builder": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/querystring-builder": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-base64": 3.208.0 tslib: ^2.3.1 - checksum: de25f542db072225c23403254be7ff4e642f12e348eb703cdb30a5e9b0ac5e4f18930947490f6bb27a31b8f8a462abfdd7b9344b16e41b6b52e1fe969ac95396 + checksum: 63d047db7b7ebfee49af8bf42f3a7aa1bea37cc687e7046bc77913c23ed99056e91b5ab77739157428be73b2a2f29783a7a659ccf29a440dd63b750d313d46cc languageName: node linkType: hard -"@aws-sdk/hash-blob-browser@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/hash-blob-browser@npm:3.257.0" +"@aws-sdk/hash-blob-browser@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/hash-blob-browser@npm:3.272.0" dependencies: "@aws-sdk/chunked-blob-reader": 3.188.0 "@aws-sdk/chunked-blob-reader-native": 3.208.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 85dfb814cbb24cb00a52fc6232e0f0c2f4c359fabf44c52cef7938c39c059c1b0b2722895394b9a4e544a63fa7e3998fb8d8bacd2582ca1beb1197e93f55a16b + checksum: ab0564672606760b934973ef33a8a8d567d52d3fa4be2a7a8919daa1b9ac1c3afaaee975ae7ad20940f51e1057e3321c39f5dcd2246ca85aad03e1f7aed68669 languageName: node linkType: hard -"@aws-sdk/hash-node@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/hash-node@npm:3.257.0" +"@aws-sdk/hash-node@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/hash-node@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-buffer-from": 3.208.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 26f8f2fca7ad13a1dc64753ee1ef85014eb89adfef9f500f5003e479807c5f2ec6ee185ae8e88d6bcb68e26512702fd6886fe211486531e4388e40fd003678a5 + checksum: 1b3d5b288133af9294df36cec2377589f45c82f61cb824b14ac38955541357826cf5a8f95d7906cbf284ed9ffbd928a37b2f94581f7281715879aa4c0e7c7b24 languageName: node linkType: hard -"@aws-sdk/hash-stream-node@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/hash-stream-node@npm:3.257.0" +"@aws-sdk/hash-stream-node@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/hash-stream-node@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 7aa9e69fb47c05f557fe79f382e20b99a87f9ada068a9458834afba550cdac13256d47baf42a50287aebe37e2f99de9747f80ea206c5da86e556855ec6b9d8bc + checksum: 4cb90a9ae442e0722d651d7e7558a8b0abcbc1b45670e194d51d0a9b2ea6cad6e3a02433d506a8d96ac94a26cd8e5746514c09f05f0da2acb2dc06c60218d3c5 languageName: node linkType: hard -"@aws-sdk/invalid-dependency@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/invalid-dependency@npm:3.257.0" +"@aws-sdk/invalid-dependency@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/invalid-dependency@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: fe99f546cc041a9ccc8b29654fd3e8e466aef41697d4c69f4afc1aab1f1f83f2e7f0b9e0e20b3fe23843a01008902f00aeeb24cf26b7df0594c75a4ebf3bb3f3 + checksum: 4ef63ed9a9275e20bdcec551ee92a9d60a6a688c120f968fd51af235d357d39ec522752592075dad752be9a8439d93b4d1848e12fa9a88cda595920d78b008d2 languageName: node linkType: hard @@ -957,11 +957,11 @@ __metadata: linkType: hard "@aws-sdk/lib-storage@npm:^3.208.0": - version: 3.261.0 - resolution: "@aws-sdk/lib-storage@npm:3.261.0" + version: 3.272.0 + resolution: "@aws-sdk/lib-storage@npm:3.272.0" dependencies: - "@aws-sdk/middleware-endpoint": 3.257.0 - "@aws-sdk/smithy-client": 3.261.0 + "@aws-sdk/middleware-endpoint": 3.272.0 + "@aws-sdk/smithy-client": 3.272.0 buffer: 5.6.0 events: 3.3.0 stream-browserify: 3.0.0 @@ -969,268 +969,268 @@ __metadata: peerDependencies: "@aws-sdk/abort-controller": ^3.0.0 "@aws-sdk/client-s3": ^3.0.0 - checksum: 649d5ea5a9aa5723d2cfdecee9457a8b64662387b8a279e6a29a0c36e605c7b307b1666f76b3eb9422e27fc6235dcd506bfa0f0dbb00e2c6575346bf385a7d2e + checksum: 7c4f25fec63d60ade365062fbd1cf9807593268f3b0354ea22b5e06619e443f5421da920255875455d84fc19900d5472fa5e92a5bd46c1f3be148da67afa58f8 languageName: node linkType: hard -"@aws-sdk/md5-js@npm:3.258.0": - version: 3.258.0 - resolution: "@aws-sdk/md5-js@npm:3.258.0" +"@aws-sdk/md5-js@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/md5-js@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: e1812a1aae620d242d42b2425d40169e7af94c0a29275704d9dbb2ec68161207cc79a75cdc66b60b5ad24fd1607e6fcc14dc3aa3adb18fb71446b546898ea730 + checksum: d59010c1b48ba1992298ed23b605e7395a4aa964430d41012492faac24c7fa50856b565a523b0262b2c8b667904fdc57748d98475ba8c2e24b4550e17211e5ab languageName: node linkType: hard -"@aws-sdk/middleware-bucket-endpoint@npm:3.259.0": - version: 3.259.0 - resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.259.0" +"@aws-sdk/middleware-bucket-endpoint@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-arn-parser": 3.208.0 "@aws-sdk/util-config-provider": 3.208.0 tslib: ^2.3.1 - checksum: 4ad5c0ece9723e52b70129f39737a66d8778eb538868af7dcbc574264f95d9705aa3a178c043c05861aac91487e76c3a663badce8022fa5aa9aa89622ca5f58a + checksum: 2c9dffb5545e085ce6323e9628d5998b551332f213f33cdbd606e889b4ca4fdac61648e2c0d8cadcf11aa5908049a764083a794082fce611980056a093c78e55 languageName: node linkType: hard -"@aws-sdk/middleware-content-length@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-content-length@npm:3.257.0" +"@aws-sdk/middleware-content-length@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-content-length@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 4f6129653b98185624c66bf2114417d492ec3cf91063da4cbce0e07ad3b1831766ff684491f0c14f92c8b9b39599a9781ca883f2d5ee42c3d38b273b6664f361 + checksum: e1a9c3e6fec8dcfed90bb44b25a8f4786b4ed0cbd79c6f69e3d8e91d394402ad4f2667231aafdcc05caf136a331434d54fac286a72ab5870dd90705a2e56243b languageName: node linkType: hard -"@aws-sdk/middleware-endpoint@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-endpoint@npm:3.257.0" +"@aws-sdk/middleware-endpoint@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-endpoint@npm:3.272.0" dependencies: - "@aws-sdk/middleware-serde": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/signature-v4": 3.257.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/url-parser": 3.257.0 + "@aws-sdk/middleware-serde": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/signature-v4": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/url-parser": 3.272.0 "@aws-sdk/util-config-provider": 3.208.0 - "@aws-sdk/util-middleware": 3.257.0 + "@aws-sdk/util-middleware": 3.272.0 tslib: ^2.3.1 - checksum: e709f6b5dc6bee4659caa7740847f53be359b215d307210f093629f5013f3d0521e060ef6f7797c82dd02a9ac0528b47581e6e19fb0e2f38aa2ff3a8f1b9abc0 + checksum: c3acd1a35d33cff87a43df371ae138faf6c9569497c36b009cafc2fdb1f21e352671df6eb56730634d7f135bef2a47ac588ac7cdd2905676292a418b79a0eab1 languageName: node linkType: hard -"@aws-sdk/middleware-expect-continue@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-expect-continue@npm:3.257.0" +"@aws-sdk/middleware-expect-continue@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-expect-continue@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 911e087f822ce384f69a1f1d28449c99b81fa464af854f0a253656615104a047bcceb5a93837a9073a8466d2ec255550e5306a17c19087f5e3f060c27d1f930b + checksum: 19f32623758ccc1d08e2ff08db8efc62c3e04c3e89b15a7ca4b1719fa15ce7bfaad0eea3cceadc395f769405181a356a6a4efdadb2e6f6bd90afd31f8532ca40 languageName: node linkType: hard -"@aws-sdk/middleware-flexible-checksums@npm:3.259.0": - version: 3.259.0 - resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.259.0" +"@aws-sdk/middleware-flexible-checksums@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.272.0" dependencies: "@aws-crypto/crc32": 3.0.0 "@aws-crypto/crc32c": 3.0.0 "@aws-sdk/is-array-buffer": 3.201.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: b20e03676b38d8ba13b67c7bfe92b1802d8685fefd86934df472d51ec0ea856f470597e9cee98086b84bd6a8e8c02527c69961c9eac988e07a4bb805e5612e7b + checksum: 06d0f9edd3c78d17e0669dd913daed67f0c45d59be54bf39e68ad1184fd0dc80d544545bbe09f6dd51ca6dca8a42b585ba83e5be3aa665c6486fb5210b08f8df languageName: node linkType: hard -"@aws-sdk/middleware-host-header@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-host-header@npm:3.257.0" +"@aws-sdk/middleware-host-header@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-host-header@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 426f6a6a9964ef993d4e7d8401162b62f758a7247872c6b58163d40ec8320738a84dbd2dbaccd008b24801642f6fd2d24b6af11331f00a204ed48e814f1e6e3c + checksum: 3e191fe72de35b517a20fe47f647527579458091d4d66d55ef7e6b08107a4f4d7abe77afdcdd061776db906309d414525ff63e472c2c05d6e2447f41582f64fb languageName: node linkType: hard -"@aws-sdk/middleware-location-constraint@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-location-constraint@npm:3.257.0" +"@aws-sdk/middleware-location-constraint@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-location-constraint@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 3894591a69b09987d6f4e9e85078167aff7fd836d819d0c06e2c5a0c191eb39e724ff3048280ba8763c02656cfbf06f4d9a47a602cc6e5c51ac50fec2127d16e + checksum: 42cb878c4a2b4e1c0884277a9cacc4611111e1d6de649c4fb41f770e60ddceef27de433667c4e4d29882f6c9ad746859e53e0724fbfc5aff23720496a4007a0b languageName: node linkType: hard -"@aws-sdk/middleware-logger@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-logger@npm:3.257.0" +"@aws-sdk/middleware-logger@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-logger@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 3b4ac39d4be50dde9b806500a50a6d2c4ab267f6e02e780fe70adf0d07f4026c09131e3f787d86833f4295987cbad6858839884d1c5f1ea56df729fc4a8d7d49 + checksum: 128163d39522017ffb0099334f283ba82806b0c5b82965b47fff8b3b8648ae2b542b1733c69934bbca65fded9d26b8b93fa587547eeb8db2a3f5249841848f96 languageName: node linkType: hard -"@aws-sdk/middleware-recursion-detection@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-recursion-detection@npm:3.257.0" +"@aws-sdk/middleware-recursion-detection@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-recursion-detection@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: ce972140735fb040d00e1356409beac6dc5d9c477f975c73776de8294a91f81ac2a87e11c02581ff6c8b8c6f84e455e77a081291bbc536d22c9e128b07928fcd + checksum: cdc150a4f3cbd5d7c6926befcf7eb49daea1d0ca054dbe7b82e013eb74f3850056b78603f61989c2bb3cdc748798674b6811c3011c6a8c1773e13dfa11ea3ae7 languageName: node linkType: hard -"@aws-sdk/middleware-retry@npm:3.259.0": - version: 3.259.0 - resolution: "@aws-sdk/middleware-retry@npm:3.259.0" +"@aws-sdk/middleware-retry@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-retry@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/service-error-classification": 3.257.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/util-middleware": 3.257.0 - "@aws-sdk/util-retry": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/service-error-classification": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/util-middleware": 3.272.0 + "@aws-sdk/util-retry": 3.272.0 tslib: ^2.3.1 uuid: ^8.3.2 - checksum: 22ae9d575cafbc9c3806a10871e2b6749d12b8109bc15e8eabe82e24613dc60196c2ab48df62fcf39e3dae33319146a58d3983c51a68c6c1da89e941ac2d4efa + checksum: 208e8f1b96f5ee47d28d76d0f7738f0ae7e355cb9aa24dcb88a8c4d9aa35bf833bf333c1ad4a6d11d18ec27b1713cac0ee04e0fdac17462059416a214f366944 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-s3@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-sdk-s3@npm:3.257.0" +"@aws-sdk/middleware-sdk-s3@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-sdk-s3@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-arn-parser": 3.208.0 tslib: ^2.3.1 - checksum: 67742b8c34552f1b69c7d4d7c58d68bf698203e094d399f7936959318daef47d060496f451babc727970942c9699c83b3a0b57d49da26812e70888a74d6ef585 + checksum: 464f38d1593866724ce4e793e065c4e23b875ec889384a99c64d7aa34baf765ebdc18b218ed5e83f4f6c257d7b56c560aab8c0b617960a200484970ec8d55526 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sqs@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.257.0" +"@aws-sdk/middleware-sdk-sqs@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-hex-encoding": 3.201.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 54cea36a767a3d7621eea7b22e59fb7268914228d3b26f6dbcd9cf17d9dc51a542c117249c992f5fd6e5804cdb04c675593ec150a41f564773b32ebf4c103b9b + checksum: 2338c5865fb797f5e9f0963cf0045e991a9aa816c4fefb86943e129be68ff3b94a662741692999c2a212e4491db299241453d9b432c3eee63781850f22772a29 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sts@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-sdk-sts@npm:3.257.0" +"@aws-sdk/middleware-sdk-sts@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-sdk-sts@npm:3.272.0" dependencies: - "@aws-sdk/middleware-signing": 3.257.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/signature-v4": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/middleware-signing": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/signature-v4": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 9171f0fc8a9518b8344c58f26446c9b39a19d00b747f2ae02b92b022d8fdcdb65528f05e753999676b3c04bffa38d008a599d86c2e0fa65b2196cd9633ab4308 + checksum: d808f945ae7354ef7102737418794565f26af3ca3241c3873235284400a13faf118242e92eba1831c25fc249d9c6a15f3c16e4ae3101cd6d5ab175a669b70fcb languageName: node linkType: hard -"@aws-sdk/middleware-serde@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-serde@npm:3.257.0" +"@aws-sdk/middleware-serde@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-serde@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: ceda3cb7bb7ceced0d5b69363dca51fa92b4f6defcd8299910eee0fe65d557871aa7777dade4abc64aa91347d038727fa65ff7ff0cc3d9716d0065dfd939c724 + checksum: d33c07ff8c7fb9682115220ae035de5414124fd81319d7490ed3f2c235b3c0b536634a5939b311dbd735050deca4702503ee26d9e17b97ba8a1ff9e46093573e languageName: node linkType: hard -"@aws-sdk/middleware-signing@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-signing@npm:3.257.0" +"@aws-sdk/middleware-signing@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-signing@npm:3.272.0" dependencies: - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/signature-v4": 3.257.0 - "@aws-sdk/types": 3.257.0 - "@aws-sdk/util-middleware": 3.257.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/signature-v4": 3.272.0 + "@aws-sdk/types": 3.272.0 + "@aws-sdk/util-middleware": 3.272.0 tslib: ^2.3.1 - checksum: dfa31f59675427f7aff83852f24e2393bd7d1295421d68c2bb060faca001ce385d7a1d7231c92c48e841e58581ceeffef0209c7c91b51b19361af29120342a50 + checksum: 0b711de21b0f2b28178b211ae2de962676038ed49ff9247810c2213018b77ca399285278a0b448a0242f92796e1360b83c09aa268fe64a7f153428b9ed919edc languageName: node linkType: hard -"@aws-sdk/middleware-ssec@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-ssec@npm:3.257.0" +"@aws-sdk/middleware-ssec@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-ssec@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 562d601a70f15446bf863d22427e8ee0949789a6cbebd2e82f5f513ff40e0da1f98c57f87677861e4347bad47e718388ea7cfd9478fb2ce47af14b89f7639aa9 + checksum: 81836fd3235f455d79d7cdc0bc193b321024dab2f6443f16e013c5eb4b3e06c3ca283152cb560f7f2bd2e2accf81f773f95278e8c9094806c1ddb54b5af0db8f languageName: node linkType: hard -"@aws-sdk/middleware-stack@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-stack@npm:3.257.0" +"@aws-sdk/middleware-stack@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-stack@npm:3.272.0" dependencies: tslib: ^2.3.1 - checksum: f7520d3e53d026f46c6504bcebef2a5732b724ab79079ccd2db0c052f6d4fd3cc4f06b951ff02723ef9ba46c6a0a0deca3282f152172ae7b1c3b2f493d35d584 + checksum: 7006c4168c2e5c7b15edd4e87001a6e4edbd2f549908ac0e68bb61f12c232048ac1d351b0714e7a79115aeaf251838877b2ef9ac829a6b1ab04913015a3c87a3 languageName: node linkType: hard -"@aws-sdk/middleware-user-agent@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/middleware-user-agent@npm:3.257.0" +"@aws-sdk/middleware-user-agent@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/middleware-user-agent@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: b2fc45a734845d40d1e69bf7f0890613aad8357d4830f704c7ee6c1339ab51cbb0cef51920dc22718d29eb258fc1024f8c23cbc53a4f93b9b857f8bcacc442a1 + checksum: a392a8c68509f118f008002e4ef6ba7fea9f93ade97963449e6eec951c0319a7cc8fd40cf77bda1540ff25ebbbe75785a6fc5ed4be63676144e5242892940732 languageName: node linkType: hard -"@aws-sdk/node-config-provider@npm:3.259.0": - version: 3.259.0 - resolution: "@aws-sdk/node-config-provider@npm:3.259.0" +"@aws-sdk/node-config-provider@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/node-config-provider@npm:3.272.0" dependencies: - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/shared-ini-file-loader": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/shared-ini-file-loader": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 72e4818b1ab641d1aa3b85c7901f7d64ad0399eb384cda1c875b41a37021c2be9e68021e6b0aa3f7298d2d46017259ee10356f07c314b4bc40146a44f355135a + checksum: 57f1f107ae4e213ffedf648d46fe0e026af83b13eeb8c13bd8f812cbbb226a0b2c2793afec0e29165ee64cc948182499ad44fe62f63ac58b06d0dd2cab7f1461 languageName: node linkType: hard -"@aws-sdk/node-http-handler@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/node-http-handler@npm:3.257.0" +"@aws-sdk/node-http-handler@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/node-http-handler@npm:3.272.0" dependencies: - "@aws-sdk/abort-controller": 3.257.0 - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/querystring-builder": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/abort-controller": 3.272.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/querystring-builder": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 37531827bc9e0b590c67ce57b87315fab8639a5feff1cb6cda8effdf6ac2d2fbc8a645765f004b52b03ff39c896da88a090b0dbcf5cfcf5d3d65d0b995f628fb + checksum: cbcdab82a7611d1d776197e921563ac6248173aa6e5a6f6e6486a735c71763ae69d1d6ae6de8acebcb8020cdfa089a776d9180929397291623db8f11a1f7b8a9 languageName: node linkType: hard -"@aws-sdk/property-provider@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/property-provider@npm:3.257.0" +"@aws-sdk/property-provider@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/property-provider@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 066290e9b88bcbc7d6bace37482ce955c782386a6cd75dc789efeb368bc87d0c410d01fd6b25bf66918e3328c6ffe1942aa643f4fdd4fa604feee36af9114894 + checksum: 7f01794e93276e13339034dac816b2b5da2370fbc1ff304d451e2d0344957e94ba53f5c54de44eca4cb53e2847c7be820db25d6164ca9e489a4a39787fb6c8b3 languageName: node linkType: hard @@ -1244,13 +1244,13 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/protocol-http@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/protocol-http@npm:3.257.0" +"@aws-sdk/protocol-http@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/protocol-http@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: c51539e2f617d5d84e51ad9feeb93d51a310d808da18ceb53317aaf35af99bb8bea52eca532ab68d546b0ff5156b92cef5c3e98245f0b425795bd7910b608dad + checksum: 59d7c97b1a46bc3c072f56caec365472c9d94638923799ad2418cee52bb0eab945ab080cd63f5351ff45ad943dde9d88b294e096af36524e184c0764b2ea6cc5 languageName: node linkType: hard @@ -1265,51 +1265,51 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/querystring-builder@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/querystring-builder@npm:3.257.0" +"@aws-sdk/querystring-builder@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/querystring-builder@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-uri-escape": 3.201.0 tslib: ^2.3.1 - checksum: a66b07cd1c4af544c7c6f903a735d1e8359f7d3b5c74803fc63b16b854eafec21f4b1c8874761edeebc4c2341f1f0b72190f03e0a005e8fff7b619e30cd59896 + checksum: 8164bb5547c556a2b3933b0a93d55d9f205ebe096f2dbcea6d3be4aa23bb0b4e7996ba24363b9ac3f80b4026903b267b759efdf9f72379f1eea9250c182238b9 languageName: node linkType: hard -"@aws-sdk/querystring-parser@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/querystring-parser@npm:3.257.0" +"@aws-sdk/querystring-parser@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/querystring-parser@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: cd391b7993a8e2397e3f0abd25e9b0b43747fe1b1415e9c5af6a3895567bb8dc9267d97e7d494c504f721b0b868bf9e0b93ec3677a5a7bc4ef2ff7252a402985 + checksum: fe5a29a265f48ad02b3161e888a66e4ac08fe07d52a67e811ac1da1734bfa9ac87ead637b595efcbc163f64f2280c8b56c867a8399f4c816b3683b6308837f93 languageName: node linkType: hard -"@aws-sdk/service-error-classification@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/service-error-classification@npm:3.257.0" - checksum: 231440f52a1c6c6d5ab62c13491736273fda49bb68bc278954dfaa3b7fa874946576c87a529504d6268472e646b3235cacb5c0fe5acc9af2398d87a56fabda3d +"@aws-sdk/service-error-classification@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/service-error-classification@npm:3.272.0" + checksum: 9507f74c909a968aa9bf835a05a9cfc93a0892e7c685de37da485e74a61b4fff271621d7c841aa0c9aedbcc57b19f171e6bc74925a82007be6c6750b3c7d0198 languageName: node linkType: hard -"@aws-sdk/shared-ini-file-loader@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/shared-ini-file-loader@npm:3.257.0" +"@aws-sdk/shared-ini-file-loader@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/shared-ini-file-loader@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 27738db81e2b9c8e0bd248e1c0ed7f21b65b52204b247cb8119b3b48b55844c2450e5fe20bb1193311177a8a18e8bb99594d3bfde71dacd1ee9ed8bbad9a915b + checksum: 1245658ad6efbeda0181aca64b00259749abc76d6200ac8fb481fe627eb88932a5cf2e9c366583ccba9fa540706a08b611552fff5233d66835c0e525c51f97c4 languageName: node linkType: hard -"@aws-sdk/signature-v4-multi-region@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/signature-v4-multi-region@npm:3.257.0" +"@aws-sdk/signature-v4-multi-region@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/signature-v4-multi-region@npm:3.272.0" dependencies: - "@aws-sdk/protocol-http": 3.257.0 - "@aws-sdk/signature-v4": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/protocol-http": 3.272.0 + "@aws-sdk/signature-v4": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-arn-parser": 3.208.0 tslib: ^2.3.1 peerDependencies: @@ -1317,46 +1317,46 @@ __metadata: peerDependenciesMeta: "@aws-sdk/signature-v4-crt": optional: true - checksum: 260d37db48e90addbaa302358a98307c8c61561953e37986f6f4571258784decf3e582f9da3c8cc4d545b3ddc63592e983949890e6204872469f7c837b3bb939 + checksum: 231eac2d4203a9ed3829d55a93d503d629bbd43301516d4e06c461dd16eba3a72373c004a59789de43487804266ca4ced259adcb1d26b6916f7b3545401ff544 languageName: node linkType: hard -"@aws-sdk/signature-v4@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/signature-v4@npm:3.257.0" +"@aws-sdk/signature-v4@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/signature-v4@npm:3.272.0" dependencies: "@aws-sdk/is-array-buffer": 3.201.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-hex-encoding": 3.201.0 - "@aws-sdk/util-middleware": 3.257.0 + "@aws-sdk/util-middleware": 3.272.0 "@aws-sdk/util-uri-escape": 3.201.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 6faf6a3d8f51603240f6375b76bfd031223aa5cf1f0385cfa97833e6b188fb9b746caab53a45d0e7a311ca9735c82b56c67aed68b1fbcdf4bbcbf93e288fd09f + checksum: bdf997ed7779e173797bd31a9ae39bc9860e12cb7d0a734b4a47c76bde435c5c1d5f56dbb3c5f1a2b26a828367fd88f34a4527b8a12d4c1a60b3b0049aacf706 languageName: node linkType: hard -"@aws-sdk/smithy-client@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/smithy-client@npm:3.261.0" +"@aws-sdk/smithy-client@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/smithy-client@npm:3.272.0" dependencies: - "@aws-sdk/middleware-stack": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/middleware-stack": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 1394ce351d52bc3bd17b484acbfb9171a57203b64741a21d1f8c9d89443f165186539194d463ccdd2dfad18a981ff9561088d2d2c52e0467d8225400312b5486 + checksum: 8ba3c4733a32c7c28ec06735b0fc3dbc33a1657bfc54dc28f6770b021fda74680c693812d8c6db2291197a275f32fd80be909dddda4eb726328bf34e8d18bccc languageName: node linkType: hard -"@aws-sdk/token-providers@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/token-providers@npm:3.261.0" +"@aws-sdk/token-providers@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/token-providers@npm:3.272.0" dependencies: - "@aws-sdk/client-sso-oidc": 3.261.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/shared-ini-file-loader": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/client-sso-oidc": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/shared-ini-file-loader": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: ca65f92443726c14860cd4adc7fde0f6eb073cdfa93d27d05495dbede3b6ead9157ad4dc5471398f47b3202527cfaf0e44f0d184d6a4be7a0290e9ae0bd9b9ab + checksum: 8d49846f4ad124707879a9b8adaea089c4d02dfd1c15dcceb083fecd538ecce1db65f1104e6178b13941acb2a4ae275c5cf9eb586d5d25757eb9fb454bdbb70c languageName: node linkType: hard @@ -1367,23 +1367,23 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/types@npm:3.257.0, @aws-sdk/types@npm:^3.208.0, @aws-sdk/types@npm:^3.222.0": - version: 3.257.0 - resolution: "@aws-sdk/types@npm:3.257.0" +"@aws-sdk/types@npm:3.272.0, @aws-sdk/types@npm:^3.208.0, @aws-sdk/types@npm:^3.222.0": + version: 3.272.0 + resolution: "@aws-sdk/types@npm:3.272.0" dependencies: tslib: ^2.3.1 - checksum: eab2154f7d27d0bec29df41374481652525e1658ad987c64ed02cbe7b7388c563e6a8d317c8fc564ac6fbd97c98be700a29352c9acebc3903cf3305431bf0a86 + checksum: c4e4f09dd2672eab4fc15b08006c730c1d07d4b54ae35e03167d99f6110751e36b5332165e03c71c28724037f623f8da87a45a018eb631a1ce86d406f9d08da6 languageName: node linkType: hard -"@aws-sdk/url-parser@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/url-parser@npm:3.257.0" +"@aws-sdk/url-parser@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/url-parser@npm:3.272.0" dependencies: - "@aws-sdk/querystring-parser": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/querystring-parser": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 3b781c7fe94572e673e0651a47806cf023f60fb1268d2abbad9364c70112b1ad37d2261f631e0d7ce5c5ec543faa7e316d987e519091db68bf121384ad557043 + checksum: 4a66e733b336b0e28eceef89271f255dcd7079cfa8ba1c854e6c147ced211242e00016e3f22752e5ea3e49b35457568c5ae8df574f729d6e60cd1f5054f5a57d languageName: node linkType: hard @@ -1443,39 +1443,39 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-defaults-mode-browser@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/util-defaults-mode-browser@npm:3.261.0" +"@aws-sdk/util-defaults-mode-browser@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-defaults-mode-browser@npm:3.272.0" dependencies: - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/types": 3.272.0 bowser: ^2.11.0 tslib: ^2.3.1 - checksum: 218c97dc362549796a318048d496f8e105d023dd040ecf811c1cab8bc807c80afb43b8cae8bb6ac3c87f5bdfe07f9248fccd825554287cb5c39f84dddcb521b1 + checksum: 56594cc954c6431ced3646668fd92d8229eb1c20a37d6c66b0ebf3ce88a7f9803c63d432c78412768ebf0d141fdacef01644ea0f3507e6fb295a22c80f728c1a languageName: node linkType: hard -"@aws-sdk/util-defaults-mode-node@npm:3.261.0": - version: 3.261.0 - resolution: "@aws-sdk/util-defaults-mode-node@npm:3.261.0" +"@aws-sdk/util-defaults-mode-node@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-defaults-mode-node@npm:3.272.0" dependencies: - "@aws-sdk/config-resolver": 3.259.0 - "@aws-sdk/credential-provider-imds": 3.259.0 - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/property-provider": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/config-resolver": 3.272.0 + "@aws-sdk/credential-provider-imds": 3.272.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/property-provider": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: d784ae1aaf51640b0b591028b91522c8c6dc58558245c6dfcd253adbfcc42e2496d4f8139df47b8b9932edd5eccbcdf8829a5d0adcf91b634ff8a506934d4399 + checksum: ee0e44d78d70b6eab73d6e8455972218cb1a15950f47d81d72d094420b2719add34bf46218016f85242a2a155216d2a0542ed5f4e68e171efc09691125fcb6fd languageName: node linkType: hard -"@aws-sdk/util-endpoints@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/util-endpoints@npm:3.257.0" +"@aws-sdk/util-endpoints@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-endpoints@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: ba1aec13c8ceb9519400f2c77db1743b34dec4380b27598a8862e94c9df43e3e8b4e183f230fb6bdaaeb89653d232e6a13dcc2016c6a9d12246f58b630fd3ec0 + checksum: d701e0245930df2000974f9d7c8398fde65924fe5aaa72f2c314fa40a8842e1868a6e285aa78479f741e40b8be54060a4607c9b5b3ac0386839a45df8df238f2 languageName: node linkType: hard @@ -1497,48 +1497,48 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-middleware@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/util-middleware@npm:3.257.0" +"@aws-sdk/util-middleware@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-middleware@npm:3.272.0" dependencies: tslib: ^2.3.1 - checksum: 77ac007288fa98ec55c10af5a097f7f829d7ec53b6eecc43bc00a18b9ea011194aec42fb69e58421f87363490cef89b811330eaf174739fdf6b810b40cd46768 + checksum: e9a0b55317c474d3eecd65765443eff68f5130ac6f982a41450e0cb949169ff2cf13273282337f2067dfdb5cc7d25137b3bd2fa5f5228cfe541003cf387a6101 languageName: node linkType: hard -"@aws-sdk/util-retry@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/util-retry@npm:3.257.0" +"@aws-sdk/util-retry@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-retry@npm:3.272.0" dependencies: - "@aws-sdk/service-error-classification": 3.257.0 + "@aws-sdk/service-error-classification": 3.272.0 tslib: ^2.3.1 - checksum: 7d7054c5a73f3acaf59b620386ad0a6226ec6b2761e5c59f304694f8a7f5cb8ab0eb7d51be102e81d6e2a5ec97b20bd8814cf245ff44fcc5587d4e5b80a3b892 + checksum: 7449d9b5daef1244a1601c9892bdd57abeb71ee87357e9dac71d53a77b80648b8cd0db1e99749a76e241ab01fce71a753360d0c8e130f6ae6e71a94b462242f0 languageName: node linkType: hard -"@aws-sdk/util-stream-browser@npm:3.258.0": - version: 3.258.0 - resolution: "@aws-sdk/util-stream-browser@npm:3.258.0" +"@aws-sdk/util-stream-browser@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-stream-browser@npm:3.272.0" dependencies: - "@aws-sdk/fetch-http-handler": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/fetch-http-handler": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-hex-encoding": 3.201.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: c3a99e5d5fd2e6c7aff63bc7041d1f49a5a328071421aa050ee57bdeeceb5e34005f4895df5fd2e358e245ca513c67717a896d8f2402b431d41bc22abe6b135b + checksum: 18e3dfa4efcf12e5e4eda55da14c9a98154f063b1bbf0a926fc406ffdf791363a1881e93194fa5a160e7bd26dd1b1933d6a57b19134e6f0a4feda8c6f5cfcb13 languageName: node linkType: hard -"@aws-sdk/util-stream-node@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/util-stream-node@npm:3.257.0" +"@aws-sdk/util-stream-node@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-stream-node@npm:3.272.0" dependencies: - "@aws-sdk/node-http-handler": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/node-http-handler": 3.272.0 + "@aws-sdk/types": 3.272.0 "@aws-sdk/util-buffer-from": 3.208.0 tslib: ^2.3.1 - checksum: d2773a857f8400aaef45237dff4f454b233eeed2644739f1dbd90f88ef02dfdfbc456ee6b92fb13b9fea6c29d0e5853f9eb942407487f51528128ed23f5a04a7 + checksum: 7fa500251680e3eb5fa63d47c6d4846ca66f8c781ee0d990ed79d16a12b0bb074eb7d5c9e26390afd7a18159a758fbc333ce1b788c2a8dea7438cbe2f4c6c7c3 languageName: node linkType: hard @@ -1556,30 +1556,30 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-user-agent-browser@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/util-user-agent-browser@npm:3.257.0" +"@aws-sdk/util-user-agent-browser@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-user-agent-browser@npm:3.272.0" dependencies: - "@aws-sdk/types": 3.257.0 + "@aws-sdk/types": 3.272.0 bowser: ^2.11.0 tslib: ^2.3.1 - checksum: f475d6096ff92ba2292de6cc78e2e1512df96c7fff3d8ef39148884533c14cc341a84ce3c4969f78cca2d8d4098c4cefefd72edf7cb480c33f8597f5828245c3 + checksum: e5ac1b88f9af45c2e0dbec40d2aa9c616634df252ac437f2dfd3aeb316fe561a5c09d481c075945843b3a7f5edafbc10ef26741c6ccacc4d435d8be7eeab179c languageName: node linkType: hard -"@aws-sdk/util-user-agent-node@npm:3.259.0": - version: 3.259.0 - resolution: "@aws-sdk/util-user-agent-node@npm:3.259.0" +"@aws-sdk/util-user-agent-node@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-user-agent-node@npm:3.272.0" dependencies: - "@aws-sdk/node-config-provider": 3.259.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/node-config-provider": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 peerDependencies: aws-crt: ">=1.0.0" peerDependenciesMeta: aws-crt: optional: true - checksum: ed2ae75ef0ccd5f58f16887c8cfd521006e8efaa8431420d1b55c3f885c501bbb06e6a4f262c0239a88fbec9100923cd277b4539838df9fe9f391c411c5767ee + checksum: 25d5f39349190e6323f893de4f0e7a931751bf1521808210515ef8d951c1a6a3e5f1dc1773cbd5ca9f999c5d00f3a421ad570b5f79b20dc2692012a9f833ff24 languageName: node linkType: hard @@ -1602,14 +1602,14 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-waiter@npm:3.257.0": - version: 3.257.0 - resolution: "@aws-sdk/util-waiter@npm:3.257.0" +"@aws-sdk/util-waiter@npm:3.272.0": + version: 3.272.0 + resolution: "@aws-sdk/util-waiter@npm:3.272.0" dependencies: - "@aws-sdk/abort-controller": 3.257.0 - "@aws-sdk/types": 3.257.0 + "@aws-sdk/abort-controller": 3.272.0 + "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: 4dd7310ca0b9cdda7c55e3e4a80c7b0b323961ea238cc3ab512e78495d356840ddd5eb0b99add4baf1abf19759ab9ab6bb5d528fe86b61193e0e4f3a854c223b + checksum: e931a9359dc582db9e5dcd62539572aecff5320ce424e5462c2f8d4a2d83acde07f87fe9ffc83850aaf70eaf17b06b6ffd4554350bab0f0f3a4427d1b7e776c6 languageName: node linkType: hard From 65258d85ac99dc8142588b7a88a7c83c3c0ecb98 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 11:17:14 +0000 Subject: [PATCH 271/417] fix(deps): update codemirror to v6.6.0 Signed-off-by: Renovate Bot --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index a4a5521c2c..46be9572f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8993,8 +8993,8 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.4.0 - resolution: "@codemirror/language@npm:6.4.0" + version: 6.6.0 + resolution: "@codemirror/language@npm:6.6.0" dependencies: "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 @@ -9002,7 +9002,7 @@ __metadata: "@lezer/highlight": ^1.0.0 "@lezer/lr": ^1.0.0 style-mod: ^4.0.0 - checksum: 607072e234db59a9a21eb41b8777b62d68a55ed28298edc4f6aaedfcf52349db1fe3ff3e7747ccfc77f03757bad45ba9a657d59a0e9c67be1231902586dec7a3 + checksum: bb9411620e2f231653a3f0c4429e0d19a3843bff5dbc117df4649d7bf783ec4ad809c0add8bc0887a4ec3f48b4f8f941621168e47d76101d5383f0d670af1722 languageName: node linkType: hard @@ -9057,13 +9057,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0": - version: 6.7.3 - resolution: "@codemirror/view@npm:6.7.3" + version: 6.9.1 + resolution: "@codemirror/view@npm:6.9.1" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.0.0 w3c-keyname: ^2.2.4 - checksum: 37c0458cf45e52a1af9b9bef29108dd84bb91c6818ecad432d89627039d92f6b234b033cf14ecbc1c5b533694127478942fcc9641fdf52b9a1b20eccc018e27c + checksum: 485d54d338a27ebde6bec489e3008db80a2a801fe27db0d4a3c70181c8739f806f035855ba13d5b311d186ad2b130db07196e8b465ec102b0142df0689bff2f8 languageName: node linkType: hard From 007fa56c0c1e0c858f9b8433ce5eed00f7facb93 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Mon, 20 Feb 2023 12:54:39 +0100 Subject: [PATCH 272/417] Add another missing dependency Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/package.json | 1 + yarn.lock | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index d35a178f5e..047f325316 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -23,6 +23,7 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { + "@backstage/catalog-model": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 96b7078aaa..60f6b8a9e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6953,6 +6953,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-octopus-deploy@workspace:plugins/octopus-deploy" dependencies: + "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" "@backstage/core-components": "workspace:^" From 6f25fd07d60671f09f1a7efa148c7c4269bb621a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 12:04:08 +0000 Subject: [PATCH 273/417] fix(deps): update dependency @google-cloud/container to v4.7.1 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c36974df7f..3f379369c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9738,11 +9738,11 @@ __metadata: linkType: hard "@google-cloud/container@npm:^4.0.0": - version: 4.4.0 - resolution: "@google-cloud/container@npm:4.4.0" + version: 4.7.1 + resolution: "@google-cloud/container@npm:4.7.1" dependencies: google-gax: ^3.5.2 - checksum: 39e7ba3b8cd7e50908315eee5c42461b8cee909c5653ffc817503757e867d63815c5ca8f540b7566f38be9ae0454ed89d2efe95b64961a8692a9348ddf92074f + checksum: e622ddc2522fcffadd72a0cc6fa3f12e6a337b9e53ff1886a2057a8d4f3f0fc13b60b806c35946da0a1211fe52d66f65b4ab59c06b5e7cd725cd588477c0bde1 languageName: node linkType: hard From 6a28b421df84f1d6a24f877dc0bb7ca89a1a8fd2 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Mon, 20 Feb 2023 08:40:00 -0500 Subject: [PATCH 274/417] update serviceRef names to adhere to naming convention Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/todo-backend/package.json | 1 + plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts | 4 ++-- plugins/todo-backend/src/lib/TodoReader/index.ts | 2 +- plugins/todo-backend/src/plugin.ts | 4 ++-- plugins/todo-backend/src/service/TodoReaderService.ts | 6 +++--- plugins/todo-backend/src/service/types.ts | 8 -------- yarn.lock | 1 + 7 files changed, 10 insertions(+), 16 deletions(-) diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 51c3f8ede8..e3e15e4f06 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -36,6 +36,7 @@ "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", + "@backstage/plugin-catalog-node": "workspace:^", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts index d364316ae1..2804da98cc 100644 --- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts +++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts @@ -176,8 +176,8 @@ export class TodoScmReader implements TodoReader { /** * @alpha */ -export const todoScmReaderRef = createServiceRef({ - id: 'todoScmReaderFactory', +export const todoReaderServiceRef = createServiceRef({ + id: 'todo.todoReader', defaultFactory: async service => createServiceFactory({ service, diff --git a/plugins/todo-backend/src/lib/TodoReader/index.ts b/plugins/todo-backend/src/lib/TodoReader/index.ts index a56d5805d5..a325fcbe65 100644 --- a/plugins/todo-backend/src/lib/TodoReader/index.ts +++ b/plugins/todo-backend/src/lib/TodoReader/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export { TodoScmReader, todoScmReaderRef } from './TodoScmReader'; +export { TodoScmReader, todoReaderServiceRef } from './TodoScmReader'; export type { TodoScmReaderOptions } from './TodoScmReader'; export { createTodoParser } from './createTodoParser'; export type { TodoParserOptions } from './createTodoParser'; diff --git a/plugins/todo-backend/src/plugin.ts b/plugins/todo-backend/src/plugin.ts index cb25d3ddf0..cbb581f336 100644 --- a/plugins/todo-backend/src/plugin.ts +++ b/plugins/todo-backend/src/plugin.ts @@ -19,7 +19,7 @@ import { coreServices, } from '@backstage/backend-plugin-api'; -import { todoReaderServiceRef } from './service/TodoReaderService'; +import { todoServiceRef } from './service/TodoReaderService'; import { createRouter } from './service/router'; /** @@ -31,7 +31,7 @@ export const todoPlugin = createBackendPlugin({ register(env) { env.registerInit({ deps: { - todoReader: todoReaderServiceRef, + todoReader: todoServiceRef, http: coreServices.httpRouter, }, async init({ http, todoReader }) { diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index b3ed793d38..c5fa0aa70b 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -27,7 +27,7 @@ import { } from '@backstage/backend-plugin-api'; import { catalogServiceRef } from '@backstage/plugin-catalog-node'; -import { TodoReader, todoScmReaderRef } from '../lib'; +import { TodoReader, todoReaderServiceRef } from '../lib'; import { ListTodosRequest, ListTodosResponse, TodoService } from './types'; const DEFAULT_DEFAULT_PAGE_SIZE = 10; @@ -138,7 +138,7 @@ export class TodoReaderService implements TodoService { } } -export const todoReaderServiceRef: ServiceRef = +export const todoServiceRef: ServiceRef = createServiceRef({ id: 'todo.client', defaultFactory: async service => @@ -146,7 +146,7 @@ export const todoReaderServiceRef: ServiceRef = service, deps: { catalogApi: catalogServiceRef, - todoReader: todoScmReaderRef, + todoReader: todoReaderServiceRef, }, async factory({ catalogApi, todoReader }) { const todoReaderService = new TodoReaderService({ diff --git a/plugins/todo-backend/src/service/types.ts b/plugins/todo-backend/src/service/types.ts index 6b56487605..a6c54b9d87 100644 --- a/plugins/todo-backend/src/service/types.ts +++ b/plugins/todo-backend/src/service/types.ts @@ -57,11 +57,3 @@ export const TODO_FIELDS = [ 'viewUrl', 'repoFilePath', ] as const; - -/** - * @alpha - */ -export type TodosPluginDependencies = { - todoReader: TodoService; - http: HttpRouterService; -}; diff --git a/yarn.lock b/yarn.lock index 8404d7958f..b0ccfe6ec2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8383,6 +8383,7 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" + "@backstage/plugin-catalog-node": "workspace:^" "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 express: ^4.17.1 From 2c234a893256470ff19b0ac81e9c3c61eb6c51b9 Mon Sep 17 00:00:00 2001 From: Heikki Hellgren Date: Mon, 20 Feb 2023 09:20:42 +0200 Subject: [PATCH 275/417] fix: restore support for custom MS graph API url relates to #16361 Signed-off-by: Heikki Hellgren --- .changeset/slow-suits-grab.md | 5 +++++ .../src/microsoftGraph/client.test.ts | 2 +- .../src/microsoftGraph/client.ts | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .changeset/slow-suits-grab.md diff --git a/.changeset/slow-suits-grab.md b/.changeset/slow-suits-grab.md new file mode 100644 index 0000000000..4a741cac6b --- /dev/null +++ b/.changeset/slow-suits-grab.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +properly support custom graph api URL diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts index f621b4d924..6d63537b54 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts @@ -53,7 +53,7 @@ describe('MicrosoftGraphClient', () => { expect(await response.json()).toEqual({ value: 'example' }); expect(tokenCredential.getToken).toHaveBeenCalledTimes(1); expect(tokenCredential.getToken).toHaveBeenCalledWith( - 'https://graph.microsoft.com/.default', + 'https://other.example.com/.default', ); }); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts index c644e545d6..4acf7c726e 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts @@ -218,8 +218,9 @@ export class MicrosoftGraphClient { headers?: Record, ): Promise { // Make sure that we always have a valid access token (might be cached) + const urlObj = new URL(url); const token = await this.tokenCredential.getToken( - 'https://graph.microsoft.com/.default', + `${urlObj.protocol}//${urlObj.hostname}/.default`, ); if (!token) { From 604e17e09bb2cd5741d9372bf6dd5ca1cbda1e6b Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Mon, 20 Feb 2023 08:51:55 -0500 Subject: [PATCH 276/417] remove unused import Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/todo-backend/src/service/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/todo-backend/src/service/types.ts b/plugins/todo-backend/src/service/types.ts index a6c54b9d87..ab15e20027 100644 --- a/plugins/todo-backend/src/service/types.ts +++ b/plugins/todo-backend/src/service/types.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import type { HttpRouterService } from '@backstage/backend-plugin-api'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { TodoItem } from '../lib'; From fe259c1c01af2a934b50f1a938a63608c06af547 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Mon, 20 Feb 2023 08:58:08 -0500 Subject: [PATCH 277/417] update dependencies Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- packages/backend-next/package.json | 3 ++- yarn.lock | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 578cee8ad9..a76d7e1dd3 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -28,7 +28,8 @@ "@backstage/backend-defaults": "workspace:^", "@backstage/plugin-app-backend": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^", - "@backstage/plugin-scaffolder-backend": "workspace:^" + "@backstage/plugin-scaffolder-backend": "workspace:^", + "@backstage/plugin-todo-backend": "workspace:^" }, "devDependencies": { "@backstage/cli": "workspace:^" diff --git a/yarn.lock b/yarn.lock index b0ccfe6ec2..e078ec43d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22455,6 +22455,7 @@ __metadata: "@backstage/plugin-app-backend": "workspace:^" "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-scaffolder-backend": "workspace:^" + "@backstage/plugin-todo-backend": "workspace:^" languageName: unknown linkType: soft From 2b0387915daf698d7f268224772140557b77e774 Mon Sep 17 00:00:00 2001 From: Oleg S <97077423+RobotSail@users.noreply.github.com> Date: Mon, 20 Feb 2023 09:13:52 -0500 Subject: [PATCH 278/417] update api report Signed-off-by: Oleg S <97077423+RobotSail@users.noreply.github.com> --- plugins/todo-backend/api-report.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index 3908d2475b..dabe2fbfd4 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -118,6 +118,9 @@ export type TodoReaderServiceOptions = { defaultPageSize?: number; }; +// @alpha (undocumented) +export const todoReaderServiceRef: ServiceRef; + // @public (undocumented) export class TodoScmReader implements TodoReader { constructor(options: TodoScmReaderOptions); @@ -139,9 +142,6 @@ export type TodoScmReaderOptions = { filePathFilter?: (filePath: string) => boolean; }; -// @alpha (undocumented) -export const todoScmReaderRef: ServiceRef; - // @public (undocumented) export interface TodoService { // (undocumented) From 2aa93450f9256f8133dcdc8af7c30b8ab4207b1a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 14:26:21 +0000 Subject: [PATCH 279/417] fix(deps): update dependency @roadiehq/backstage-plugin-github-pull-requests to v2.5.1 Signed-off-by: Renovate Bot --- yarn.lock | 97 +++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3f379369c7..402629e14d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11691,7 +11691,7 @@ __metadata: languageName: node linkType: hard -"@mswjs/cookies@npm:^0.2.0, @mswjs/cookies@npm:^0.2.2": +"@mswjs/cookies@npm:^0.2.2": version: 0.2.2 resolution: "@mswjs/cookies@npm:0.2.2" dependencies: @@ -11701,20 +11701,6 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.15.1": - version: 0.15.3 - resolution: "@mswjs/interceptors@npm:0.15.3" - dependencies: - "@open-draft/until": ^1.0.3 - "@xmldom/xmldom": ^0.7.5 - debug: ^4.3.3 - headers-polyfill: ^3.0.4 - outvariant: ^1.2.1 - strict-event-emitter: ^0.2.0 - checksum: 4c8e1d16f4a7b6133c02f1e13e9fc20af82dfa90106209036a9b3d85bb6ef4cce3b41312abde4bc9ccf59aa0b448e506d670bc6877b2ba25aad4f4b348d1454a - languageName: node - linkType: hard - "@mswjs/interceptors@npm:^0.17.5": version: 0.17.5 resolution: "@mswjs/interceptors@npm:0.17.5" @@ -12951,8 +12937,8 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-github-pull-requests@npm:^2.2.7": - version: 2.4.3 - resolution: "@roadiehq/backstage-plugin-github-pull-requests@npm:2.4.3" + version: 2.5.1 + resolution: "@roadiehq/backstage-plugin-github-pull-requests@npm:2.5.1" dependencies: "@backstage/catalog-model": ^1.1.5 "@backstage/core-components": ^0.12.3 @@ -12968,14 +12954,14 @@ __metadata: history: ^5.0.0 lodash: ^4.17.21 moment: ^2.27.0 - msw: ^0.39.2 + msw: ^1.0.1 node-fetch: ^2.6.1 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 - checksum: 3d2d5d754921835088f1a34339e67938d3abdf673e267ee347526dac6c03afd4e0fdceca38090625654427c211ac2f52e78a7d2cad2347b56198bcfb9e00b95e + checksum: 769991ac46d4466261f2765eaab6eca903e751dc003d94a21dfb0376fca69af8edb2a8b9b12b375e903694278d32a95f8745d1f724a19429df34adeb3fb3e58c languageName: node linkType: hard @@ -24282,7 +24268,7 @@ __metadata: languageName: node linkType: hard -"graphql@npm:^15.0.0 || ^16.0.0, graphql@npm:^16.0.0, graphql@npm:^16.3.0": +"graphql@npm:^15.0.0 || ^16.0.0, graphql@npm:^16.0.0": version: 16.6.0 resolution: "graphql@npm:16.6.0" checksum: bf1d9e3c1938ce3c1a81e909bd3ead1ae4707c577f91cff1ca2eca474bfbc7873d5d7b942e1e9777ff5a8304421dba57a4b76d7a29eb19de8711cb70e3c2415e @@ -24531,7 +24517,7 @@ __metadata: languageName: node linkType: hard -"headers-polyfill@npm:^3.0.4, headers-polyfill@npm:^3.1.0": +"headers-polyfill@npm:^3.1.0": version: 3.1.0 resolution: "headers-polyfill@npm:3.1.0" checksum: a95257065684653b7185efbb9a380c547ea832002991b5adf0d90cd222073da2701be9dc2849d1970ecf15e8c35b383984358566afe6e76ca8ff1dbd7cdce3af @@ -29760,35 +29746,6 @@ __metadata: languageName: node linkType: hard -"msw@npm:^0.39.2": - version: 0.39.2 - resolution: "msw@npm:0.39.2" - dependencies: - "@mswjs/cookies": ^0.2.0 - "@mswjs/interceptors": ^0.15.1 - "@open-draft/until": ^1.0.3 - "@types/cookie": ^0.4.1 - "@types/js-levenshtein": ^1.1.1 - chalk: 4.1.1 - chokidar: ^3.4.2 - cookie: ^0.4.2 - graphql: ^16.3.0 - headers-polyfill: ^3.0.4 - inquirer: ^8.2.0 - is-node-process: ^1.0.1 - js-levenshtein: ^1.1.6 - node-fetch: ^2.6.7 - path-to-regexp: ^6.2.0 - statuses: ^2.0.0 - strict-event-emitter: ^0.2.0 - type-fest: ^1.2.2 - yargs: ^17.3.1 - bin: - msw: cli/index.js - checksum: 4802f5568cbaadedd488f03b953523fb5dd7e1b8e48a85f142d7cfd1b8c25241729a0af4a06b9f2be543c18b67475c8777fa4924bdc6f1de19dbe142ea4a8405 - languageName: node - linkType: hard - "msw@npm:^0.49.0": version: 0.49.3 resolution: "msw@npm:0.49.3" @@ -29823,6 +29780,40 @@ __metadata: languageName: node linkType: hard +"msw@npm:^1.0.1": + version: 1.0.1 + resolution: "msw@npm:1.0.1" + dependencies: + "@mswjs/cookies": ^0.2.2 + "@mswjs/interceptors": ^0.17.5 + "@open-draft/until": ^1.0.3 + "@types/cookie": ^0.4.1 + "@types/js-levenshtein": ^1.1.1 + chalk: 4.1.1 + chokidar: ^3.4.2 + cookie: ^0.4.2 + graphql: ^15.0.0 || ^16.0.0 + headers-polyfill: ^3.1.0 + inquirer: ^8.2.0 + is-node-process: ^1.0.1 + js-levenshtein: ^1.1.6 + node-fetch: ^2.6.7 + outvariant: ^1.3.0 + path-to-regexp: ^6.2.0 + strict-event-emitter: ^0.4.3 + type-fest: ^2.19.0 + yargs: ^17.3.1 + peerDependencies: + typescript: ">= 4.4.x <= 4.9.x" + peerDependenciesMeta: + typescript: + optional: true + bin: + msw: cli/index.js + checksum: e5d6cbe67067ca46f42aaa33011f53a4e5a873abcf81c52a6996536b3c41a88f522821d3a4cf589658252581506afddb58fd8c3dfd79a5cbf06e26e14f9570b6 + languageName: node + linkType: hard + "multicast-dns@npm:^7.2.4": version: 7.2.4 resolution: "multicast-dns@npm:7.2.4" @@ -35786,7 +35777,7 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1, statuses@npm:^2.0.0": +"statuses@npm:2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb @@ -35888,7 +35879,7 @@ __metadata: languageName: node linkType: hard -"strict-event-emitter@npm:^0.2.0, strict-event-emitter@npm:^0.2.4": +"strict-event-emitter@npm:^0.2.4": version: 0.2.7 resolution: "strict-event-emitter@npm:0.2.7" dependencies: @@ -37289,7 +37280,7 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^1.2.1, type-fest@npm:^1.2.2": +"type-fest@npm:^1.2.1": version: 1.4.0 resolution: "type-fest@npm:1.4.0" checksum: b011c3388665b097ae6a109a437a04d6f61d81b7357f74cbcb02246f2f5bd72b888ae33631b99871388122ba0a87f4ff1c94078e7119ff22c70e52c0ff828201 From 122a37a880e851aa374af4f1200e300ac005d68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 20 Feb 2023 15:11:03 +0100 Subject: [PATCH 280/417] fixup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/rare-pandas-hope.md | 5 +++++ .../PlaylistPage/AddEntitiesDrawer.tsx | 22 +++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 .changeset/rare-pandas-hope.md diff --git a/.changeset/rare-pandas-hope.md b/.changeset/rare-pandas-hope.md new file mode 100644 index 0000000000..6e8e81fcfb --- /dev/null +++ b/.changeset/rare-pandas-hope.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-playlist': patch +--- + +Internal update to work with newer versions of react-router diff --git a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx index 05dd4da231..fe08870bcd 100644 --- a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx +++ b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx @@ -102,12 +102,16 @@ export const AddEntitiesDrawer = ({ const entityRoute = useRouteRef(entityRouteRef); const entityLocationRegex = useMemo(() => { const forwardSlashRegex = new RegExp('/', 'g'); + // We need to do this in two steps, since entityRoute will ruin some special chars, like question marks const locationRegex = entityRoute({ - namespace: '(?.+?)', - kind: '(?.+?)', - name: '(?.+?)', - }).replace(forwardSlashRegex, '\\/'); - + namespace: '__REPLACE_WITH_NAMESPACE__', + kind: '__REPLACE_WITH_KIND__', + name: '__REPLACE_WITH_NAME__', + }) + .replace('__REPLACE_WITH_NAMESPACE__', '(?.+?)') + .replace('__REPLACE_WITH_KIND__', '(?.+?)') + .replace('__REPLACE_WITH_NAME__', '(?.+?)') + .replace(forwardSlashRegex, '\\/'); return new RegExp(`${locationRegex}$`); }, [entityRoute]); @@ -127,12 +131,12 @@ export const AddEntitiesDrawer = ({ const addEntity = useCallback( entityResult => { - // TODO (kuangp): this parsing of the location is not great. Ideally `CatalogEntityDocument` + // TODO(kuangp): this parsing of the location is not great. Ideally `CatalogEntityDocument` // contains the `metadata.name` field so we can derive the full ref and we only fall back to // parsing location if it's missing (ie. for older versions) - const { groups } = entityResult.location.match(entityLocationRegex); - if (groups) { - onAdd(stringifyEntityRef(groups)); + const match = entityResult.location.match(entityLocationRegex); + if (match?.groups) { + onAdd(stringifyEntityRef(match?.groups)); } else { // eslint-disable-next-line no-console console.error( From daf2f962cda785c2556af4f8dffe85e649542842 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 15:09:04 +0000 Subject: [PATCH 281/417] fix(deps): update dependency core-js to v3.28.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 402629e14d..568a99319d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19475,9 +19475,9 @@ __metadata: linkType: hard "core-js@npm:^3.6.5": - version: 3.27.2 - resolution: "core-js@npm:3.27.2" - checksum: 718debd426f55a6b97cf9b757c936be258afd6d4f7052f89d0f96c982d7013e9000b0b006df42831a0cf32adad298e34d6a19052dce9ae1c7ab87162c0c665e0 + version: 3.28.0 + resolution: "core-js@npm:3.28.0" + checksum: 3155fd0ec16d0089106b145e9595280a4ea4bde0d7ff26aa14364cd4f1c203baf6620c3025acd284f363d08b9f21104101692766ca9a36ffeee7307bdf3e1881 languageName: node linkType: hard From ac87afa070baa2c34e3f1fe2c2a3c1b3091c57aa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 15:10:17 +0000 Subject: [PATCH 282/417] fix(deps): update dependency cronstrue to v2.23.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 402629e14d..9afda260a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19641,11 +19641,11 @@ __metadata: linkType: hard "cronstrue@npm:^2.2.0": - version: 2.22.0 - resolution: "cronstrue@npm:2.22.0" + version: 2.23.0 + resolution: "cronstrue@npm:2.23.0" bin: cronstrue: bin/cli.js - checksum: 5017cccddee819c162d3b71c2a517c2468834f6454e9ce6a21016149848a69cf7f7433584c61dd1b92adea79ea461da291d32f48129c0a5ccef93019be93494f + checksum: 050140ac6452468d6f9032f18038f41b16968502d411a996efd5d42243cfd882271ff20ed4a3cdb25c45bf8f88beeb0579e45e974a11987401e9d383af2641a8 languageName: node linkType: hard From d3d624e8e8d43ed94f41124894fee37db1e3f23f Mon Sep 17 00:00:00 2001 From: martincostello Date: Mon, 20 Feb 2023 17:34:34 +0000 Subject: [PATCH 283/417] Update SonarQube card icons - If there are no vulnerabilities, show a closed lock. - If there are no code smells, show a happy face. Signed-off-by: martincostello --- .changeset/thin-candles-wait.md | 5 +++++ .../src/components/SonarQubeCard/SonarQubeCard.tsx | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 .changeset/thin-candles-wait.md diff --git a/.changeset/thin-candles-wait.md b/.changeset/thin-candles-wait.md new file mode 100644 index 0000000000..c7e18367b5 --- /dev/null +++ b/.changeset/thin-candles-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-sonarqube': patch +--- + +Show a more appropriate icon if there are no code smells and/or vulnerabilities. diff --git a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx index 900c8d082c..f37bd6eda5 100644 --- a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx +++ b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx @@ -23,9 +23,11 @@ import { import { Chip, Grid } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import BugReport from '@material-ui/icons/BugReport'; +import Lock from '@material-ui/icons/Lock'; import LockOpen from '@material-ui/icons/LockOpen'; import Security from '@material-ui/icons/Security'; import SentimentVeryDissatisfied from '@material-ui/icons/SentimentVeryDissatisfied'; +import SentimentVerySatisfied from '@material-ui/icons/SentimentVerySatisfied'; import React, { useMemo } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { Percentage } from './Percentage'; @@ -200,14 +202,22 @@ export const SonarQubeCard = (props: { rightSlot={} /> } + titleIcon={ + value.metrics.vulnerabilities === '0' ? : + } title="Vulnerabilities" link={value.getIssuesUrl('VULNERABILITY')} leftSlot={} rightSlot={} /> } + titleIcon={ + value.metrics.code_smells === '0' ? ( + + ) : ( + + ) + } title="Code Smells" link={value.getIssuesUrl('CODE_SMELL')} leftSlot={} From e949b827af7fd5658dd55697c5077beba7fda7c3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 20:47:33 +0000 Subject: [PATCH 284/417] chore(deps): update dependency esbuild to v0.17.10 Signed-off-by: Renovate Bot --- yarn.lock | 182 +++++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 91 deletions(-) diff --git a/yarn.lock b/yarn.lock index 68b57702bb..150c5341d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9265,9 +9265,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/android-arm64@npm:0.17.8" +"@esbuild/android-arm64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/android-arm64@npm:0.17.10" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -9286,9 +9286,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/android-arm@npm:0.17.8" +"@esbuild/android-arm@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/android-arm@npm:0.17.10" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -9300,9 +9300,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/android-x64@npm:0.17.8" +"@esbuild/android-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/android-x64@npm:0.17.10" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -9314,9 +9314,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/darwin-arm64@npm:0.17.8" +"@esbuild/darwin-arm64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/darwin-arm64@npm:0.17.10" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -9328,9 +9328,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/darwin-x64@npm:0.17.8" +"@esbuild/darwin-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/darwin-x64@npm:0.17.10" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -9342,9 +9342,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/freebsd-arm64@npm:0.17.8" +"@esbuild/freebsd-arm64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/freebsd-arm64@npm:0.17.10" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -9356,9 +9356,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/freebsd-x64@npm:0.17.8" +"@esbuild/freebsd-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/freebsd-x64@npm:0.17.10" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -9370,9 +9370,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-arm64@npm:0.17.8" +"@esbuild/linux-arm64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-arm64@npm:0.17.10" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -9384,9 +9384,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-arm@npm:0.17.8" +"@esbuild/linux-arm@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-arm@npm:0.17.10" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -9398,9 +9398,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-ia32@npm:0.17.8" +"@esbuild/linux-ia32@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-ia32@npm:0.17.10" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -9419,9 +9419,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-loong64@npm:0.17.8" +"@esbuild/linux-loong64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-loong64@npm:0.17.10" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -9433,9 +9433,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-mips64el@npm:0.17.8" +"@esbuild/linux-mips64el@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-mips64el@npm:0.17.10" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -9447,9 +9447,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-ppc64@npm:0.17.8" +"@esbuild/linux-ppc64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-ppc64@npm:0.17.10" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -9461,9 +9461,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-riscv64@npm:0.17.8" +"@esbuild/linux-riscv64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-riscv64@npm:0.17.10" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -9475,9 +9475,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-s390x@npm:0.17.8" +"@esbuild/linux-s390x@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-s390x@npm:0.17.10" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -9489,9 +9489,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/linux-x64@npm:0.17.8" +"@esbuild/linux-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/linux-x64@npm:0.17.10" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -9503,9 +9503,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/netbsd-x64@npm:0.17.8" +"@esbuild/netbsd-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/netbsd-x64@npm:0.17.10" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -9517,9 +9517,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/openbsd-x64@npm:0.17.8" +"@esbuild/openbsd-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/openbsd-x64@npm:0.17.10" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -9531,9 +9531,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/sunos-x64@npm:0.17.8" +"@esbuild/sunos-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/sunos-x64@npm:0.17.10" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -9545,9 +9545,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/win32-arm64@npm:0.17.8" +"@esbuild/win32-arm64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/win32-arm64@npm:0.17.10" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -9559,9 +9559,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/win32-ia32@npm:0.17.8" +"@esbuild/win32-ia32@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/win32-ia32@npm:0.17.10" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -9573,9 +9573,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.17.8": - version: 0.17.8 - resolution: "@esbuild/win32-x64@npm:0.17.8" +"@esbuild/win32-x64@npm:0.17.10": + version: 0.17.10 + resolution: "@esbuild/win32-x64@npm:0.17.10" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -21658,31 +21658,31 @@ __metadata: linkType: hard "esbuild@npm:^0.17.0": - version: 0.17.8 - resolution: "esbuild@npm:0.17.8" + version: 0.17.10 + resolution: "esbuild@npm:0.17.10" dependencies: - "@esbuild/android-arm": 0.17.8 - "@esbuild/android-arm64": 0.17.8 - "@esbuild/android-x64": 0.17.8 - "@esbuild/darwin-arm64": 0.17.8 - "@esbuild/darwin-x64": 0.17.8 - "@esbuild/freebsd-arm64": 0.17.8 - "@esbuild/freebsd-x64": 0.17.8 - "@esbuild/linux-arm": 0.17.8 - "@esbuild/linux-arm64": 0.17.8 - "@esbuild/linux-ia32": 0.17.8 - "@esbuild/linux-loong64": 0.17.8 - "@esbuild/linux-mips64el": 0.17.8 - "@esbuild/linux-ppc64": 0.17.8 - "@esbuild/linux-riscv64": 0.17.8 - "@esbuild/linux-s390x": 0.17.8 - "@esbuild/linux-x64": 0.17.8 - "@esbuild/netbsd-x64": 0.17.8 - "@esbuild/openbsd-x64": 0.17.8 - "@esbuild/sunos-x64": 0.17.8 - "@esbuild/win32-arm64": 0.17.8 - "@esbuild/win32-ia32": 0.17.8 - "@esbuild/win32-x64": 0.17.8 + "@esbuild/android-arm": 0.17.10 + "@esbuild/android-arm64": 0.17.10 + "@esbuild/android-x64": 0.17.10 + "@esbuild/darwin-arm64": 0.17.10 + "@esbuild/darwin-x64": 0.17.10 + "@esbuild/freebsd-arm64": 0.17.10 + "@esbuild/freebsd-x64": 0.17.10 + "@esbuild/linux-arm": 0.17.10 + "@esbuild/linux-arm64": 0.17.10 + "@esbuild/linux-ia32": 0.17.10 + "@esbuild/linux-loong64": 0.17.10 + "@esbuild/linux-mips64el": 0.17.10 + "@esbuild/linux-ppc64": 0.17.10 + "@esbuild/linux-riscv64": 0.17.10 + "@esbuild/linux-s390x": 0.17.10 + "@esbuild/linux-x64": 0.17.10 + "@esbuild/netbsd-x64": 0.17.10 + "@esbuild/openbsd-x64": 0.17.10 + "@esbuild/sunos-x64": 0.17.10 + "@esbuild/win32-arm64": 0.17.10 + "@esbuild/win32-ia32": 0.17.10 + "@esbuild/win32-x64": 0.17.10 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -21730,7 +21730,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: d09776fcf3da2726975d0d3c11afe0a1db2a8fbb88cbcb25d97f269a1e58f17fa04cb881b9189195d8e76b8a1cfb165e990e27527ae0366f6dc2721fb0ed0af9 + checksum: 803de327036528c140b3d1d8e148604fd1446062b63d2b5a49cd8fe5fa607dc41be915f28dec1242be77164378e3ca27a2ed2968692a73cc833896c7bebc0e12 languageName: node linkType: hard From 0a7327454bdc95c1c70916e7115a558d3d5451a5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 20:48:05 +0000 Subject: [PATCH 285/417] fix(deps): update dependency dataloader to v2.2.2 Signed-off-by: Renovate Bot --- yarn.lock | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 68b57702bb..cec9d86f1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20323,13 +20323,20 @@ __metadata: languageName: node linkType: hard -"dataloader@npm:2.1.0, dataloader@npm:^2.0.0": +"dataloader@npm:2.1.0": version: 2.1.0 resolution: "dataloader@npm:2.1.0" checksum: bbd43496c41697766f8611f60ed3bae437b450985499140b9603a2447c10d45975d3a0661caaebaa9750bc1bc9fd154676a314423294916c8b8ca1a59a08d139 languageName: node linkType: hard +"dataloader@npm:^2.0.0": + version: 2.2.2 + resolution: "dataloader@npm:2.2.2" + checksum: 4dabd247089c29f194e94d5434d504f99156c5c214a03463c20f3f17f40398d7e179edee69a27c16e315519ac8739042a810090087ae26449a0e685156a02c65 + languageName: node + linkType: hard + "date-fns@npm:^2.16.1, date-fns@npm:^2.18.0, date-fns@npm:^2.29.1": version: 2.29.3 resolution: "date-fns@npm:2.29.3" From 507b2f1de18bda6def4deeccc563aa67a593062d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 21:28:00 +0000 Subject: [PATCH 286/417] fix(deps): update dependency jose to v4.12.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 150c5341d2..3badbcd025 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26820,9 +26820,9 @@ __metadata: linkType: hard "jose@npm:^4.10.0, jose@npm:^4.6.0": - version: 4.11.4 - resolution: "jose@npm:4.11.4" - checksum: ab870d61e3721cfa1059b1a79cfc2fce06586c8afd4164362e1725934a635191bd938893ebdfac55a0811efbe9b6fd650bbf82d36d87e8a0b7cb4b0379328dab + version: 4.12.0 + resolution: "jose@npm:4.12.0" + checksum: 09e67611768127ab54b6b507401de4b1f87e1e285cf2c2fc917e931e001b7e584c90081b421f483f13a6eec4fc44936e4a5f4b8ae2d59928061e886e35d33fa2 languageName: node linkType: hard From 588b621b571299a6737a169ca30d8b0cb853bbd2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 22:19:40 +0000 Subject: [PATCH 287/417] fix(deps): update dependency logform to v2.5.1 Signed-off-by: Renovate Bot --- yarn.lock | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 929ee912a4..0bf1a2fcd9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15630,6 +15630,13 @@ __metadata: languageName: node linkType: hard +"@types/triple-beam@npm:^1.3.2": + version: 1.3.2 + resolution: "@types/triple-beam@npm:1.3.2" + checksum: dd7b4a563fb710abc992e5d59eac481bed9e303fada2e276e37b00be31c392e03300ee468e57761e616512872e77935f92472877d0704a19688d15a726cee17b + languageName: node + linkType: hard + "@types/trusted-types@npm:*": version: 2.0.2 resolution: "@types/trusted-types@npm:2.0.2" @@ -28342,15 +28349,16 @@ __metadata: linkType: hard "logform@npm:^2.3.2, logform@npm:^2.4.0": - version: 2.4.2 - resolution: "logform@npm:2.4.2" + version: 2.5.1 + resolution: "logform@npm:2.5.1" dependencies: "@colors/colors": 1.5.0 + "@types/triple-beam": ^1.3.2 fecha: ^4.2.0 ms: ^2.1.1 safe-stable-stringify: ^2.3.1 triple-beam: ^1.3.0 - checksum: 3d00f4e1ccaf0a86886aabbf66d1f1d207441d5b408f103457da6d64d055aee76c02af4b40a31ca77a1db4cbcdecb007149f731536c39cbd89b7b6ba3dda6d7b + checksum: 08fdf03be5bb69af33bac214eb4f6a0c83ad3821a30de498925fccb61e993e5a4a87470aab356ca2110c11e4643685bed5597ca5f46dd1cd11437c44a0e0e3c2 languageName: node linkType: hard From a8658c12835cbc1fc21d98071c458c314f1c9930 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 22:20:54 +0000 Subject: [PATCH 288/417] fix(deps): update dependency openid-client to v5.4.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 929ee912a4..0ab67bda0a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30769,14 +30769,14 @@ __metadata: linkType: hard "openid-client@npm:^5.2.1, openid-client@npm:^5.3.0": - version: 5.3.2 - resolution: "openid-client@npm:5.3.2" + version: 5.4.0 + resolution: "openid-client@npm:5.4.0" dependencies: jose: ^4.10.0 lru-cache: ^6.0.0 object-hash: ^2.0.1 oidc-token-hash: ^5.0.1 - checksum: 59dc58d5b5cb795f3500f2d9d7ce604f6fb4c00623b16660fdf635d2789c3b2bb32e328ff10c918f9fa4e7fb269c768658d00769761d301be2d96d6150e07051 + checksum: d198dbcaf0aa1d8b9f0f1d99ae30e90ec594eaf9ae668b5d61f2ee9af94a4460968d8dea7e53bd18903a1fb9c445e05aefca965bb88be3688a4bac273d1634d9 languageName: node linkType: hard From 0a770e840041793f7d57b11f4a0e8ae0277f4737 Mon Sep 17 00:00:00 2001 From: Carlos Esteban Lopez Date: Mon, 20 Feb 2023 19:04:14 -0500 Subject: [PATCH 289/417] refactor: CammelCase for folder structure Signed-off-by: Carlos Esteban Lopez --- .../bannerSection.module.scss} | 0 .../bannerSection.tsx} | 2 +- .../bannerSectionGrid.module.scss} | 0 .../bannerSectionGrid.tsx} | 2 +- .../contentBlock.module.scss} | 0 .../content-block.tsx => contentBlock/contentBlock.tsx} | 2 +- microsite-next/src/pages/community/index.tsx | 6 +++--- microsite-next/src/pages/demos/index.tsx | 6 +++--- microsite-next/src/pages/home/_home.tsx | 8 ++++---- ...-new-adopters-form.tsx => _hubSpotNewAdoptersForm.tsx} | 2 +- ...orm.module.scss => hubSpotNewAdoptersForm.module.scss} | 0 .../pages/plugins/{_plugin-card.tsx => _pluginCard.tsx} | 0 microsite-next/src/pages/plugins/index.tsx | 2 +- 13 files changed, 15 insertions(+), 15 deletions(-) rename microsite-next/src/components/{banner-section/banner-section.module.scss => bannerSection/bannerSection.module.scss} (100%) rename microsite-next/src/components/{banner-section/banner-section.tsx => bannerSection/bannerSection.tsx} (93%) rename microsite-next/src/components/{banner-section/banner-section-grid.module.scss => bannerSection/bannerSectionGrid.module.scss} (100%) rename microsite-next/src/components/{banner-section/banner-section-grid.tsx => bannerSection/bannerSectionGrid.tsx} (92%) rename microsite-next/src/components/{content-block/content-block.module.scss => contentBlock/contentBlock.module.scss} (100%) rename microsite-next/src/components/{content-block/content-block.tsx => contentBlock/contentBlock.tsx} (95%) rename microsite-next/src/pages/home/{_hub-spot-new-adopters-form.tsx => _hubSpotNewAdoptersForm.tsx} (94%) rename microsite-next/src/pages/home/{hub-spot-new-adopters-form.module.scss => hubSpotNewAdoptersForm.module.scss} (100%) rename microsite-next/src/pages/plugins/{_plugin-card.tsx => _pluginCard.tsx} (100%) diff --git a/microsite-next/src/components/banner-section/banner-section.module.scss b/microsite-next/src/components/bannerSection/bannerSection.module.scss similarity index 100% rename from microsite-next/src/components/banner-section/banner-section.module.scss rename to microsite-next/src/components/bannerSection/bannerSection.module.scss diff --git a/microsite-next/src/components/banner-section/banner-section.tsx b/microsite-next/src/components/bannerSection/bannerSection.tsx similarity index 93% rename from microsite-next/src/components/banner-section/banner-section.tsx rename to microsite-next/src/components/bannerSection/bannerSection.tsx index 564b1f2043..64c8d246c8 100644 --- a/microsite-next/src/components/banner-section/banner-section.tsx +++ b/microsite-next/src/components/bannerSection/bannerSection.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import React, { PropsWithChildren } from 'react'; -import bannerStyles from './banner-section.module.scss'; +import bannerStyles from './bannerSection.module.scss'; export type IBannerSectionProps = PropsWithChildren<{ className?: string; diff --git a/microsite-next/src/components/banner-section/banner-section-grid.module.scss b/microsite-next/src/components/bannerSection/bannerSectionGrid.module.scss similarity index 100% rename from microsite-next/src/components/banner-section/banner-section-grid.module.scss rename to microsite-next/src/components/bannerSection/bannerSectionGrid.module.scss diff --git a/microsite-next/src/components/banner-section/banner-section-grid.tsx b/microsite-next/src/components/bannerSection/bannerSectionGrid.tsx similarity index 92% rename from microsite-next/src/components/banner-section/banner-section-grid.tsx rename to microsite-next/src/components/bannerSection/bannerSectionGrid.tsx index 7846ffe010..639cc0a97c 100644 --- a/microsite-next/src/components/banner-section/banner-section-grid.tsx +++ b/microsite-next/src/components/bannerSection/bannerSectionGrid.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import React, { PropsWithChildren, ReactNode } from 'react'; -import bannerGridStyles from './banner-section-grid.module.scss'; +import bannerGridStyles from './bannerSectionGrid.module.scss'; export type IBannerSectionColumnsProps = PropsWithChildren<{ header?: ReactNode; diff --git a/microsite-next/src/components/content-block/content-block.module.scss b/microsite-next/src/components/contentBlock/contentBlock.module.scss similarity index 100% rename from microsite-next/src/components/content-block/content-block.module.scss rename to microsite-next/src/components/contentBlock/contentBlock.module.scss diff --git a/microsite-next/src/components/content-block/content-block.tsx b/microsite-next/src/components/contentBlock/contentBlock.tsx similarity index 95% rename from microsite-next/src/components/content-block/content-block.tsx rename to microsite-next/src/components/contentBlock/contentBlock.tsx index ae67070953..aae065db44 100644 --- a/microsite-next/src/components/content-block/content-block.tsx +++ b/microsite-next/src/components/contentBlock/contentBlock.tsx @@ -2,7 +2,7 @@ import Link from '@docusaurus/Link'; import clsx from 'clsx'; import React, { FC, PropsWithChildren, ReactNode } from 'react'; -import contentBlockStyles from './content-block.module.scss'; +import contentBlockStyles from './contentBlock.module.scss'; export interface ContentBlockActionButtonProps { label: string; diff --git a/microsite-next/src/pages/community/index.tsx b/microsite-next/src/pages/community/index.tsx index 595e2b01c8..a6dbf8432b 100644 --- a/microsite-next/src/pages/community/index.tsx +++ b/microsite-next/src/pages/community/index.tsx @@ -1,12 +1,12 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { BannerSection } from '@site/src/components/banner-section/banner-section'; -import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; +import { BannerSection } from '@site/src/components/bannerSection/bannerSection'; +import { BannerSectionGrid } from '@site/src/components/bannerSection/bannerSectionGrid'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; import React from 'react'; -import { ContentBlock } from '../../components/content-block/content-block'; +import { ContentBlock } from '../../components/contentBlock/contentBlock'; import communityStyles from './community.module.scss'; interface ICollectionItem { diff --git a/microsite-next/src/pages/demos/index.tsx b/microsite-next/src/pages/demos/index.tsx index d112ca2c49..2ca77e5c89 100644 --- a/microsite-next/src/pages/demos/index.tsx +++ b/microsite-next/src/pages/demos/index.tsx @@ -1,8 +1,8 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { BannerSection } from '@site/src/components/banner-section/banner-section'; -import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; -import { ContentBlock } from '@site/src/components/content-block/content-block'; +import { BannerSection } from '@site/src/components/bannerSection/bannerSection'; +import { BannerSectionGrid } from '@site/src/components/bannerSection/bannerSectionGrid'; +import { ContentBlock } from '@site/src/components/contentBlock/contentBlock'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; import React from 'react'; diff --git a/microsite-next/src/pages/home/_home.tsx b/microsite-next/src/pages/home/_home.tsx index 7f7f008bc4..4ba5539348 100644 --- a/microsite-next/src/pages/home/_home.tsx +++ b/microsite-next/src/pages/home/_home.tsx @@ -1,15 +1,15 @@ import BrowserOnly from '@docusaurus/BrowserOnly'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import { BannerSection } from '@site/src/components/banner-section/banner-section'; -import { BannerSectionGrid } from '@site/src/components/banner-section/banner-section-grid'; -import { ContentBlock } from '@site/src/components/content-block/content-block'; +import { BannerSection } from '@site/src/components/bannerSection/bannerSection'; +import { BannerSectionGrid } from '@site/src/components/bannerSection/bannerSectionGrid'; +import { ContentBlock } from '@site/src/components/contentBlock/contentBlock'; import Layout from '@theme/Layout'; import { clsx } from 'clsx'; import React, { useState } from 'react'; import homeStyles from './home.module.scss'; -import { HubSpotNewAdoptersForm } from './_hub-spot-new-adopters-form'; +import { HubSpotNewAdoptersForm } from './_hubSpotNewAdoptersForm'; const hiddenNewsletterBannerKey = 'hiddenNewsletterBanner'; diff --git a/microsite-next/src/pages/home/_hub-spot-new-adopters-form.tsx b/microsite-next/src/pages/home/_hubSpotNewAdoptersForm.tsx similarity index 94% rename from microsite-next/src/pages/home/_hub-spot-new-adopters-form.tsx rename to microsite-next/src/pages/home/_hubSpotNewAdoptersForm.tsx index 18b720098f..36f00dff75 100644 --- a/microsite-next/src/pages/home/_hub-spot-new-adopters-form.tsx +++ b/microsite-next/src/pages/home/_hubSpotNewAdoptersForm.tsx @@ -1,7 +1,7 @@ import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; -import hubSpotStyles from './hub-spot-new-adopters-form.module.scss'; +import hubSpotStyles from './hubSpotNewAdoptersForm.module.scss'; export const HubSpotNewAdoptersForm = () => { const [isClosed, setClosed] = useState(true); diff --git a/microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss b/microsite-next/src/pages/home/hubSpotNewAdoptersForm.module.scss similarity index 100% rename from microsite-next/src/pages/home/hub-spot-new-adopters-form.module.scss rename to microsite-next/src/pages/home/hubSpotNewAdoptersForm.module.scss diff --git a/microsite-next/src/pages/plugins/_plugin-card.tsx b/microsite-next/src/pages/plugins/_pluginCard.tsx similarity index 100% rename from microsite-next/src/pages/plugins/_plugin-card.tsx rename to microsite-next/src/pages/plugins/_pluginCard.tsx diff --git a/microsite-next/src/pages/plugins/index.tsx b/microsite-next/src/pages/plugins/index.tsx index 6f19864f93..f8c6f78819 100644 --- a/microsite-next/src/pages/plugins/index.tsx +++ b/microsite-next/src/pages/plugins/index.tsx @@ -3,7 +3,7 @@ import Layout from '@theme/Layout'; import clsx from 'clsx'; import React from 'react'; -import { IPluginData, PluginCard } from './_plugin-card'; +import { IPluginData, PluginCard } from './_pluginCard'; import pluginsStyles from './plugins.module.scss'; //#region Plugin data import From 265fdf03c9ae4287b57006a3de2562b25c267c67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 02:06:02 +0000 Subject: [PATCH 290/417] fix(deps): update dependency yeoman-environment to v3.15.1 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ee6415ebba..7f9ed3d85e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -39126,8 +39126,8 @@ __metadata: linkType: hard "yeoman-environment@npm:^3.9.1": - version: 3.13.0 - resolution: "yeoman-environment@npm:3.13.0" + version: 3.15.1 + resolution: "yeoman-environment@npm:3.15.1" dependencies: "@npmcli/arborist": ^4.0.4 are-we-there-yet: ^2.0.0 @@ -39170,7 +39170,7 @@ __metadata: mem-fs-editor: ^8.1.2 || ^9.0.0 bin: yoe: cli/index.js - checksum: 2d622d18d2e3fff179477b6dabbdee8b380d58b5d639d300c3ace75e0533223cecb9b325baaf0f46f71879eaa5778d64b11fa660403a26ec3086b2a428484ce6 + checksum: 7ea7bb0a210f2e0702f54420916075cda329ee2b71243fb911af9bcfc1e59a934daef1027dd9e95a410f5dae1eeb1fcdb85f4c697a0429477a3a50d2e48d0d58 languageName: node linkType: hard From ec2960b17b9cf48d080c1f8278adc0a672d45dfe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 08:49:09 +0000 Subject: [PATCH 291/417] fix(deps): update typescript-eslint monorepo to v5.53.0 Signed-off-by: Renovate Bot --- yarn.lock | 156 ++++++++++++++++-------------------------------------- 1 file changed, 47 insertions(+), 109 deletions(-) diff --git a/yarn.lock b/yarn.lock index ee6415ebba..554cd67fcf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15776,13 +15776,14 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^5.9.0": - version: 5.48.1 - resolution: "@typescript-eslint/eslint-plugin@npm:5.48.1" + version: 5.53.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.53.0" dependencies: - "@typescript-eslint/scope-manager": 5.48.1 - "@typescript-eslint/type-utils": 5.48.1 - "@typescript-eslint/utils": 5.48.1 + "@typescript-eslint/scope-manager": 5.53.0 + "@typescript-eslint/type-utils": 5.53.0 + "@typescript-eslint/utils": 5.53.0 debug: ^4.3.4 + grapheme-splitter: ^1.0.4 ignore: ^5.2.0 natural-compare-lite: ^1.4.0 regexpp: ^3.2.0 @@ -15794,7 +15795,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: d8d73d123d16fc9b50b500ef21816dcabdffe0d2dcfdb15089dc5a1015d57cbad709de565d1c830f5058c0d7b410069e2554c0b53d1485fe7b237ea8089e58be + checksum: 12dffe65969d8e5248c86a700fe46a737e55ecafb276933e747b4731eab6266fe55e2d43a34b8b340179fe248e127d861cd016a7614b1b9804cd0687c99616d1 languageName: node linkType: hard @@ -15815,39 +15816,29 @@ __metadata: linkType: hard "@typescript-eslint/parser@npm:^5.9.0": - version: 5.48.1 - resolution: "@typescript-eslint/parser@npm:5.48.1" + version: 5.53.0 + resolution: "@typescript-eslint/parser@npm:5.53.0" dependencies: - "@typescript-eslint/scope-manager": 5.48.1 - "@typescript-eslint/types": 5.48.1 - "@typescript-eslint/typescript-estree": 5.48.1 + "@typescript-eslint/scope-manager": 5.53.0 + "@typescript-eslint/types": 5.53.0 + "@typescript-eslint/typescript-estree": 5.53.0 debug: ^4.3.4 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: c624d24eb209b4ce7f0a6c8116712363f10a9c9a5138f240e254ff265526ee4b0fd73b7b6b4b6a0e7611bd9934c42036350dd27f96ae2fa4efdade1a7ebd0e9e + checksum: 979e5d63793a9e64998b1f956ba0f00f8a2674db3a664fafce7b2433323f5248bd776af8305e2419d73a9d94c55176fee099abc5c153b4cc52e5765c725c1edd languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:5.48.1": - version: 5.48.1 - resolution: "@typescript-eslint/scope-manager@npm:5.48.1" +"@typescript-eslint/scope-manager@npm:5.53.0": + version: 5.53.0 + resolution: "@typescript-eslint/scope-manager@npm:5.53.0" dependencies: - "@typescript-eslint/types": 5.48.1 - "@typescript-eslint/visitor-keys": 5.48.1 - checksum: f60a7efe917798cccf8652925de6be58b023ded6c6ee44ce74d074f0c2a1927680398a6d73bab33d500c69474ad8c54d63b90fcc6e13256712707d12a60e0a64 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:5.49.0": - version: 5.49.0 - resolution: "@typescript-eslint/scope-manager@npm:5.49.0" - dependencies: - "@typescript-eslint/types": 5.49.0 - "@typescript-eslint/visitor-keys": 5.49.0 - checksum: 466047e24ff8a4195f14aadde39375f22891bdaced09e58c89f2c32af0aa4a0d87e71a5f006f6ab76858e6f30c4b764b1e0ef7bc26713bb78add30638108c45f + "@typescript-eslint/types": 5.53.0 + "@typescript-eslint/visitor-keys": 5.53.0 + checksum: 51f31dc01e95908611f402441f58404da80a338c0237b2b82f4a7b0b2e8868c4bfe8f7cf44b2567dd56533de609156a5d4ac54bb1f9f09c7014b99428aef2543 languageName: node linkType: hard @@ -15861,12 +15852,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.48.1": - version: 5.48.1 - resolution: "@typescript-eslint/type-utils@npm:5.48.1" +"@typescript-eslint/type-utils@npm:5.53.0": + version: 5.53.0 + resolution: "@typescript-eslint/type-utils@npm:5.53.0" dependencies: - "@typescript-eslint/typescript-estree": 5.48.1 - "@typescript-eslint/utils": 5.48.1 + "@typescript-eslint/typescript-estree": 5.53.0 + "@typescript-eslint/utils": 5.53.0 debug: ^4.3.4 tsutils: ^3.21.0 peerDependencies: @@ -15874,21 +15865,14 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 2739b35caf48c9edbeab82936de58ce0759ab34955ce7eec1786690d6a63146ae0a6c5d9c76034605d9fe200c87a73ede0772c6244c5df6e66df992d9ebbab72 + checksum: 52c40967c5fabd58c2ae8bf519ef89e4feb511e4df630aeaeac8335661a79b6b3a32d30a61a5f1d8acc703f21c4d90751a5d41cda1b35d08867524da11bc2e1d languageName: node linkType: hard -"@typescript-eslint/types@npm:5.48.1": - version: 5.48.1 - resolution: "@typescript-eslint/types@npm:5.48.1" - checksum: 8437986e9d86d792b23327517ae2f9861ec55992d5a9cd55991e525409b6244169436cd708f3987ab7c579e45e59b6eab5a9d3583f7729219e25691164293094 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.49.0": - version: 5.49.0 - resolution: "@typescript-eslint/types@npm:5.49.0" - checksum: 41f72a043007fc3f3356b5a38d7bfa54871545b4a309810a062f044cff25122413a9660ce6d83d1221762f60d067351d020b0cb68f7e1279817f53e77ce8f33d +"@typescript-eslint/types@npm:5.53.0": + version: 5.53.0 + resolution: "@typescript-eslint/types@npm:5.53.0" + checksum: b0eaf23de4ab13697d4d2095838c959a3f410c30f0d19091e5ca08e62320c3cc3c72bcb631823fb6a4fbb31db0a059e386a0801244930d0a88a6a698e5f46548 languageName: node linkType: hard @@ -15899,12 +15883,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.48.1": - version: 5.48.1 - resolution: "@typescript-eslint/typescript-estree@npm:5.48.1" +"@typescript-eslint/typescript-estree@npm:5.53.0": + version: 5.53.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.53.0" dependencies: - "@typescript-eslint/types": 5.48.1 - "@typescript-eslint/visitor-keys": 5.48.1 + "@typescript-eslint/types": 5.53.0 + "@typescript-eslint/visitor-keys": 5.53.0 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -15913,25 +15897,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 2b26e5848ef131e1bb99ed54d8c0efa8279cf8e8f7d8b72de00c2ca6cf2799d96c20f5bbbcf26e14e81b7b9d1035ba509bff30f2d852c174815879e8f14c27ed - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.49.0": - version: 5.49.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.49.0" - dependencies: - "@typescript-eslint/types": 5.49.0 - "@typescript-eslint/visitor-keys": 5.49.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.3.7 - tsutils: ^3.21.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: f331af9f0ef3ce3157c421b8cc727dec5aa0a60add305aa4c676a02c63ec07799105268af192c5ed193a682b7ed804564d29d49bdbd2019678e495d80e65e29a + checksum: 6e119c8e4167c8495d728c5556a834545a9c064918dd5e7b79b0d836726f4f8e2a0297b0ac82bf2b71f1e5427552217d0b59d8fb1406fd79bd3bf91b75dca873 languageName: node linkType: hard @@ -15953,59 +15919,31 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.48.1": - version: 5.48.1 - resolution: "@typescript-eslint/utils@npm:5.48.1" +"@typescript-eslint/utils@npm:5.53.0, @typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.43.0": + version: 5.53.0 + resolution: "@typescript-eslint/utils@npm:5.53.0" dependencies: "@types/json-schema": ^7.0.9 "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.48.1 - "@typescript-eslint/types": 5.48.1 - "@typescript-eslint/typescript-estree": 5.48.1 + "@typescript-eslint/scope-manager": 5.53.0 + "@typescript-eslint/types": 5.53.0 + "@typescript-eslint/typescript-estree": 5.53.0 eslint-scope: ^5.1.1 eslint-utils: ^3.0.0 semver: ^7.3.7 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 2d112cbb6a920f147c6c3322e404ca3c56c1170e1ede3bcbf16fb779960dc24cdba688b1f2d06acd242859fc1dbc8702da5f8fa8bbf53e7081e41d80bec4c236 + checksum: 18e6bac14ae853385a74123759850bca367904723e170c37416fc014673eb714afb6bb090367bff61494a8387e941b6af65ee5f4f845f7177fabb4df85e01643 languageName: node linkType: hard -"@typescript-eslint/utils@npm:^5.10.0, @typescript-eslint/utils@npm:^5.43.0": - version: 5.49.0 - resolution: "@typescript-eslint/utils@npm:5.49.0" +"@typescript-eslint/visitor-keys@npm:5.53.0": + version: 5.53.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.53.0" dependencies: - "@types/json-schema": ^7.0.9 - "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.49.0 - "@typescript-eslint/types": 5.49.0 - "@typescript-eslint/typescript-estree": 5.49.0 - eslint-scope: ^5.1.1 - eslint-utils: ^3.0.0 - semver: ^7.3.7 - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 8218c566637d5104dfb2346216f8cb4c244f31c2a39e261aafe554b8abd48bd630a0d0807a0a8d776af8f9d9914c8776d86abf0a523049f3c5619c498a7e5b1e - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.48.1": - version: 5.48.1 - resolution: "@typescript-eslint/visitor-keys@npm:5.48.1" - dependencies: - "@typescript-eslint/types": 5.48.1 + "@typescript-eslint/types": 5.53.0 eslint-visitor-keys: ^3.3.0 - checksum: 2bda10cf4e6bc48b0d463767617e48a832d708b9434665dff6ed101f7d33e0d592f02af17a2259bde1bd17e666246448ae78d0fe006148cb93d897fff9b1d134 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.49.0": - version: 5.49.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.49.0" - dependencies: - "@typescript-eslint/types": 5.49.0 - eslint-visitor-keys: ^3.3.0 - checksum: 46dc7bc713e8825d1fccba521fdf7c6e2f8829e491c2afd44dbe4105c6432e3c3dfe7e1ecb221401269d639264bb4af77b60a7b65521fcff9ab02cd31d8ef782 + checksum: 090695883c15364c6f401e97f56b13db0f31c1114f3bd22562bd41734864d27f6a3c80de33957e9dedab2d5f94b0f4480ba3fde1d4574e74dca4593917b7b54a languageName: node linkType: hard From 3f75b7607ca79458e6440d428db1077312a31142 Mon Sep 17 00:00:00 2001 From: Ilya Savich Date: Fri, 17 Feb 2023 12:16:21 +0100 Subject: [PATCH 292/417] Add ability to pass icon as function to have ability to customize it by search item Signed-off-by: Ilya Savich --- .changeset/slow-insects-cheat.md | 8 ++++++++ plugins/catalog/api-report.md | 2 +- .../CatalogSearchResultListItem.tsx | 8 ++++++-- plugins/explore/api-report.md | 2 +- .../ToolSearchResultListItem/ToolSearchResultListItem.tsx | 8 ++++++-- plugins/techdocs/api-report.md | 2 +- .../search/components/TechDocsSearchResultListItem.tsx | 8 ++++++-- 7 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 .changeset/slow-insects-cheat.md diff --git a/.changeset/slow-insects-cheat.md b/.changeset/slow-insects-cheat.md new file mode 100644 index 0000000000..e07d6d6f96 --- /dev/null +++ b/.changeset/slow-insects-cheat.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-techdocs': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-explore': patch +--- + +Add ability to pass icon as function to have ability +to customize it by search item diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 6d746f6a7c..ee0ca180f4 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -117,7 +117,7 @@ export interface CatalogSearchResultListItemProps { // (undocumented) highlight?: ResultHighlight; // (undocumented) - icon?: ReactNode; + icon?: ReactNode | ((result: IndexableDocument) => ReactNode); // (undocumented) rank?: number; // (undocumented) diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index a277584d2f..6d0b3e3038 100644 --- a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -50,7 +50,7 @@ const useStyles = makeStyles( * @public */ export interface CatalogSearchResultListItemProps { - icon?: ReactNode; + icon?: ReactNode | ((result: IndexableDocument) => ReactNode); result?: IndexableDocument; highlight?: ResultHighlight; rank?: number; @@ -69,7 +69,11 @@ export function CatalogSearchResultListItem( return (
    - {props.icon && {props.icon}} + {props.icon && ( + + {typeof props.icon === 'function' ? props.icon(result) : props.icon} + + )}
    ReactNode); // (undocumented) rank?: number; // (undocumented) diff --git a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx index eb12ba45d8..1aad122ee6 100644 --- a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx +++ b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx @@ -46,7 +46,7 @@ const useStyles = makeStyles({ * @public */ export interface ToolSearchResultListItemProps { - icon?: ReactNode; + icon?: ReactNode | ((result: IndexableDocument) => ReactNode); result?: IndexableDocument; highlight?: ResultHighlight; rank?: number; @@ -62,7 +62,11 @@ export function ToolSearchResultListItem(props: ToolSearchResultListItemProps) { return ( <> - {props.icon && {props.icon}} + {props.icon && ( + + {typeof props.icon === 'function' ? props.icon(result) : props.icon} + + )}
    ReactNode); result?: any; highlight?: ResultHighlight; rank?: number; diff --git a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx index 9bf8b76092..3c0d2314e2 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx @@ -37,7 +37,7 @@ const useStyles = makeStyles({ * @public */ export type TechDocsSearchResultListItemProps = { - icon?: ReactNode; + icon?: ReactNode | ((result: any) => ReactNode); result?: any; highlight?: ResultHighlight; rank?: number; @@ -151,7 +151,11 @@ export const TechDocsSearchResultListItem = ( const ListItemWrapper = ({ children }: PropsWithChildren<{}>) => asListItem ? ( <> - {icon && {icon}} + {icon && ( + + {typeof icon === 'function' ? icon(result) : icon} + + )}
    {children}
    ) : ( From ea19696345637c787621a361fabe91aa12e61f2b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 09:16:26 +0000 Subject: [PATCH 293/417] fix(deps): update docusaurus monorepo to v2.3.1 Signed-off-by: Renovate Bot --- microsite-next/package.json | 6 +- microsite-next/yarn.lock | 368 ++++++++++++++++++------------------ 2 files changed, 187 insertions(+), 187 deletions(-) diff --git a/microsite-next/package.json b/microsite-next/package.json index 861d0ff958..f56ed6ae39 100644 --- a/microsite-next/package.json +++ b/microsite-next/package.json @@ -17,7 +17,7 @@ "docusaurus": "docusaurus" }, "devDependencies": { - "@docusaurus/module-type-aliases": "2.3.0", + "@docusaurus/module-type-aliases": "2.3.1", "@spotify/prettier-config": "^14.0.0", "@tsconfig/docusaurus": "^1.0.6", "@types/webpack-env": "^1.18.0", @@ -29,8 +29,8 @@ }, "prettier": "@spotify/prettier-config", "dependencies": { - "@docusaurus/core": "2.3.0", - "@docusaurus/preset-classic": "2.3.0", + "@docusaurus/core": "2.3.1", + "@docusaurus/preset-classic": "2.3.1", "clsx": "^1.1.1", "docusaurus-plugin-sass": "^0.2.3", "react": "^17.0.2", diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 7c627edcb4..81d5c07f6f 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -1660,9 +1660,9 @@ __metadata: languageName: node linkType: hard -"@docusaurus/core@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/core@npm:2.3.0" +"@docusaurus/core@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/core@npm:2.3.1" dependencies: "@babel/core": ^7.18.6 "@babel/generator": ^7.18.7 @@ -1674,13 +1674,13 @@ __metadata: "@babel/runtime": ^7.18.6 "@babel/runtime-corejs3": ^7.18.6 "@babel/traverse": ^7.18.8 - "@docusaurus/cssnano-preset": 2.3.0 - "@docusaurus/logger": 2.3.0 - "@docusaurus/mdx-loader": 2.3.0 + "@docusaurus/cssnano-preset": 2.3.1 + "@docusaurus/logger": 2.3.1 + "@docusaurus/mdx-loader": 2.3.1 "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/utils": 2.3.0 - "@docusaurus/utils-common": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/utils": 2.3.1 + "@docusaurus/utils-common": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 "@slorber/static-site-generator-webpack-plugin": ^4.0.7 "@svgr/webpack": ^6.2.1 autoprefixer: ^10.4.7 @@ -1701,7 +1701,7 @@ __metadata: del: ^6.1.1 detect-port: ^1.3.0 escape-html: ^1.0.3 - eta: ^1.12.3 + eta: ^2.0.0 file-loader: ^6.2.0 fs-extra: ^10.1.0 html-minifier-terser: ^6.1.0 @@ -1740,40 +1740,40 @@ __metadata: react-dom: ^16.8.4 || ^17.0.0 bin: docusaurus: bin/docusaurus.mjs - checksum: 59954cd761e1cf55c951014a5bb960498b619a6a65fa82c853cc55317e8d27385f0be410b76381221dca136ab0d0030dcbaedca173f38f8495fefbac3e5235d4 + checksum: 812aecae45af3f4d02fd16e89517ca9f1ba22821a078aaa890f5797ac7e0cc0c79e7623eb999e885cf7e7652a6ffda8ff7c06dfd85ca29aaab600993c3d9980d languageName: node linkType: hard -"@docusaurus/cssnano-preset@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/cssnano-preset@npm:2.3.0" +"@docusaurus/cssnano-preset@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/cssnano-preset@npm:2.3.1" dependencies: cssnano-preset-advanced: ^5.3.8 postcss: ^8.4.14 postcss-sort-media-queries: ^4.2.1 tslib: ^2.4.0 - checksum: ec51299236c1fdad1ce7f761eb85076ebddefbbc21bba9596a226a6e830060e0905fcc072a5dad4e1f668956329b7296e3b1b4468956d29cd607190d7dd5531b + checksum: a3d00ce86b16caffde36734bb2f4541d2c0df5e8ab6891a78ad05bccc631a895fecb04c385626ebcb8f905510c28fa6158288585673ae96565532d4ee4b60d4f languageName: node linkType: hard -"@docusaurus/logger@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/logger@npm:2.3.0" +"@docusaurus/logger@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/logger@npm:2.3.1" dependencies: chalk: ^4.1.2 tslib: ^2.4.0 - checksum: bf668d380e35ab795c0c28c4891794519093d13ae00221fe43981be1863fdada1f2de1c46095a9c949c15c545d1ad007d1714ee8a3862042c8f75785fded6e1a + checksum: eff5f258aeac9c643431426256e3bc4515074cc3cc754fa643579ba427ba232ecace9a9579ae5af542330b22d7361892a1eaf84526983a0c821c5ca3ee895176 languageName: node linkType: hard -"@docusaurus/mdx-loader@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/mdx-loader@npm:2.3.0" +"@docusaurus/mdx-loader@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/mdx-loader@npm:2.3.1" dependencies: "@babel/parser": ^7.18.8 "@babel/traverse": ^7.18.8 - "@docusaurus/logger": 2.3.0 - "@docusaurus/utils": 2.3.0 + "@docusaurus/logger": 2.3.1 + "@docusaurus/utils": 2.3.1 "@mdx-js/mdx": ^1.6.22 escape-html: ^1.0.3 file-loader: ^6.2.0 @@ -1790,16 +1790,16 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: e07be7155941ca9e3e07f996a0364e12bd5b9793b804bf87121341a491420047e88f7c010bde5ee71e65bed47b4febda242b601773f74bcafc116dd09ec8f5b5 + checksum: 4a1c9ef0e8506ab4d9cb4714ff7437664e238e0f2878a5eb4a2e082897bbee7ae8d0b61ba9d45ffa820beb5ce75aa0050201db815b00c18fc136aaa4c6411c21 languageName: node linkType: hard -"@docusaurus/module-type-aliases@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/module-type-aliases@npm:2.3.0" +"@docusaurus/module-type-aliases@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/module-type-aliases@npm:2.3.1" dependencies: "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/types": 2.3.0 + "@docusaurus/types": 2.3.1 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -1809,21 +1809,21 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: 96d9dc39d90bbec155a55403272a9c3be2603fd556c1e4da6db161e3841de671e9e219b1de153f072ab09a440f523a628c4e382ff527acd527780e7843aebe0d + checksum: 74f799f81455dc8ff3e6edf07428996764014c2c7b416e6b5d160af15f00ad3aa1ab75dee5356645ec7f2ea832fb2aca6e9a32b19d64abeb9e3d57c4195f1e50 languageName: node linkType: hard -"@docusaurus/plugin-content-blog@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-content-blog@npm:2.3.0" +"@docusaurus/plugin-content-blog@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-content-blog@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/logger": 2.3.0 - "@docusaurus/mdx-loader": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils": 2.3.0 - "@docusaurus/utils-common": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/logger": 2.3.1 + "@docusaurus/mdx-loader": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils": 2.3.1 + "@docusaurus/utils-common": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 cheerio: ^1.0.0-rc.12 feed: ^4.2.2 fs-extra: ^10.1.0 @@ -1836,21 +1836,21 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: e5b89196ddec47f7c282b9f5fba1d1caada0c6d44776e2f55ee5b13b440661f586bef18553d49e3b44a417982e4c799d3e18e10f60d60e90a0b8c90b8b30232a + checksum: abc668ceab15269f57be7f74acbec2e139b4f6b90af8771d246a9036d124b49b0d9fd4890e9566df7a4ba960f2da0316c18741eed1be0646f2b4602465219ddd languageName: node linkType: hard -"@docusaurus/plugin-content-docs@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-content-docs@npm:2.3.0" +"@docusaurus/plugin-content-docs@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-content-docs@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/logger": 2.3.0 - "@docusaurus/mdx-loader": 2.3.0 - "@docusaurus/module-type-aliases": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/logger": 2.3.1 + "@docusaurus/mdx-loader": 2.3.1 + "@docusaurus/module-type-aliases": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 "@types/react-router-config": ^5.0.6 combine-promises: ^1.1.0 fs-extra: ^10.1.0 @@ -1863,132 +1863,132 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: a18bd0c7e089239819938675fd3c3f5a7447cfeae6f27dac165a34558d4b39cad8a4934736228ecf4d7dde6f28fe4e1c5ed97ba9f5cba3251f5eb4781517f413 + checksum: bcf8d921407d11b497926a1f61a1dc8c96f82fbe5a1959cc106b082e555f8fb6f42cf9262a658acf33d9543e5eb3e778049d91f71e4a2855993dc759c845cf31 languageName: node linkType: hard -"@docusaurus/plugin-content-pages@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-content-pages@npm:2.3.0" +"@docusaurus/plugin-content-pages@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-content-pages@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/mdx-loader": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/mdx-loader": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 fs-extra: ^10.1.0 tslib: ^2.4.0 webpack: ^5.73.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 3ff7090045929a64b87da4e5e5a57cf725e552b03569d2a0086cf79849316393948e239d58f4bea758d131224b165ceb96ab1e908e357e6e256b5e499f0d4ad6 + checksum: 8543050ed7330f54a28c0daeef11662eed3f3a08a6d0015b1a32db3d5e9ec46f0c6a8a5a4cb3e871ce953074d60424cc418b7ffa280695294626855a7a1a146a languageName: node linkType: hard -"@docusaurus/plugin-debug@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-debug@npm:2.3.0" +"@docusaurus/plugin-debug@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-debug@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils": 2.3.1 fs-extra: ^10.1.0 react-json-view: ^1.21.3 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 770cd5749730ebb3f8633f7c07b0e5248ee24c175dcb6bfc99717253fc6e16ac75d720e373a4d98ade51ca47ec69543cd7159f215961f64d41f95120efe06c76 + checksum: e660575f900eedbeab6e222eb4f8ef6a7a49815c91a97839a4839737c0b3101698bf7c6e035cbafaa49010340010a9ec0d37270dc81a470b3bae42662c7a24b8 languageName: node linkType: hard -"@docusaurus/plugin-google-analytics@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-google-analytics@npm:2.3.0" +"@docusaurus/plugin-google-analytics@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-google-analytics@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 2de84efb8998c36315d856ec1c7fe40af9265d078642f2984d280d9e698af45922dcc205039fbaeb30f45802d788e230fe34cd4d292d57d95f99c006b92f2e25 + checksum: 9306ae89cd5fb8ca86fd58809d7e624f988411d8908a151e9b6d9e8d0b84e08f1e3eba46024bc4321bcaeb3e9bc38e919b0bcf561adc9d40fa97c8ffeb232888 languageName: node linkType: hard -"@docusaurus/plugin-google-gtag@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-google-gtag@npm:2.3.0" +"@docusaurus/plugin-google-gtag@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-google-gtag@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 8d1c192163ed902498ed8ff5fef668a8ebd8fd63b3da691295a875ef96eb98e2e9b0967986dff2ea454f2094479fec2e4876d2f66c643a174df26204e4aab2a2 + checksum: 494f0405d79aa9cb36d1ea4cf739499ad15b59fe876573ab5b304b5e84ab6ef4d428ebdc26647777b0816af452f62959b5ddb25e5bbf73c7fb3d6568258980d0 languageName: node linkType: hard -"@docusaurus/plugin-google-tag-manager@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-google-tag-manager@npm:2.3.0" +"@docusaurus/plugin-google-tag-manager@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-google-tag-manager@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: dd9830fd4f3ee5f4ab1a8a26a055b7551084e49dd33046eb62950fa74a30d1c6371cacb10f42753ba0b32b025bdcb34abf6877dd7b7fe42e9ab86f3539634483 + checksum: d0b2ccc212652bb4f1c1bd61420e7f235325d4f2e8de0f5b25282305f54209d05da981c1253325bcae9afbc7575bd5c246d037d2be5fbda06f2842ba8335ab47 languageName: node linkType: hard -"@docusaurus/plugin-sitemap@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/plugin-sitemap@npm:2.3.0" +"@docusaurus/plugin-sitemap@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/plugin-sitemap@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/logger": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils": 2.3.0 - "@docusaurus/utils-common": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/logger": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils": 2.3.1 + "@docusaurus/utils-common": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 fs-extra: ^10.1.0 sitemap: ^7.1.1 tslib: ^2.4.0 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: f2ace8f5a121aa616d411dbe0211ecba5ca57ad1fceb4529f8418c4c5259cfe62a5a511332289502242e6ff04116d27ddf5a8826d16324cc1ccaacfca29b49b1 + checksum: 667d2abbf46efffc4d20e38fe435a19392f07726446193a017306652ee9db3d478e971eefb209e1a5c243b6b82af3de72d4b975b8e74aa93bda4711ce8c309bc languageName: node linkType: hard -"@docusaurus/preset-classic@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/preset-classic@npm:2.3.0" +"@docusaurus/preset-classic@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/preset-classic@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/plugin-content-blog": 2.3.0 - "@docusaurus/plugin-content-docs": 2.3.0 - "@docusaurus/plugin-content-pages": 2.3.0 - "@docusaurus/plugin-debug": 2.3.0 - "@docusaurus/plugin-google-analytics": 2.3.0 - "@docusaurus/plugin-google-gtag": 2.3.0 - "@docusaurus/plugin-google-tag-manager": 2.3.0 - "@docusaurus/plugin-sitemap": 2.3.0 - "@docusaurus/theme-classic": 2.3.0 - "@docusaurus/theme-common": 2.3.0 - "@docusaurus/theme-search-algolia": 2.3.0 - "@docusaurus/types": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/plugin-content-blog": 2.3.1 + "@docusaurus/plugin-content-docs": 2.3.1 + "@docusaurus/plugin-content-pages": 2.3.1 + "@docusaurus/plugin-debug": 2.3.1 + "@docusaurus/plugin-google-analytics": 2.3.1 + "@docusaurus/plugin-google-gtag": 2.3.1 + "@docusaurus/plugin-google-tag-manager": 2.3.1 + "@docusaurus/plugin-sitemap": 2.3.1 + "@docusaurus/theme-classic": 2.3.1 + "@docusaurus/theme-common": 2.3.1 + "@docusaurus/theme-search-algolia": 2.3.1 + "@docusaurus/types": 2.3.1 peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 0806924793094a4446b20d63fdc910c5ae82b2353905502f886c2a02981a4e42378b0251e38a60caf496e6e6034014096829eb51401685f747934eb83f15dcbb + checksum: e4128a1bcb64d5ced04a281476ec1ae2d5523040d41ed57a8f744fb83659a2a2be902e94989de69ab1e6d693ec26c60d1ef6b2fe3ec96d5af6c9b3ef58f5b0cd languageName: node linkType: hard @@ -2004,22 +2004,22 @@ __metadata: languageName: node linkType: hard -"@docusaurus/theme-classic@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/theme-classic@npm:2.3.0" +"@docusaurus/theme-classic@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/theme-classic@npm:2.3.1" dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/mdx-loader": 2.3.0 - "@docusaurus/module-type-aliases": 2.3.0 - "@docusaurus/plugin-content-blog": 2.3.0 - "@docusaurus/plugin-content-docs": 2.3.0 - "@docusaurus/plugin-content-pages": 2.3.0 - "@docusaurus/theme-common": 2.3.0 - "@docusaurus/theme-translations": 2.3.0 - "@docusaurus/types": 2.3.0 - "@docusaurus/utils": 2.3.0 - "@docusaurus/utils-common": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/mdx-loader": 2.3.1 + "@docusaurus/module-type-aliases": 2.3.1 + "@docusaurus/plugin-content-blog": 2.3.1 + "@docusaurus/plugin-content-docs": 2.3.1 + "@docusaurus/plugin-content-pages": 2.3.1 + "@docusaurus/theme-common": 2.3.1 + "@docusaurus/theme-translations": 2.3.1 + "@docusaurus/types": 2.3.1 + "@docusaurus/utils": 2.3.1 + "@docusaurus/utils-common": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 "@mdx-js/react": ^1.6.22 clsx: ^1.2.1 copy-text-to-clipboard: ^3.0.1 @@ -2036,20 +2036,20 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: a6206f34161aa388e36dde2f8eb9291cec34dba890a40cd7226040efd303aa322110237464016ce407a65b8a2bff755470ff6c5250b20e3a27645d8860246a65 + checksum: 273812924fc29b2316aff554ae0302509ebeaca5aa829b58253e74d22a66e69444f1c324a2d5e8e170e6c6f27dd0d6927e6c6a22a7e0c14567ff777d04a5b0c1 languageName: node linkType: hard -"@docusaurus/theme-common@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/theme-common@npm:2.3.0" +"@docusaurus/theme-common@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/theme-common@npm:2.3.1" dependencies: - "@docusaurus/mdx-loader": 2.3.0 - "@docusaurus/module-type-aliases": 2.3.0 - "@docusaurus/plugin-content-blog": 2.3.0 - "@docusaurus/plugin-content-docs": 2.3.0 - "@docusaurus/plugin-content-pages": 2.3.0 - "@docusaurus/utils": 2.3.0 + "@docusaurus/mdx-loader": 2.3.1 + "@docusaurus/module-type-aliases": 2.3.1 + "@docusaurus/plugin-content-blog": 2.3.1 + "@docusaurus/plugin-content-docs": 2.3.1 + "@docusaurus/plugin-content-pages": 2.3.1 + "@docusaurus/utils": 2.3.1 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -2062,26 +2062,26 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: e38683aa8fd74599b9ccb6032af7a0ccb76144f5b3ccc4b93d423be263ca5ffb1ace42c22ce789c11ab45ae076fdf95bd36287b551edbf51d55c2e848e8a6189 + checksum: 6b902e9e782721c3c49bcdee5d969ea1c1138ebcb03891e34f827b16f2c06f43a86d95f240a60ed084539e9b16435312a41be7bff4e724f4fb209998dd4d3a59 languageName: node linkType: hard -"@docusaurus/theme-search-algolia@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/theme-search-algolia@npm:2.3.0" +"@docusaurus/theme-search-algolia@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/theme-search-algolia@npm:2.3.1" dependencies: "@docsearch/react": ^3.1.1 - "@docusaurus/core": 2.3.0 - "@docusaurus/logger": 2.3.0 - "@docusaurus/plugin-content-docs": 2.3.0 - "@docusaurus/theme-common": 2.3.0 - "@docusaurus/theme-translations": 2.3.0 - "@docusaurus/utils": 2.3.0 - "@docusaurus/utils-validation": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/logger": 2.3.1 + "@docusaurus/plugin-content-docs": 2.3.1 + "@docusaurus/theme-common": 2.3.1 + "@docusaurus/theme-translations": 2.3.1 + "@docusaurus/utils": 2.3.1 + "@docusaurus/utils-validation": 2.3.1 algoliasearch: ^4.13.1 algoliasearch-helper: ^3.10.0 clsx: ^1.2.1 - eta: ^1.12.3 + eta: ^2.0.0 fs-extra: ^10.1.0 lodash: ^4.17.21 tslib: ^2.4.0 @@ -2089,23 +2089,23 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 97d7314ae6c612eda1b8aa24b6d812c66a8da1030f7eea8d04c9ab8caba62bb66ec95dfcbb613f0f522fa6130e51cd41fcc7eca1c0fe50e533ccbf5aa9e2047d + checksum: 965303068e43b11f58d20b95bb6dfc01d5e575c2070d2730b94303bd2a1d33794075cae43bfe472f08061bd8770f14c8eb54932274e6b39f954ab34e7cfc5689 languageName: node linkType: hard -"@docusaurus/theme-translations@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/theme-translations@npm:2.3.0" +"@docusaurus/theme-translations@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/theme-translations@npm:2.3.1" dependencies: fs-extra: ^10.1.0 tslib: ^2.4.0 - checksum: df11b8a0b569a5adaec505d52cccffef1d903404232c776354035a387b56fcc7aa7d742aa0df622ccc052b61443ba134b6dcc6d3a4076aced4cd253d6cf957f6 + checksum: dd3796be63c4c946af789c3da18ed2704a2fa90d8e752ba2b780a124dc13369ba590218afad0ac4ea2342f7331ccb9eb1be086226c950b8384978d94a15c57ad languageName: node linkType: hard -"@docusaurus/types@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/types@npm:2.3.0" +"@docusaurus/types@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/types@npm:2.3.1" dependencies: "@types/history": ^4.7.11 "@types/react": "*" @@ -2118,13 +2118,13 @@ __metadata: peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 - checksum: 563749b9473e35848c3e462c7e401d292dbf3f36e3ab72b5a03aebe204f1147b666953fc8e176c2024ea9c2b3a8aa7fd33f500df576afff456dea003b742c52b + checksum: 91e52f37b97964112aa0d50ee4a6f534d7da941443af5ddc96418817c6ce532a98c73e67045ac703b582c7ed703ebb360205eec30da7f738c0105f2b3ae1a246 languageName: node linkType: hard -"@docusaurus/utils-common@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/utils-common@npm:2.3.0" +"@docusaurus/utils-common@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/utils-common@npm:2.3.1" dependencies: tslib: ^2.4.0 peerDependencies: @@ -2132,28 +2132,28 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 67711f2a53cd9e91768645015ab17e9c3b46d850958a4dcab6e0fb939b4d90bb3bb0323f8c70446246af6aacad98c1044d33f5f74dcc8e8bc9871ae62ea33a7b + checksum: 405dc5b8aba9a97b2670ba8ff3911bbdaed274edc15214ab482a7159a07ad1c9b3198835a7bee42de4e0320d42bd402ed89ae6896744a364d64d89d9f78bcfb0 languageName: node linkType: hard -"@docusaurus/utils-validation@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/utils-validation@npm:2.3.0" +"@docusaurus/utils-validation@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/utils-validation@npm:2.3.1" dependencies: - "@docusaurus/logger": 2.3.0 - "@docusaurus/utils": 2.3.0 + "@docusaurus/logger": 2.3.1 + "@docusaurus/utils": 2.3.1 joi: ^17.6.0 js-yaml: ^4.1.0 tslib: ^2.4.0 - checksum: 0275530f4c49a1d0269422dfbe8f7abcda94c83fb3c20d1be36f9259b16c2170f8090f30077091b02e1059b2c683726d40b19235f07250f245719159d3ecd98c + checksum: 1e5529d1d0c4fcd9006adf2e5b545458a7dba3877563fb444dcec472f27a3d8492d4c6fb5dd1071bb6e668a13a845d74b8f6c4b6387babfa0e467a9b8b237fda languageName: node linkType: hard -"@docusaurus/utils@npm:2.3.0": - version: 2.3.0 - resolution: "@docusaurus/utils@npm:2.3.0" +"@docusaurus/utils@npm:2.3.1": + version: 2.3.1 + resolution: "@docusaurus/utils@npm:2.3.1" dependencies: - "@docusaurus/logger": 2.3.0 + "@docusaurus/logger": 2.3.1 "@svgr/webpack": ^6.2.1 escape-string-regexp: ^4.0.0 file-loader: ^6.2.0 @@ -2174,7 +2174,7 @@ __metadata: peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 6874bd327af99bc97bdea3fca6ce71f917b6a89fa18bbd81a2d955a33ccf1746f70960f27fc7fca557bc9e1a671a6f369e7aade28f7908727dc58e84f9ac5851 + checksum: e8bce9bbd98bf63664fcd7c0a5f8dec30dad31ed19e18d724b43189b04ecdc1174537e1d987293575ec18d421236fb92d3d39d28477e921507260a39c3f6d6d0 languageName: node linkType: hard @@ -3597,9 +3597,9 @@ __metadata: version: 0.0.0-use.local resolution: "backstage-microsite@workspace:." dependencies: - "@docusaurus/core": 2.3.0 - "@docusaurus/module-type-aliases": 2.3.0 - "@docusaurus/preset-classic": 2.3.0 + "@docusaurus/core": 2.3.1 + "@docusaurus/module-type-aliases": 2.3.1 + "@docusaurus/preset-classic": 2.3.1 "@spotify/prettier-config": ^14.0.0 "@tsconfig/docusaurus": ^1.0.6 "@types/webpack-env": ^1.18.0 @@ -5165,10 +5165,10 @@ __metadata: languageName: node linkType: hard -"eta@npm:^1.12.3": - version: 1.12.3 - resolution: "eta@npm:1.12.3" - checksum: 390c1cd320755cb98fd5a4a911539e8ed498fc49b82414f0023033ff606d80a34e6df0aeeb9fb0b519b318a750e6d17a72fc25f8a8c686cfc52d638e998237a1 +"eta@npm:^2.0.0": + version: 2.0.0 + resolution: "eta@npm:2.0.0" + checksum: ab8e93af73f0d4917485976aa8fcac68e730c47e9aa54a720c21c2e9087cdcd5f984a50cf5e04d189757612df014a229fa047a437651c9eea31e0b6bf1afe56b languageName: node linkType: hard From b12f56424068da4bd3525aa387dd72df6965c18d Mon Sep 17 00:00:00 2001 From: martincostello Date: Tue, 21 Feb 2023 09:39:26 +0000 Subject: [PATCH 294/417] Fix formatting Fix prettier issue caused by minor refactor just before previous commit. Signed-off-by: martincostello --- .../src/components/SonarQubeCard/SonarQubeCard.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx index f37bd6eda5..5bd1cd8e9f 100644 --- a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx +++ b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx @@ -203,7 +203,11 @@ export const SonarQubeCard = (props: { /> : + value.metrics.vulnerabilities === '0' ? ( + + ) : ( + + ) } title="Vulnerabilities" link={value.getIssuesUrl('VULNERABILITY')} From 7a23cdfa59a5b864139ad2cdfef7824bdb48d36f Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Feb 2023 11:43:14 +0100 Subject: [PATCH 295/417] Update image links to use markdown syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ben Lambert Co-authored-by: Fredrik Adelöw Signed-off-by: Johan Haals --- docs/api/utility-apis.md | 4 +-- .../building-plugins-and-modules/01-index.md | 2 +- docs/features/search/architecture.md | 4 ++- docs/features/techdocs/addons.md | 4 ++- docs/features/techdocs/architecture.md | 8 +++-- docs/features/techdocs/getting-started.md | 8 +++-- docs/getting-started/configuration.md | 35 +++++++------------ docs/getting-started/create-an-app.md | 4 +-- docs/getting-started/homepage.md | 17 ++++----- docs/getting-started/index.md | 12 ++----- 10 files changed, 43 insertions(+), 55 deletions(-) diff --git a/docs/api/utility-apis.md b/docs/api/utility-apis.md index a69c874307..44c00d1ab7 100644 --- a/docs/api/utility-apis.md +++ b/docs/api/utility-apis.md @@ -290,9 +290,7 @@ The figure below shows the relationship between FooApi via the fooApiRef. -
    -Figure showing the relationship between utility APIs, the apps that provide them, and the plugins that consume them -
    +![Figure showing the relationship between utility APIs, the apps that provide them, and the plugins that consume them](../assets/utility-apis-fig1.svg) The current method for connecting Utility API providers and consumers is via the React tree using an `ApiProvider`, which is added to the `AppProvider` of the diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index 18cbabfe5d..848a38ce16 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -74,7 +74,7 @@ Backend modules are used to extend [plugins](../architecture/04-plugins.md) with additional features or change existing behavior. They must always be installed in the same backend instance as the plugin that they extend, and may only extend a single plugin. Modules interact with their target plugin using the [extension -points](./05-extension-points.md) registered by the plugin, while also being +points](../architecture/05-extension-points.md) registered by the plugin, while also being able to depend on the [services](../architecture/03-services.md) of that plugin. That last point is worth reiterating: injected `plugin` scoped services will be the exact diff --git a/docs/features/search/architecture.md b/docs/features/search/architecture.md index f1183cec5f..62f3a68ff6 100644 --- a/docs/features/search/architecture.md +++ b/docs/features/search/architecture.md @@ -9,7 +9,9 @@ to support a wide variety of search engines, while providing a simple developer experience for plugin developers, and a good out-of-the-box experience for Backstage end-users. -Search Architecture + + +![Search Architecture](../../assets/search/architecture.drawio.svg) At a base-level, we want to support the following: diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md index 60999f599c..bd709ee15f 100644 --- a/docs/features/techdocs/addons.md +++ b/docs/features/techdocs/addons.md @@ -39,7 +39,9 @@ representative of physical spaces in the TechDocs UI: - `Component`: A [proposed-but-not-yet-implemented](https://github.com/backstage/backstage/issues/11109) virtual location, aimed at simplifying a common type of Addon. -TechDocs Addon Location Guide + + +![TechDocs Addon Location Guide](../../assets/techdocs/addon-locations.png) ### Addon Registry diff --git a/docs/features/techdocs/architecture.md b/docs/features/techdocs/architecture.md index d781f71917..2cb8543ccd 100644 --- a/docs/features/techdocs/architecture.md +++ b/docs/features/techdocs/architecture.md @@ -9,7 +9,9 @@ description: Documentation on TechDocs Architecture When you deploy Backstage (with TechDocs enabled by default), you get a basic out-of-the box experience. -TechDocs Architecture diagram + + +![TechDocs Architecture diagram](../../assets/techdocs/architecture-basic.drawio.svg) > Note: See below for our recommended deployment architecture which takes care > of stability, scalability and speed. Also look at the @@ -42,7 +44,9 @@ storage system (e.g. AWS S3, GCS or Azure Blob Storage). Read more in This is how we recommend deploying TechDocs in a production environment. -TechDocs Architecture diagram + + +![TechDocs Architecture diagram](../../assets/techdocs/architecture-recommended.drawio.svg) The key difference in the recommended deployment approach is where the docs are built. diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index 578a631798..3f7edd23a0 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -89,11 +89,15 @@ const AppRoutes = () => { I know, you're curious to see how it looks, aren't you? See the image below: -TechDocs Report Issue Add-on + + +![TechDocs Report Issue Add-on](../../assets/techdocs/report-issue-addon.png) By clicking the open new issue button, you will be redirected to the new issue page according to the source code provider you are using: -TechDocs Report Issue Template + + +![TechDocs Report Issue Template](../../assets/techdocs/report-issue-template.png) That's it! Now, we need the TechDocs Backend plugin for the frontend to work. diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index 0441d3f589..1c25606ac3 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -136,9 +136,7 @@ frontend, in our tutorial it would be `http://localhost:3000`. The `Authorization callback URL` will point to the auth backend, which will most likely be `http://localhost:7007/api/auth/github/handler/frame`. -

    - Screenshot of the GitHub OAuth creation page -

    +![Screenshot of the GitHub OAuth creation page](../assets/getting-started/gh-oauth.png) Take note of the `Client ID` and the `Client Secret`. Open `app-config.yaml`, and add your `clientId` and `clientSecret` to this file. It should end up @@ -214,9 +212,7 @@ name to identify this token and put it in the notes field. Choose a number of days for expiration. If you have a hard time picking a number, we suggest to go for 7 days, it's a lucky number. -

    - Screenshot of the GitHub Personal Access Token creation page -

    +![Screenshot of the GitHub Personal Access Token creation page](../assets/getting-started/gh-pat.png) Set the scope to your likings. For this tutorial, selecting `repo` and `workflow` is required as the scaffolding job in this guide configures a GitHub actions workflow for the newly created project. @@ -262,21 +258,18 @@ otherwise something went terribly wrong. - Register a new component, by going to `create` and choose `Register existing component` -

    - Software template main screen, with a blue button to add an existing component -

    + + + ![Software template main screen, with a blue button to add an existing component](../assets/getting-started/b-existing-1.png) - As URL use `https://github.com/backstage/demo/blob/master/catalog-info.yaml`. This is used by our [demo site](https://demo.backstage.io). -

    - Register a new component wizard, asking for an URL to the existing component YAML file -

    -- Hit `Analyze` and review the changes. Apply them if correct + ![Register a new component wizard, asking for an URL to the existing component YAML file](../assets/getting-started/b-existing-2.png) -

    - Register a new component wizard, showing the metadata for the component YAML we use in this tutorial -

    +- Hit `Analyze` and review the changes. Apply them if correct. + + ![Register a new component wizard, showing the metadata for the component YAML we use in this tutorial](../assets/getting-started/b-existing-3.png) - You should receive a message that your entities have been added. - If you go back to `Home`, you should be able to find `demo`. You should be @@ -286,14 +279,12 @@ otherwise something went terribly wrong. - Go to `create` and choose to create a website with the `Example Node.js Template` - Type in a name, let's use `tutorial` and click `Next Step` -

    - Software template deployment input screen asking for a name -

    + +![Software template deployment input screen asking for a name](../assets/getting-started/b-scaffold-1.png) - You should see the following screen: -

    - Software template deployment input screen asking for the GitHub username, and name of the new repo to create -

    + +![Software template deployment input screen asking for the GitHub username, and name of the new repo to create](../assets/getting-started/b-scaffold-2.png) - For host, it should default to github.com - As owner, type your GitHub username diff --git a/docs/getting-started/create-an-app.md b/docs/getting-started/create-an-app.md index 05c12ffb75..535bc848fc 100644 --- a/docs/getting-started/create-an-app.md +++ b/docs/getting-started/create-an-app.md @@ -34,9 +34,7 @@ npx @backstage/create-app This will create a new Backstage App inside the current folder. The name of the app-folder is the name that was provided when prompted. -

    - create app -

    +![create app](../assets/getting-started/create-app_output.png) Inside that directory, it will generate all the files and folder structure needed for you to run your app. diff --git a/docs/getting-started/homepage.md b/docs/getting-started/homepage.md index 7db41d7768..9fa91e694f 100644 --- a/docs/getting-started/homepage.md +++ b/docs/getting-started/homepage.md @@ -82,16 +82,9 @@ const routes = ( Let's update the route for "Home" in the Backstage sidebar to point to the new homepage. We'll also add a Sidebar item to quickly open Catalog. -

    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©4iy(`jXf^=>(Oie1aq= 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 {KtK-(V^o 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μB-Kq-fLg7}N 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≤}vg&wl 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

    - - - - - - - - -
    Sidebar without CatalogSidebar with Catalog
    BeforeAfter
    +| Before | After | +| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| ![Sidebar without Catalog](../assets/getting-started/sidebar-without-catalog.png) | ![Sidebar with Catalog](../assets/getting-started/sidebar-with-catalog.png) | The code for the Backstage sidebar is most likely inside your [`packages/app/src/components/Root/Root.tsx`](https://github.com/backstage/backstage/blob/master/packages/app/src/components/Root/Root.tsx). @@ -121,7 +114,9 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( That's it! You should now have _(although slightly boring)_ a homepage! -Screenshot of a blank homepage + + +![Screenshot of a blank homepage](../assets/getting-started/simple-homepage.png) In the next steps, we will make it interesting and useful! diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 962919015b..c3d6b21923 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -54,9 +54,7 @@ npx @backstage/create-app@latest The wizard will ask you for the name of the app, which will also be the name of the directory -

    - Screenshot of the wizard asking for a name for the app. -

    +![Screenshot of the wizard asking for a name for the app.](../assets/getting-started/wizard.png) ### Run the Backstage app @@ -69,9 +67,7 @@ cd my-backstage-app yarn dev ``` -

    - Screenshot of the command output, with the message web pack compiled successfully. -

    +![Screenshot of the command output, with the message web pack compiled successfully](../assets/getting-started/startup.png) It might take a little while, but as soon as the message `[0] webpack compiled successfully` appears, you can open a browser and directly @@ -80,9 +76,7 @@ You can start exploring the demo immediately. Please note that the in-memory database will be cleared when you restart the app, so you'll most likely want to carry on with the database steps. -

    - Screenshot of the Backstage portal. -

    +![Screenshot of the Backstage portal.](../assets/getting-started/portal.png) In the next part of this tutorial, you'll learn how to change to a persistent database, configure authentication, and add your first integration. Continue From 4975e751f1aedea4f29209a2ccbe098d5902bf73 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Feb 2023 11:43:55 +0100 Subject: [PATCH 296/417] Update sidebar Signed-off-by: Johan Haals --- microsite-next/sidebars.json | 52 ++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/microsite-next/sidebars.json b/microsite-next/sidebars.json index 67c4209976..f489771fa0 100644 --- a/microsite-next/sidebars.json +++ b/microsite-next/sidebars.json @@ -1,6 +1,9 @@ { "releases": { "Release Notes": [ + "releases/v1.11.0", + "releases/v1.10.0", + "releases/v1.9.0", "releases/v1.8.0", "releases/v1.7.0", "releases/v1.6.0", @@ -85,7 +88,8 @@ "features/kubernetes/installation", "features/kubernetes/configuration", "features/kubernetes/authentication", - "features/kubernetes/troubleshooting" + "features/kubernetes/troubleshooting", + "features/kubernetes/proxy" ] }, { @@ -101,6 +105,7 @@ "features/software-templates/writing-custom-actions", "features/software-templates/writing-custom-field-extensions", "features/software-templates/writing-custom-step-layouts", + "features/software-templates/testing-scaffolder-alpha", "features/software-templates/migrating-from-v1beta2-to-v1beta3" ] }, @@ -199,7 +204,8 @@ "label": "GitLab", "items": [ "integrations/gitlab/locations", - "integrations/gitlab/discovery" + "integrations/gitlab/discovery", + "integrations/gitlab/org" ] }, { @@ -237,8 +243,7 @@ "plugins/proxying", "plugins/backend-plugin", "plugins/call-existing-api", - "plugins/url-reader", - "plugins/new-backend-system" + "plugins/url-reader" ] }, { @@ -361,6 +366,43 @@ "architecture-decisions/adrs-adr012", "architecture-decisions/adrs-adr013" ], - "FAQ": ["FAQ"] + "FAQ": ["FAQ"], + "Experimental Backend System": [ + "backend-system/index", + { + "type": "category", + "label": "Architecture", + "items": [ + "backend-system/architecture/index", + "backend-system/architecture/services", + "backend-system/architecture/plugins", + "backend-system/architecture/extension-points", + "backend-system/architecture/modules", + "backend-system/architecture/naming-patterns" + ] + }, + { + "type": "category", + "label": "Building Backends", + "items": [ + "backend-system/building-backends/index", + "backend-system/building-backends/migrating" + ] + }, + { + "type": "category", + "label": "Building Plugins & Modules", + "items": [ + "backend-system/building-plugins-and-modules/index", + "backend-system/building-plugins-and-modules/testing", + "backend-system/building-plugins-and-modules/migrating" + ] + }, + { + "type": "category", + "label": "Core Services", + "items": ["backend-system/core-services/index"] + } + ] } } From 185abd171d1d8318509f4f888cb070bb3ca04c34 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Feb 2023 11:44:09 +0100 Subject: [PATCH 297/417] Use new search index configuration Signed-off-by: Johan Haals --- microsite-next/docusaurus.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index 52867ed121..b050f4d914 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -218,9 +218,9 @@ module.exports = { '', }, algolia: { - appId: 'AZYC4ZFNTN', - apiKey: '7dbd2089b0d445ee0d87db71abfc794f', - indexName: 'backstage', + apiKey: '10b9e6c92a4513c1cf390f50e53aad1f', + indexName: 'backstage_io', + appId: 'JCMFNHCHI8', searchParameters: {}, }, }, From be99a4ddd60cf6dc99d28659967d4e01a9f7cc1e Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 12:31:25 +0100 Subject: [PATCH 298/417] feat: added the ability to grab the schema for the field definition in the validator Signed-off-by: blam --- .../Stepper/createAsyncValidators.test.ts | 73 +++++++++++++++++++ .../Stepper/createAsyncValidators.ts | 21 +++++- .../src/next/extensions/types.ts | 6 +- 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 3c4442afea..196bae0255 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -56,6 +56,79 @@ describe('createAsyncValidators', () => { expect(validators.AddressField).toHaveBeenCalled(); }); + it('should call the validator function with the correct schema in the context', async () => { + const schema: JsonObject = { + type: 'object', + properties: { + name: { + type: 'string', + 'ui:options': { + bob: true, + }, + pattern: 'lols', + 'ui:field': 'NameField', + }, + address: { + type: 'object', + 'ui:field': 'AddressField', + properties: { + street: { + type: 'string', + }, + postcode: { + type: 'string', + }, + }, + }, + }, + }; + + const validators = { NameField: jest.fn(), AddressField: jest.fn() }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await validate({ + name: 'asd', + address: { street: 'street', postcode: 'postcode' }, + }); + + expect(validators.NameField).toHaveBeenCalledWith( + 'asd', + expect.anything(), + expect.objectContaining({ + schema: { + type: 'string', + 'ui:options': { + bob: true, + }, + pattern: 'lols', + 'ui:field': 'NameField', + }, + }), + ); + + expect(validators.AddressField).toHaveBeenCalledWith( + { street: 'street', postcode: 'postcode' }, + expect.anything(), + expect.objectContaining({ + schema: { + type: 'object', + 'ui:field': 'AddressField', + properties: { + street: { + type: 'string', + }, + postcode: { + type: 'string', + }, + }, + }, + }), + ); + }); + it('should return the correct errors to the frontend', async () => { const schema: JsonObject = { type: 'object', diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index b524944719..111f3a0f1f 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -48,12 +48,17 @@ export const createAsyncValidators = ( validatorName: string, key: string, value: JsonValue | undefined, + schema: JsonObject, ) => { const validator = validators[validatorName]; if (validator) { const fieldValidation = createFieldValidation(); try { - await validator(value, fieldValidation, { ...context, formData }); + await validator(value, fieldValidation, { + ...context, + formData, + schema, + }); } catch (ex) { fieldValidation.addError(ex.message); } @@ -67,7 +72,12 @@ export const createAsyncValidators = ( if (definitionInSchema && 'ui:field' in definitionInSchema) { if ('ui:field' in definitionInSchema) { - await validateForm(definitionInSchema['ui:field'], key, value); + await validateForm( + definitionInSchema['ui:field'], + key, + value, + definitionInSchema, + ); } } else if ( definitionInSchema && @@ -75,7 +85,12 @@ export const createAsyncValidators = ( 'ui:field' in definitionInSchema.items ) { if ('ui:field' in definitionInSchema.items) { - await validateForm(definitionInSchema.items['ui:field'], key, value); + await validateForm( + definitionInSchema.items['ui:field'], + key, + value, + definitionInSchema.items, + ); } } else if (isObject(value)) { formValidation[key] = await validate(formData, path, value); diff --git a/plugins/scaffolder-react/src/next/extensions/types.ts b/plugins/scaffolder-react/src/next/extensions/types.ts index 27778b0420..d8ed2817d3 100644 --- a/plugins/scaffolder-react/src/next/extensions/types.ts +++ b/plugins/scaffolder-react/src/next/extensions/types.ts @@ -46,7 +46,11 @@ export interface NextFieldExtensionComponentProps< export type NextCustomFieldValidator = ( data: TFieldReturnValue, field: FieldValidationV5, - context: { apiHolder: ApiHolder; formData: JsonObject }, + context: { + apiHolder: ApiHolder; + formData: JsonObject; + schema?: JsonObject; + }, ) => void | Promise; /** From cc418d652a7517b3031ce9aa277438db09bf339b Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 12:33:07 +0100 Subject: [PATCH 299/417] chore: added changeset Signed-off-by: blam --- .changeset/six-melons-rhyme.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/six-melons-rhyme.md diff --git a/.changeset/six-melons-rhyme.md b/.changeset/six-melons-rhyme.md new file mode 100644 index 0000000000..dbb878fc89 --- /dev/null +++ b/.changeset/six-melons-rhyme.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +scaffolder/next: Added the ability to get the fields definition in the schema in the validation function From 8fbcbd34b61a3bab56d6c4863f2fcc4271784c26 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 12:39:37 +0100 Subject: [PATCH 300/417] chore: this is always going to be present Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 1 + plugins/scaffolder-react/src/next/extensions/types.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 33246d8bea..69bffbf724 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -176,6 +176,7 @@ export type NextCustomFieldValidator = ( context: { apiHolder: ApiHolder; formData: JsonObject; + schema: JsonObject; }, ) => void | Promise; diff --git a/plugins/scaffolder-react/src/next/extensions/types.ts b/plugins/scaffolder-react/src/next/extensions/types.ts index d8ed2817d3..1e4c671511 100644 --- a/plugins/scaffolder-react/src/next/extensions/types.ts +++ b/plugins/scaffolder-react/src/next/extensions/types.ts @@ -49,7 +49,7 @@ export type NextCustomFieldValidator = ( context: { apiHolder: ApiHolder; formData: JsonObject; - schema?: JsonObject; + schema: JsonObject; }, ) => void | Promise; From 8c220101042ae62ff956f34f592d092c45aed14c Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Tue, 21 Feb 2023 13:09:40 +0100 Subject: [PATCH 301/417] Update slow-insects-cheat.md Signed-off-by: Ben Lambert --- .changeset/slow-insects-cheat.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.changeset/slow-insects-cheat.md b/.changeset/slow-insects-cheat.md index e07d6d6f96..70b7bbf69b 100644 --- a/.changeset/slow-insects-cheat.md +++ b/.changeset/slow-insects-cheat.md @@ -1,8 +1,7 @@ --- -'@backstage/plugin-techdocs': patch -'@backstage/plugin-catalog': patch +'@backstage/plugin-techdocs': minor +'@backstage/plugin-catalog': minor '@backstage/plugin-explore': patch --- -Add ability to pass icon as function to have ability -to customize it by search item +Add ability to pass icon as function to have ability to customize it by search item From 7a61434b9c268aa23473c988140b2e3672d4d699 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Feb 2023 12:20:11 +0000 Subject: [PATCH 302/417] chore(deps): update dependency typescript to v4.9.5 Signed-off-by: Renovate Bot --- microsite-next/yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 81d5c07f6f..3d3870d142 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -10196,22 +10196,22 @@ __metadata: linkType: hard "typescript@npm:^4.9.4": - version: 4.9.4 - resolution: "typescript@npm:4.9.4" + version: 4.9.5 + resolution: "typescript@npm:4.9.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: e782fb9e0031cb258a80000f6c13530288c6d63f1177ed43f770533fdc15740d271554cdae86701c1dd2c83b082cea808b07e97fd68b38a172a83dbf9e0d0ef9 + checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db languageName: node linkType: hard "typescript@patch:typescript@^4.9.4#~builtin": - version: 4.9.4 - resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=a1c5e5" + version: 4.9.5 + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=a1c5e5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 37f6e2c3c5e2aa5934b85b0fddbf32eeac8b1bacf3a5b51d01946936d03f5377fe86255d4e5a4ae628fd0cd553386355ad362c57f13b4635064400f3e8e05b9d + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 languageName: node linkType: hard From 17271841de8e3b004ed08a141836d851db7d4365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 21 Feb 2023 13:26:45 +0100 Subject: [PATCH 303/417] Updated frontend plugin template to use some more recent features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/perfect-mayflies-greet.md | 5 +++++ .../ExampleFetchComponent/ExampleFetchComponent.tsx.hbs | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .changeset/perfect-mayflies-greet.md diff --git a/.changeset/perfect-mayflies-greet.md b/.changeset/perfect-mayflies-greet.md new file mode 100644 index 0000000000..7e57507dae --- /dev/null +++ b/.changeset/perfect-mayflies-greet.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated frontend plugin template to use some more recent features diff --git a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs index 159fcd70c5..03b25dfb4f 100644 --- a/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs +++ b/packages/cli/templates/default-plugin/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx.hbs @@ -1,7 +1,7 @@ import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { Table, TableColumn, Progress } from '@backstage/core-components'; -import Alert from '@material-ui/lab/Alert'; +import { Table, TableColumn, Progress, ResponseErrorPanel } from '@backstage/core-components'; +import { fetchApiRef, useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; const useStyles = makeStyles({ @@ -74,6 +74,7 @@ export const DenseTable = ({ users }: DenseTableProps) => { }; export const ExampleFetchComponent = () => { + const { fetch } = useApi(fetchApiRef); const { value, loading, error } = useAsync(async (): Promise => { const response = await fetch('https://randomuser.me/api/?results=20'); const data = await response.json(); @@ -83,7 +84,7 @@ export const ExampleFetchComponent = () => { if (loading) { return ; } else if (error) { - return {error.message}; + return ; } return ; From 3ab1b8fcae463674dc2c56640628ab224e44a6a1 Mon Sep 17 00:00:00 2001 From: Morgan Bentell Date: Tue, 21 Feb 2023 13:32:45 +0100 Subject: [PATCH 304/417] avoid wrapping addons when rendering them in a test setting, the levels of nesting is very sensitive due to TechDocsReaderPage.tsx, this will result in a more realistic component tree Signed-off-by: Morgan Bentell --- plugins/techdocs-addons-test-utils/src/test-utils.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index 0d65e7e51e..53da924db5 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -236,9 +236,9 @@ export class TechDocsAddonTester { element={} > - {this.addons.map((addon, index) => ( - {addon} - ))} + {this.addons.map((addon, index) => + React.cloneElement(addon, { key: index }), + )}

    Made with ❤️ at Spotify

    From 2b00d8a225c867a2c6d62a92d1d77a94b0a4ed2e Mon Sep 17 00:00:00 2001 From: Morgan Bentell Date: Tue, 21 Feb 2023 13:35:55 +0100 Subject: [PATCH 305/417] add changeset Signed-off-by: Morgan Bentell --- .changeset/quick-schools-dress.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/quick-schools-dress.md diff --git a/.changeset/quick-schools-dress.md b/.changeset/quick-schools-dress.md new file mode 100644 index 0000000000..511709461e --- /dev/null +++ b/.changeset/quick-schools-dress.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +Fix bug/problem with test helper From 048b4ab5f564657c2b94809b150a1d28b032a4f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 21 Feb 2023 13:37:25 +0100 Subject: [PATCH 306/417] add alpha exports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/todo/package.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 3a0dd54fa8..cc988b3f45 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -8,7 +8,8 @@ "publishConfig": { "access": "public", "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "frontend-plugin" @@ -20,7 +21,7 @@ "directory": "plugins/todo" }, "scripts": { - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "start": "backstage-cli package start", "lint": "backstage-cli package lint", "test": "backstage-cli package test", @@ -57,6 +58,7 @@ "msw": "^0.49.0" }, "files": [ - "dist" + "dist", + "alpha" ] } From b2ac4ebb9431c943e652a24c3554428281d2503c Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Feb 2023 13:45:37 +0100 Subject: [PATCH 307/417] Update search index Signed-off-by: Johan Haals --- microsite-next/docusaurus.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index b050f4d914..a5dbd144da 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -218,8 +218,8 @@ module.exports = { '

    Made with ❤️ at Spotify

    ', }, algolia: { - apiKey: '10b9e6c92a4513c1cf390f50e53aad1f', - indexName: 'backstage_io', + apiKey: '1f0ba86672ccfc3576faa94583e5b318', + indexName: 'crawler_Backstage Docusaurus 2', appId: 'JCMFNHCHI8', searchParameters: {}, }, From ab4e68032d4c76a21a87a5f72956ece29690b619 Mon Sep 17 00:00:00 2001 From: Morgan Bentell Date: Tue, 21 Feb 2023 13:50:08 +0100 Subject: [PATCH 308/417] remove unused import Signed-off-by: Morgan Bentell --- plugins/techdocs-addons-test-utils/src/test-utils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index 53da924db5..e60a96402c 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { ReactElement, Fragment } from 'react'; +import React, { ReactElement } from 'react'; // Shadow DOM support for the simple and complete DOM testing utilities // https://github.com/testing-library/dom-testing-library/issues/742#issuecomment-674987855 From c765aa7558e3a375ae3f15e0f66ee282aa6e4e44 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Feb 2023 14:00:02 +0100 Subject: [PATCH 309/417] microsite: deploy new microsite Co-authored-by: blam Signed-off-by: Johan Haals --- .github/workflows/deploy_microsite.yml | 8 ++++---- microsite/static/.nojekyll | 0 microsite/static/CNAME | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 microsite/static/.nojekyll create mode 100644 microsite/static/CNAME diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 1f87c30af2..fc2adadc68 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -42,20 +42,20 @@ jobs: - name: build microsite run: yarn build - working-directory: microsite + working-directory: microsite-next - name: build storybook run: yarn build-storybook working-directory: storybook - name: move storybook dist into microsite - run: mv storybook/dist/ microsite/build/backstage/storybook + run: mv storybook/dist/ microsite-next/build/storybook - name: Check the build output - run: ls microsite/build/backstage && ls microsite/build/backstage/storybook + run: ls microsite/build && ls microsite-next/build/storybook - name: Deploy both microsite and storybook to gh-pages uses: JamesIves/github-pages-deploy-action@v4.4.1 with: branch: gh-pages - folder: microsite/build/backstage + folder: microsite-next/build diff --git a/microsite/static/.nojekyll b/microsite/static/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/microsite/static/CNAME b/microsite/static/CNAME new file mode 100644 index 0000000000..c3be0f8d9b --- /dev/null +++ b/microsite/static/CNAME @@ -0,0 +1 @@ +backstage.io \ No newline at end of file From 5a4577e8f6e6ae7ddf5fe526ab39396ed00edde1 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Feb 2023 14:06:44 +0100 Subject: [PATCH 310/417] fix working directory Signed-off-by: Johan Haals --- .github/workflows/deploy_microsite.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index fc2adadc68..61a0cd5b0f 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -32,7 +32,7 @@ jobs: run: yarn install --immutable - name: microsite yarn install run: yarn install --immutable - working-directory: microsite + working-directory: microsite-next - name: storybook yarn install run: yarn install --immutable working-directory: storybook @@ -52,7 +52,7 @@ jobs: run: mv storybook/dist/ microsite-next/build/storybook - name: Check the build output - run: ls microsite/build && ls microsite-next/build/storybook + run: ls microsite-next/build && ls microsite-next/build/storybook - name: Deploy both microsite and storybook to gh-pages uses: JamesIves/github-pages-deploy-action@v4.4.1 From 8bf24946c664a09b7dc59ea4365e63010b32c952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 21 Feb 2023 14:07:46 +0100 Subject: [PATCH 311/417] adjust some epxress dependencies to be the same as the others MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/odd-fireants-bathe.md | 6 ++++++ .../default-backend-plugin/package.json.hbs | 4 ++-- plugins/adr-backend/package.json | 6 +++--- yarn.lock | 12 ++++++------ 4 files changed, 17 insertions(+), 11 deletions(-) create mode 100644 .changeset/odd-fireants-bathe.md diff --git a/.changeset/odd-fireants-bathe.md b/.changeset/odd-fireants-bathe.md new file mode 100644 index 0000000000..d4b7f5dc5a --- /dev/null +++ b/.changeset/odd-fireants-bathe.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-adr-backend': patch +'@backstage/cli': patch +--- + +Adjust express dependencies to be the same as the rest of the project diff --git a/packages/cli/templates/default-backend-plugin/package.json.hbs b/packages/cli/templates/default-backend-plugin/package.json.hbs index 3a9091e87f..24c2bb8f0a 100644 --- a/packages/cli/templates/default-backend-plugin/package.json.hbs +++ b/packages/cli/templates/default-backend-plugin/package.json.hbs @@ -30,8 +30,8 @@ "dependencies": { "@backstage/backend-common": "{{versionQuery '@backstage/backend-common'}}", "@backstage/config": "{{versionQuery '@backstage/config'}}", - "@types/express": "{{versionQuery '@types/express' '4.17.13'}}", - "express": "{{versionQuery 'express' '4.18.1'}}", + "@types/express": "{{versionQuery '@types/express' '4.17.6'}}", + "express": "{{versionQuery 'express' '4.17.1'}}", "express-promise-router": "{{versionQuery 'express-promise-router' '4.1.0'}}", "winston": "{{versionQuery 'winston' '3.2.1'}}", "node-fetch": "{{versionQuery 'node-fetch' '2.6.7'}}", diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 2c16cca144..b6b62fbc93 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -36,9 +36,9 @@ "@backstage/integration": "workspace:^", "@backstage/plugin-adr-common": "workspace:^", "@backstage/plugin-search-common": "workspace:^", - "@types/express": "^4.17.15", - "express": "^4.18.2", - "express-promise-router": "^4.1.1", + "@types/express": "^4.17.6", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", "luxon": "^3.0.0", "marked": "^4.0.14", "node-fetch": "^2.6.5", diff --git a/yarn.lock b/yarn.lock index ee6415ebba..cb8048823a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4121,11 +4121,11 @@ __metadata: "@backstage/integration": "workspace:^" "@backstage/plugin-adr-common": "workspace:^" "@backstage/plugin-search-common": "workspace:^" - "@types/express": ^4.17.15 + "@types/express": ^4.17.6 "@types/marked": ^4.0.0 "@types/supertest": ^2.0.8 - express: ^4.18.2 - express-promise-router: ^4.1.1 + express: ^4.17.1 + express-promise-router: ^4.1.0 luxon: ^3.0.0 marked: ^4.0.14 msw: ^0.49.0 @@ -14438,7 +14438,7 @@ __metadata: languageName: node linkType: hard -"@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.15, @types/express@npm:^4.17.6": +"@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.6": version: 4.17.16 resolution: "@types/express@npm:4.17.16" dependencies: @@ -22697,7 +22697,7 @@ __metadata: languageName: node linkType: hard -"express-promise-router@npm:^4.1.0, express-promise-router@npm:^4.1.1": +"express-promise-router@npm:^4.1.0": version: 4.1.1 resolution: "express-promise-router@npm:4.1.1" dependencies: @@ -22739,7 +22739,7 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.17.1, express@npm:^4.17.3, express@npm:^4.18.1, express@npm:^4.18.2": +"express@npm:^4.17.1, express@npm:^4.17.3, express@npm:^4.18.1": version: 4.18.2 resolution: "express@npm:4.18.2" dependencies: From c8d78b9ae9d418d018df86d81cc96834a13f801b Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Tue, 21 Feb 2023 12:49:33 +0000 Subject: [PATCH 312/417] fix bug in hasErrors with empty objects Signed-off-by: Paul Cowan --- .changeset/happy-boxes-arrive.md | 5 +++ .../src/next/components/Stepper/utils.test.ts | 32 +++++++++++++++++++ .../src/next/components/Stepper/utils.ts | 4 ++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 .changeset/happy-boxes-arrive.md diff --git a/.changeset/happy-boxes-arrive.md b/.changeset/happy-boxes-arrive.md new file mode 100644 index 0000000000..85998c1bdd --- /dev/null +++ b/.changeset/happy-boxes-arrive.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +fix bug with `hasErrors` returning false when dealing with empty objects diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts index f6a1b012ac..e07c4e5508 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { type FormValidation } from './createAsyncValidators'; import { hasErrors } from './utils'; describe('hasErrors', () => { @@ -58,4 +59,35 @@ describe('hasErrors', () => { }), ).toBe(true); }); + + it('should not return false when the error is an empty object', () => { + const errors = { + something: {}, + otherThing: {}, + someName: { + __errors: [ + 'Accepts alphanumeric values along with _(underscore) and -(hypen) as special characters', + ], + addError: jest.fn(), + }, + someOtherName: { + __errors: ['Must start with an alphabet & not contain .(period)'], + addError: jest.fn(), + }, + aName: { + __errors: [], + addError: jest.fn(), + }, + bName: { + __errors: [], + addError: jest.fn(), + }, + cName: { + __errors: [], + addError: jest.fn(), + }, + }; + + expect(hasErrors(errors)).toBe(true); + }); }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts index 7d3efa9d94..0b70f57813 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/utils.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts @@ -35,7 +35,9 @@ export function hasErrors(errors?: FormValidation): boolean { continue; } - return hasErrors(error); + if (hasErrors(error)) { + return true; + } } return false; From 0c219d9c18763cf126d482a4dbb189fde8a855a0 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Tue, 21 Feb 2023 13:08:30 +0000 Subject: [PATCH 313/417] remove unused import Signed-off-by: Paul Cowan --- .../scaffolder-react/src/next/components/Stepper/utils.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts index e07c4e5508..24c62ebb35 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { type FormValidation } from './createAsyncValidators'; import { hasErrors } from './utils'; describe('hasErrors', () => { From b4cd145b574f8ac29bd63bdfb00a3cd5fd62bbee Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 9 Jan 2023 22:52:19 +0100 Subject: [PATCH 314/417] cli: added package-exports migration command Signed-off-by: Patrik Oldsberg --- .changeset/long-nails-pump.md | 5 ++ packages/cli/src/commands/index.ts | 7 ++ .../src/commands/migrate/packageExports.ts | 83 +++++++++++++++++++ packages/cli/src/lib/monorepo/PackageGraph.ts | 4 + 4 files changed, 99 insertions(+) create mode 100644 .changeset/long-nails-pump.md create mode 100644 packages/cli/src/commands/migrate/packageExports.ts diff --git a/.changeset/long-nails-pump.md b/.changeset/long-nails-pump.md new file mode 100644 index 0000000000..d9eefc0249 --- /dev/null +++ b/.changeset/long-nails-pump.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added a new `migrate package-exports` command that synchronizes package exports fields in all `package.json`s. diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 628e46df85..2fdd2442d4 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -191,6 +191,13 @@ export function registerMigrateCommand(program: Command) { lazy(() => import('./migrate/packageScripts').then(m => m.command)), ); + command + .command('package-exports') + .description('Synchronize package sub-path export definitions') + .action( + lazy(() => import('./migrate/packageExports').then(m => m.command)), + ); + command .command('package-lint-configs') .description( diff --git a/packages/cli/src/commands/migrate/packageExports.ts b/packages/cli/src/commands/migrate/packageExports.ts new file mode 100644 index 0000000000..3a59c02375 --- /dev/null +++ b/packages/cli/src/commands/migrate/packageExports.ts @@ -0,0 +1,83 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fs from 'fs-extra'; +import { resolve as resolvePath } from 'path'; +import { PackageGraph } from '../../lib/monorepo'; + +function trimRelative(path: string): string { + if (path.startsWith('./')) { + return path.slice(2); + } + return path; +} + +export async function command() { + const packages = await PackageGraph.listTargetPackages(); + + await Promise.all( + packages.map(async ({ dir, packageJson }) => { + const { exports: exp } = packageJson; + if (!exp || typeof exp !== 'object' || Array.isArray(exp)) { + return; + } + + const existingTypesVersions = JSON.stringify(packageJson.typesVersions); + + const typeEntries: Record = {}; + + for (const [path, value] of Object.entries(exp)) { + const newPath = path === '.' ? '*' : trimRelative(path); + + if (typeof value === 'string') { + typeEntries[newPath] = [trimRelative(value)]; + } else if ( + value && + typeof value === 'object' && + !Array.isArray(value) + ) { + if (typeof value.types === 'string') { + typeEntries[newPath] = [trimRelative(value.types)]; + } else if (typeof value.default === 'string') { + typeEntries[newPath] = [trimRelative(value.default)]; + } + } + } + + const typesVersions = { '*': typeEntries }; + + if (existingTypesVersions !== JSON.stringify(typesVersions)) { + console.log(`Synchronizing exports in ${packageJson.name}`); + const newPkgEntries = Object.entries(packageJson).filter( + ([name]) => name !== 'typesVersions', + ); + newPkgEntries.splice( + newPkgEntries.findIndex(([name]) => name === 'exports') + 1, + 0, + ['typesVersions', typesVersions], + ); + + await fs.writeJson( + resolvePath(dir, 'package.json'), + Object.fromEntries(newPkgEntries), + { + spaces: 2, + }, + ); + } + }), + ); +} diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index a1fc95e669..d34ede41ae 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -20,6 +20,7 @@ import { paths } from '../paths'; import { PackageRole } from '../role'; import { listChangedFiles, readFileAtRef } from '../git'; import { Lockfile } from '../versioning'; +import { JsonValue } from '@backstage/types'; type PackageJSON = Package['packageJson']; @@ -34,6 +35,9 @@ export interface ExtendedPackageJSON extends PackageJSON { backstage?: { role?: PackageRole; }; + + exports?: JsonValue; + typesVersions?: Record>; } export type ExtendedPackage = { From a9b88cda173d2d8559eb377553d12d35dcbcd3e0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Jan 2023 14:16:34 +0100 Subject: [PATCH 315/417] cli: add exports support for package builds Signed-off-by: Patrik Oldsberg --- .../cli/src/commands/build/buildBackend.ts | 1 + packages/cli/src/commands/repo/build.ts | 1 + packages/cli/src/lib/builder/config.test.ts | 5 + packages/cli/src/lib/builder/config.ts | 214 ++++++++++-------- packages/cli/src/lib/builder/types.ts | 3 + packages/cli/src/lib/monorepo/PackageGraph.ts | 3 + packages/cli/src/lib/monorepo/entryPoints.ts | 73 ++++++ .../src/lib/packager/createDistWorkspace.ts | 1 + 8 files changed, 203 insertions(+), 98 deletions(-) create mode 100644 packages/cli/src/lib/monorepo/entryPoints.ts diff --git a/packages/cli/src/commands/build/buildBackend.ts b/packages/cli/src/commands/build/buildBackend.ts index d7c4f72dbe..7e61f9ae85 100644 --- a/packages/cli/src/commands/build/buildBackend.ts +++ b/packages/cli/src/commands/build/buildBackend.ts @@ -37,6 +37,7 @@ export async function buildBackend(options: BuildBackendOptions) { // We build the target package without generating type declarations. await buildPackage({ targetDir: options.targetDir, + packageJson: pkg, outputs: new Set([Output.cjs]), }); diff --git a/packages/cli/src/commands/repo/build.ts b/packages/cli/src/commands/repo/build.ts index a6bf87da82..d5602a4008 100644 --- a/packages/cli/src/commands/repo/build.ts +++ b/packages/cli/src/commands/repo/build.ts @@ -130,6 +130,7 @@ export async function command(opts: OptionValues, cmd: Command): Promise { return { targetDir: pkg.dir, + packageJson: pkg.packageJson, outputs, logPrefix: `${chalk.cyan(relativePath(paths.targetRoot, pkg.dir))}: `, minify: buildOptions.minify, diff --git a/packages/cli/src/lib/builder/config.test.ts b/packages/cli/src/lib/builder/config.test.ts index a2e99da73b..733c35fb55 100644 --- a/packages/cli/src/lib/builder/config.test.ts +++ b/packages/cli/src/lib/builder/config.test.ts @@ -24,6 +24,11 @@ describe('makeRollupConfigs', () => { const [config] = await makeRollupConfigs({ outputs: new Set([Output.cjs]), + packageJson: { + name: 'test', + version: '0.0.0', + main: './src/index.ts', + }, }); const external = config.external as Exclude< ExternalOption, diff --git a/packages/cli/src/lib/builder/config.ts b/packages/cli/src/lib/builder/config.ts index 1cfaf15bfc..ecd755d05b 100644 --- a/packages/cli/src/lib/builder/config.ts +++ b/packages/cli/src/lib/builder/config.ts @@ -31,6 +31,10 @@ import { forwardFileImports } from './plugins'; import { BuildOptions, Output } from './types'; import { paths } from '../paths'; import { svgrTemplate } from '../svgrTemplate'; +import { ExtendedPackageJSON } from '../monorepo'; +import { readEntryPoints } from '../monorepo/entryPoints'; + +const SCRIPT_EXTS = ['.js', '.jsx', '.ts', '.tsx']; function isFileImport(source: string) { if (source.startsWith('.')) { @@ -50,6 +54,13 @@ export async function makeRollupConfigs( ): Promise { const configs = new Array(); const targetDir = options.targetDir ?? paths.targetDir; + + let targetPkg = options.packageJson; + if (!targetPkg) { + const packagePath = resolvePath(targetDir, 'package.json'); + targetPkg = (await fs.readJson(packagePath)) as ExtendedPackageJSON; + } + const onwarn = ({ code, message }: RollupWarning) => { if (code === 'EMPTY_BUNDLE') { return; // We don't care about this one @@ -62,111 +73,118 @@ export async function makeRollupConfigs( }; const distDir = resolvePath(targetDir, 'dist'); + const entryPoints = readEntryPoints(targetPkg); - if (options.outputs.has(Output.cjs) || options.outputs.has(Output.esm)) { - const output = new Array(); - const mainFields = ['module', 'main']; - - if (options.outputs.has(Output.cjs)) { - output.push({ - dir: distDir, - entryFileNames: 'index.cjs.js', - chunkFileNames: 'cjs/[name]-[hash].cjs.js', - format: 'commonjs', - sourcemap: true, - }); - } - if (options.outputs.has(Output.esm)) { - output.push({ - dir: distDir, - entryFileNames: 'index.esm.js', - chunkFileNames: 'esm/[name]-[hash].esm.js', - format: 'module', - sourcemap: true, - }); - // Assume we're building for the browser if ESM output is included - mainFields.unshift('browser'); + for (const { path, name, ext } of entryPoints) { + if (!SCRIPT_EXTS.includes(ext)) { + continue; } - configs.push({ - input: resolvePath(targetDir, 'src/index.ts'), - output, - onwarn, - preserveEntrySignatures: 'strict', - // All module imports are always marked as external - external: (source, importer, isResolved) => - Boolean(importer && !isResolved && !isFileImport(source)), - plugins: [ - resolve({ mainFields }), - commonjs({ - include: /node_modules/, - exclude: [/\/[^/]+\.(?:stories|test)\.[^/]+$/], - }), - postcss(), - forwardFileImports({ - exclude: /\.icon\.svg$/, - include: [ - /\.svg$/, - /\.png$/, - /\.gif$/, - /\.jpg$/, - /\.jpeg$/, - /\.eot$/, - /\.woff$/, - /\.woff2$/, - /\.ttf$/, - ], - }), - json(), - yaml(), - svgr({ - include: /\.icon\.svg$/, - template: svgrTemplate, - }), - esbuild({ - target: 'es2019', - minify: options.minify, - }), - ], - }); - } + if (options.outputs.has(Output.cjs) || options.outputs.has(Output.esm)) { + const output = new Array(); + const mainFields = ['module', 'main']; - if (options.outputs.has(Output.types) && !options.useApiExtractor) { - const typesInput = paths.resolveTargetRoot( - 'dist-types', - relativePath(paths.targetRoot, targetDir), - 'src/index.d.ts', - ); + if (options.outputs.has(Output.cjs)) { + output.push({ + dir: distDir, + entryFileNames: `${name}.cjs.js`, + chunkFileNames: `cjs/${name}/[name]-[hash].cjs.js`, + format: 'commonjs', + sourcemap: true, + }); + } + if (options.outputs.has(Output.esm)) { + output.push({ + dir: distDir, + entryFileNames: `${name}.esm.js`, + chunkFileNames: `esm/${name}/[name]-[hash].esm.js`, + format: 'module', + sourcemap: true, + }); + // Assume we're building for the browser if ESM output is included + mainFields.unshift('browser'); + } - const declarationsExist = await fs.pathExists(typesInput); - if (!declarationsExist) { - const path = relativePath(targetDir, typesInput); - throw new Error( - `No declaration files found at ${path}, be sure to run ${chalk.bgRed.white( - 'yarn tsc', - )} to generate .d.ts files before packaging`, + configs.push({ + input: resolvePath(targetDir, path), + output, + onwarn, + preserveEntrySignatures: 'strict', + // All module imports are always marked as external + external: (source, importer, isResolved) => + Boolean(importer && !isResolved && !isFileImport(source)), + plugins: [ + resolve({ mainFields }), + commonjs({ + include: /node_modules/, + exclude: [/\/[^/]+\.(?:stories|test)\.[^/]+$/], + }), + postcss(), + forwardFileImports({ + exclude: /\.icon\.svg$/, + include: [ + /\.svg$/, + /\.png$/, + /\.gif$/, + /\.jpg$/, + /\.jpeg$/, + /\.eot$/, + /\.woff$/, + /\.woff2$/, + /\.ttf$/, + ], + }), + json(), + yaml(), + svgr({ + include: /\.icon\.svg$/, + template: svgrTemplate, + }), + esbuild({ + target: 'es2019', + minify: options.minify, + }), + ], + }); + } + + if (options.outputs.has(Output.types) && !options.useApiExtractor) { + const typesInput = paths.resolveTargetRoot( + 'dist-types', + relativePath(paths.targetRoot, targetDir), + path.replace(/\.ts$/, '.d.ts'), ); - } - configs.push({ - input: typesInput, - output: { - file: resolvePath(distDir, 'index.d.ts'), - format: 'es', - }, - external: [ - /\.css$/, - /\.scss$/, - /\.sass$/, - /\.svg$/, - /\.eot$/, - /\.woff$/, - /\.woff2$/, - /\.ttf$/, - ], - onwarn, - plugins: [dts()], - }); + const declarationsExist = await fs.pathExists(typesInput); + if (!declarationsExist) { + const declarationPath = relativePath(targetDir, typesInput); + throw new Error( + `No declaration files found at ${declarationPath}, be sure to run ${chalk.bgRed.white( + 'yarn tsc', + )} to generate .d.ts files before packaging`, + ); + } + + configs.push({ + input: typesInput, + output: { + file: resolvePath(distDir, `${name}.d.ts`), + format: 'es', + }, + external: [ + /\.css$/, + /\.scss$/, + /\.sass$/, + /\.svg$/, + /\.eot$/, + /\.woff$/, + /\.woff2$/, + /\.ttf$/, + ], + onwarn, + plugins: [dts()], + }); + } } return configs; diff --git a/packages/cli/src/lib/builder/types.ts b/packages/cli/src/lib/builder/types.ts index f43d84cd92..de7e9b10eb 100644 --- a/packages/cli/src/lib/builder/types.ts +++ b/packages/cli/src/lib/builder/types.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { ExtendedPackageJSON } from '../monorepo'; + export enum Output { esm, cjs, @@ -23,6 +25,7 @@ export enum Output { export type BuildOptions = { logPrefix?: string; targetDir?: string; + packageJson?: ExtendedPackageJSON; outputs: Set; minify?: boolean; useApiExtractor?: boolean; diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index d34ede41ae..421d9aa25b 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -25,6 +25,9 @@ import { JsonValue } from '@backstage/types'; type PackageJSON = Package['packageJson']; export interface ExtendedPackageJSON extends PackageJSON { + main?: string; + module?: string; + scripts?: { [key: string]: string; }; diff --git a/packages/cli/src/lib/monorepo/entryPoints.ts b/packages/cli/src/lib/monorepo/entryPoints.ts new file mode 100644 index 0000000000..8a8bbd27f9 --- /dev/null +++ b/packages/cli/src/lib/monorepo/entryPoints.ts @@ -0,0 +1,73 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { extname } from 'path'; +import { ExtendedPackageJSON } from './PackageGraph'; + +export interface EntryPoint { + mount: string; + path: string; + name: string; + ext: string; +} + +function parseEntryPoint(mount: string, path: string): EntryPoint { + let name = mount; + if (name === '.') { + name = 'index'; + } else if (name.startsWith('./')) { + name = name.slice(2); + } + if (name.includes('/')) { + throw new Error(`Mount point '${mount}' may not contain multiple slashes`); + } + + return { mount, path, name, ext: extname(path) }; +} + +export function readEntryPoints(pkg: ExtendedPackageJSON): Array { + const exp = pkg.exports; + if (typeof exp === 'string') { + return [parseEntryPoint('.', exp)]; + } else if (exp && typeof exp === 'object' && !Array.isArray(exp)) { + const entryPoints = new Array<{ + mount: string; + path: string; + name: string; + ext: string; + }>(); + + for (const mount of Object.keys(exp)) { + const path = exp[mount]; + if (typeof path !== 'string') { + throw new Error( + `Exports field value must be a string, got '${JSON.stringify(path)}'`, + ); + } + + entryPoints.push(parseEntryPoint(mount, path)); + } + + return entryPoints; + } + + const main = pkg.main || pkg.module; + if (main) { + return [parseEntryPoint('.', main)]; + } + + return []; +} diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts index 5451a873f7..28b5526fc9 100644 --- a/packages/cli/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/lib/packager/createDistWorkspace.ts @@ -178,6 +178,7 @@ export async function createDistWorkspace( if (outputs.size > 0) { standardBuilds.push({ targetDir: pkg.dir, + packageJson: pkg.packageJson, outputs: outputs, logPrefix: `${chalk.cyan(relativePath(paths.targetRoot, pkg.dir))}: `, // No need to detect these for the backend builds, we assume no minification or types From 3099c54f228bef4508d6fb508e5207954c5c9c3e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Jan 2023 16:37:33 +0100 Subject: [PATCH 316/417] cli: unify production packing logic and add support for exports field Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/pack.ts | 73 +----- packages/cli/src/lib/monorepo/PackageGraph.ts | 1 + .../cli/src/lib/packager/copyPackageDist.ts | 93 -------- .../src/lib/packager/createDistWorkspace.ts | 7 +- .../cli/src/lib/packager/productionPack.ts | 223 ++++++++++++++++++ 5 files changed, 235 insertions(+), 162 deletions(-) delete mode 100644 packages/cli/src/lib/packager/copyPackageDist.ts create mode 100644 packages/cli/src/lib/packager/productionPack.ts diff --git a/packages/cli/src/commands/pack.ts b/packages/cli/src/commands/pack.ts index 6c88ac055f..9c101e97fe 100644 --- a/packages/cli/src/commands/pack.ts +++ b/packages/cli/src/commands/pack.ts @@ -14,77 +14,16 @@ * limitations under the License. */ -import fs from 'fs-extra'; +import { + productionPack, + revertProductionPack, +} from '../lib/packager/productionPack'; import { paths } from '../lib/paths'; -import { join as joinPath } from 'path'; - -const SKIPPED_KEYS = ['access', 'registry', 'tag', 'alphaTypes', 'betaTypes']; - -const PKG_PATH = 'package.json'; -const PKG_BACKUP_PATH = 'package.json-prepack'; - -function resolveEntrypoint(pkg: any, name: string) { - const targetEntry = pkg.publishConfig[name] || pkg[name]; - return targetEntry && joinPath('..', targetEntry); -} - -// Writes e.g. alpha/package.json -async function writeReleaseStageEntrypoint(pkg: any, stage: 'alpha' | 'beta') { - await fs.ensureDir(paths.resolveTarget(stage)); - await fs.writeJson( - paths.resolveTarget(stage, PKG_PATH), - { - name: pkg.name, - version: pkg.version, - main: resolveEntrypoint(pkg, 'main'), - module: resolveEntrypoint(pkg, 'module'), - browser: resolveEntrypoint(pkg, 'browser'), - types: joinPath('..', pkg.publishConfig[`${stage}Types`]), - }, - { encoding: 'utf8', spaces: 2 }, - ); -} export const pre = async () => { - const pkgPath = paths.resolveTarget(PKG_PATH); - - const pkgContent = await fs.readFile(pkgPath, 'utf8'); - const pkg = JSON.parse(pkgContent); - await fs.writeFile(PKG_BACKUP_PATH, pkgContent); - - const publishConfig = pkg.publishConfig ?? {}; - for (const key of Object.keys(publishConfig)) { - if (!SKIPPED_KEYS.includes(key)) { - pkg[key] = publishConfig[key]; - } - } - await fs.writeJson(pkgPath, pkg, { encoding: 'utf8', spaces: 2 }); - - if (publishConfig.alphaTypes) { - await writeReleaseStageEntrypoint(pkg, 'alpha'); - } - if (publishConfig.betaTypes) { - await writeReleaseStageEntrypoint(pkg, 'beta'); - } + await productionPack({ packageDir: paths.targetDir }); }; export const post = async () => { - // postpack isn't called by yarn right now, so it needs to be called manually - try { - await fs.move(PKG_BACKUP_PATH, PKG_PATH, { overwrite: true }); - - // Check if we're shipping types for other release stages, clean up in that case - const pkg = await fs.readJson(PKG_PATH); - if (pkg.publishConfig?.alphaTypes) { - await fs.remove(paths.resolveTarget('alpha')); - } - if (pkg.publishConfig?.betaTypes) { - await fs.remove(paths.resolveTarget('beta')); - } - } catch (error) { - console.warn( - `Failed to restore package.json during postpack, ${error}. ` + - 'Your package will be fine but you may have ended up with some garbage in the repo.', - ); - } + await revertProductionPack(paths.targetDir); }; diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index 421d9aa25b..b6d6d927a6 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -27,6 +27,7 @@ type PackageJSON = Package['packageJson']; export interface ExtendedPackageJSON extends PackageJSON { main?: string; module?: string; + types?: string; scripts?: { [key: string]: string; diff --git a/packages/cli/src/lib/packager/copyPackageDist.ts b/packages/cli/src/lib/packager/copyPackageDist.ts deleted file mode 100644 index b704148542..0000000000 --- a/packages/cli/src/lib/packager/copyPackageDist.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2022 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 fs from 'fs-extra'; -import npmPackList from 'npm-packlist'; -import { join as joinPath, resolve as resolvePath } from 'path'; - -const SKIPPED_KEYS = ['access', 'registry', 'tag', 'alphaTypes', 'betaTypes']; - -function resolveEntrypoint(pkg: any, name: string) { - const targetEntry = pkg.publishConfig[name] || pkg[name]; - return targetEntry && joinPath('..', targetEntry); -} - -// Writes e.g. alpha/package.json -async function writeReleaseStageEntrypoint( - pkg: any, - stage: 'alpha' | 'beta', - targetDir: string, -) { - await fs.ensureDir(resolvePath(targetDir, stage)); - await fs.writeJson( - resolvePath(targetDir, stage, 'package.json'), - { - name: pkg.name, - version: pkg.version, - main: resolveEntrypoint(pkg, 'main'), - module: resolveEntrypoint(pkg, 'module'), - browser: resolveEntrypoint(pkg, 'browser'), - types: joinPath('..', pkg.publishConfig[`${stage}Types`]), - }, - { encoding: 'utf8', spaces: 2 }, - ); -} - -export async function copyPackageDist(packageDir: string, targetDir: string) { - const pkgPath = resolvePath(packageDir, 'package.json'); - const pkgContent = await fs.readFile(pkgPath, 'utf8'); - const pkg = JSON.parse(pkgContent); - - const publishConfig = pkg.publishConfig ?? {}; - for (const key of Object.keys(publishConfig)) { - if (!SKIPPED_KEYS.includes(key)) { - pkg[key] = publishConfig[key]; - } - } - - // We remove the dependencies from package.json of packages that are marked - // as bundled, so that yarn doesn't try to install them. - if (pkg.bundled) { - delete pkg.dependencies; - delete pkg.devDependencies; - delete pkg.peerDependencies; - delete pkg.optionalDependencies; - } - - // Lists all dist files, respecting .npmignore, files field in package.json, etc. - const filePaths = await npmPackList({ - path: packageDir, - // This makes sure we use the update package.json when listing files - packageJsonCache: new Map([[resolvePath(packageDir, 'package.json'), pkg]]), - }); - - await fs.ensureDir(targetDir); - for (const filePath of filePaths.sort()) { - const target = resolvePath(targetDir, filePath); - if (filePath === 'package.json') { - await fs.writeJson(target, pkg, { encoding: 'utf8', spaces: 2 }); - } else { - await fs.copy(resolvePath(packageDir, filePath), target); - } - } - - if (publishConfig.alphaTypes) { - await writeReleaseStageEntrypoint(pkg, 'alpha', targetDir); - } - if (publishConfig.betaTypes) { - await writeReleaseStageEntrypoint(pkg, 'beta', targetDir); - } -} diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts index 28b5526fc9..2d2967fc44 100644 --- a/packages/cli/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/lib/packager/createDistWorkspace.ts @@ -37,7 +37,7 @@ import { getOutputsForRole, Output, } from '../builder'; -import { copyPackageDist } from './copyPackageDist'; +import { productionPack } from './productionPack'; import { getRoleInfo } from '../role'; import { runParallelWorkers } from '../parallel'; @@ -258,7 +258,10 @@ async function moveToDistWorkspace( const outputDir = relativePath(paths.targetRoot, target.dir); const absoluteOutputPath = resolvePath(workspaceDir, outputDir); - await copyPackageDist(target.dir, absoluteOutputPath); + await productionPack({ + packageDir: target.dir, + targetDir: absoluteOutputPath, + }); }), ); diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts new file mode 100644 index 0000000000..c58cdab5a0 --- /dev/null +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -0,0 +1,223 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fs from 'fs-extra'; +import npmPackList from 'npm-packlist'; +import { join as joinPath, resolve as resolvePath } from 'path'; +import { ExtendedPackageJSON } from '../monorepo'; +import { readEntryPoints } from '../monorepo/entryPoints'; + +const PKG_PATH = 'package.json'; +const PKG_BACKUP_PATH = 'package.json-prepack'; + +const SKIPPED_KEYS = ['access', 'registry', 'tag', 'alphaTypes', 'betaTypes']; + +interface ProductionPackOptions { + packageDir: string; + targetDir?: string; +} + +export async function productionPack(options: ProductionPackOptions) { + const { packageDir, targetDir } = options; + const pkgPath = resolvePath(packageDir, PKG_PATH); + const pkgContent = await fs.readFile(pkgPath, 'utf8'); + const pkg = JSON.parse(pkgContent) as ExtendedPackageJSON; + + // If we're making the update in-line, back up the package.json + if (!targetDir) { + await fs.writeFile(PKG_BACKUP_PATH, pkgContent); + } + + const hasStageEntry = + !!pkg.publishConfig?.alphaTypes || !!pkg.publishConfig?.betaTypes; + if (pkg.exports && hasStageEntry) { + throw new Error( + 'Combining both exports and alpha/beta types is not supported', + ); + } + + // This mutates pkg to fill in index exports, so call it before applying publishConfig + if (pkg.exports) { + await writeExportsEntryPoints(pkg, targetDir ?? packageDir); + } + + // TODO(Rugvip): Once exports are rolled out more broadly we should deprecate and remove this behavior + const publishConfig = pkg.publishConfig ?? {}; + for (const key of Object.keys(publishConfig)) { + if (!SKIPPED_KEYS.includes(key)) { + (pkg as any)[key] = publishConfig[key as keyof typeof publishConfig]; + } + } + + // We remove the dependencies from package.json of packages that are marked + // as bundled, so that yarn doesn't try to install them. + if (pkg.bundled) { + delete pkg.dependencies; + delete pkg.devDependencies; + delete pkg.peerDependencies; + delete pkg.optionalDependencies; + } + + if (targetDir) { + // Lists all dist files, respecting .npmignore, files field in package.json, etc. + const filePaths = await npmPackList({ + path: packageDir, + // This makes sure we use the updated package.json when listing files + packageJsonCache: new Map([ + [resolvePath(packageDir, PKG_PATH), pkg], + ]) as any, // Seems like this parameter type is wrong, + }); + + await fs.ensureDir(targetDir); + for (const filePath of filePaths.sort()) { + const target = resolvePath(targetDir, filePath); + if (filePath === PKG_PATH) { + await fs.writeJson(target, pkg, { encoding: 'utf8', spaces: 2 }); + } else { + await fs.copy(resolvePath(packageDir, filePath), target); + } + } + } else { + await fs.writeJson(pkgPath, pkg, { encoding: 'utf8', spaces: 2 }); + } + + if (publishConfig.alphaTypes) { + await writeReleaseStageEntrypoint(pkg, 'alpha', targetDir ?? packageDir); + } + if (publishConfig.betaTypes) { + await writeReleaseStageEntrypoint(pkg, 'beta', targetDir ?? packageDir); + } +} + +// Reverts the changes made by productionPack when called without a targetDir. +export async function revertProductionPack(packageDir: string) { + // postpack isn't called by yarn right now, so it needs to be called manually + try { + await fs.move(PKG_BACKUP_PATH, PKG_PATH, { overwrite: true }); + + // Check if we're shipping types for other release stages, clean up in that case + const pkg = await fs.readJson(PKG_PATH); + if (pkg.publishConfig?.alphaTypes) { + await fs.remove(resolvePath(packageDir, 'alpha')); + } + if (pkg.publishConfig?.betaTypes) { + await fs.remove(resolvePath(packageDir, 'beta')); + } + + // Remove any extra entrypoint backwards compatibility directories + const entryPoints = readEntryPoints(pkg); + for (const entryPoint of entryPoints) { + if (entryPoint.mount !== '.') { + await fs.remove(resolvePath(packageDir, entryPoint.name)); + } + } + } catch (error) { + console.warn( + `Failed to restore package.json, ${error}. ` + + 'Your package will be fine but you may have ended up with some garbage in the repo.', + ); + } +} + +function resolveEntrypoint(pkg: any, name: string) { + const targetEntry = pkg.publishConfig[name] || pkg[name]; + return targetEntry && joinPath('..', targetEntry); +} + +// Writes e.g. alpha/package.json +async function writeReleaseStageEntrypoint( + pkg: ExtendedPackageJSON, + stage: 'alpha' | 'beta', + targetDir: string, +) { + await fs.ensureDir(resolvePath(targetDir, stage)); + await fs.writeJson( + resolvePath(targetDir, stage, PKG_PATH), + { + name: pkg.name, + version: pkg.version, + main: resolveEntrypoint(pkg, 'main'), + module: resolveEntrypoint(pkg, 'module'), + browser: resolveEntrypoint(pkg, 'browser'), + types: joinPath('..', pkg.publishConfig![`${stage}Types`]!), + }, + { encoding: 'utf8', spaces: 2 }, + ); +} + +const EXPORT_MAP = { + import: '.esm.js', + require: '.cjs.js', + types: '.d.ts', +}; + +/** + * Rewrites the exports field in package.json to point to dist files, as + * well as creating backwards compatibility entry points for importers + * that don't support exports. + */ +async function writeExportsEntryPoints( + pkg: ExtendedPackageJSON, + targetDir: string, +) { + const distFiles = await fs.readdir(resolvePath(targetDir, 'dist')); + const outputExports = {} as Record>; + + const entryPoints = readEntryPoints(pkg); + for (const entryPoint of entryPoints) { + const exp = {} as Record; + for (const [key, ext] of Object.entries(EXPORT_MAP)) { + const name = `${entryPoint.name}${ext}`; + if (distFiles.includes(name)) { + exp[key] = `./${joinPath(`dist`, name)}`; + } + } + exp.default = exp.require ?? exp.import; + + // This creates a directory with a lone package.json for backwards compatibility + if (entryPoint.mount === '.') { + if (exp.default) { + pkg.main = exp.default; + } + if (exp.import) { + pkg.module = exp.import; + } + if (exp.types) { + pkg.types = exp.types; + } + } else { + const entryPointDir = resolvePath(targetDir, entryPoint.name); + await fs.ensureDir(entryPointDir); + await fs.writeJson( + resolvePath(entryPointDir, PKG_PATH), + { + name: pkg.name, + version: pkg.version, + ...(exp.default ? { main: joinPath('..', exp.default) } : {}), + ...(exp.import ? { module: joinPath('..', exp.import) } : {}), + ...(exp.types ? { types: joinPath('..', exp.types) } : {}), + }, + { encoding: 'utf8', spaces: 2 }, + ); + } + + if (Object.keys(exp).length > 0) { + outputExports[entryPoint.mount] = exp; + } + } + + pkg.exports = outputExports; +} From 6ba8faf22ac366dcd502602d15be2f842e9495b2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Jan 2023 17:20:02 +0100 Subject: [PATCH 317/417] repo-tools: add support for API reports for additional entry points Signed-off-by: Patrik Oldsberg --- .changeset/yellow-bananas-yawn.md | 5 ++ .../src/commands/api-reports/api-extractor.ts | 47 ++++++++++++++++--- 2 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 .changeset/yellow-bananas-yawn.md diff --git a/.changeset/yellow-bananas-yawn.md b/.changeset/yellow-bananas-yawn.md new file mode 100644 index 0000000000..d9c522a429 --- /dev/null +++ b/.changeset/yellow-bananas-yawn.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +The API report generation process is now able to detect and generate reports for additional entry points declared in the package `"exports"` field. diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index 39df70c21a..c9081255b8 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -300,6 +300,33 @@ function logApiReportInstructions() { console.log(''); } +async function findPackageEntryPoints( + packageDirs: string[], +): Promise> { + return Promise.all( + packageDirs.map(async packageDir => { + const pkg = await fs.readJson( + cliPaths.resolveTargetRoot(packageDir, 'package.json'), + ); + + if (pkg.exports && typeof pkg.exports !== 'string') { + return Object.keys(pkg.exports).map(mount => { + let name = mount; + if (name.startsWith('./')) { + name = name.slice(2); + } + if (!name || name === '.') { + return { packageDir, name: 'index' }; + } + return { packageDir, name }; + }); + } + + return { packageDir, name: 'index' }; + }), + ).then(results => results.flat()); +} + interface ApiExtractionOptions { packageDirs: string[]; outputDir: string; @@ -319,9 +346,11 @@ export async function runApiExtraction({ }: ApiExtractionOptions) { await fs.remove(outputDir); - const entryPoints = packageDirs.map(packageDir => { + const packageEntryPoints = await findPackageEntryPoints(packageDirs); + + const entryPoints = packageEntryPoints.map(({ packageDir, name }) => { return cliPaths.resolveTargetRoot( - `./dist-types/${packageDir}/src/index.d.ts`, + `./dist-types/${packageDir}/src/${name}.d.ts`, ); }); @@ -337,7 +366,7 @@ export async function runApiExtraction({ } const warnings = new Array(); - for (const packageDir of packageDirs) { + for (const { packageDir, name } of packageEntryPoints) { console.log(`## Processing ${packageDir}`); const noBail = Array.isArray(allowWarnings) ? allowWarnings.some(aw => aw === packageDir || minimatch(packageDir, aw)) @@ -351,9 +380,10 @@ export async function runApiExtraction({ const warningCountBefore = await countApiReportWarnings(projectFolder); + const prefix = name === 'index' ? '' : `${name}-`; const extractorConfig = ExtractorConfig.prepare({ configObject: { - mainEntryPointFilePath: resolvePath(packageFolder, 'src/index.d.ts'), + mainEntryPointFilePath: resolvePath(packageFolder, `src/${name}.d.ts`), bundledPackages: [], compiler: { @@ -362,16 +392,19 @@ export async function runApiExtraction({ apiReport: { enabled: true, - reportFileName: 'api-report.md', + reportFileName: `${prefix}api-report.md`, reportFolder: projectFolder, - reportTempFolder: resolvePath(outputDir, ''), + reportTempFolder: resolvePath( + outputDir, + `${prefix}`, + ), }, docModel: { enabled: true, apiJsonFilePath: resolvePath( outputDir, - '.api.json', + `${prefix}.api.json`, ), }, From a5e66e59cb222351dba72dac3ce369574ed22468 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Jan 2023 17:28:49 +0100 Subject: [PATCH 318/417] backend-app-api,backend-plugin-api: removed unused usage of experimental type build Signed-off-by: Patrik Oldsberg --- packages/backend-app-api/package.json | 5 ++--- packages/backend-plugin-api/package.json | 5 ++--- plugins/techdocs-react/package.json | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index f6672f1fbb..9c105fb474 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -7,8 +7,7 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "types": "dist/index.d.ts" }, "backstage": { "role": "node-library" @@ -24,7 +23,7 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index f8af9e5bdc..30ea47c520 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -7,8 +7,7 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "types": "dist/index.d.ts" }, "backstage": { "role": "node-library" @@ -24,7 +23,7 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 34f78f9d84..7f7fd06bec 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -4,7 +4,6 @@ "version": "1.1.3", "publishConfig": { "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, @@ -25,7 +24,7 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", From 1cece753173800c44704d83fb74d37b734e9e97f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 14 Jan 2023 17:41:04 +0100 Subject: [PATCH 319/417] cli: add automatic exports compatibility entry point addition to files field Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/monorepo/PackageGraph.ts | 2 ++ packages/cli/src/lib/packager/productionPack.ts | 3 +++ 2 files changed, 5 insertions(+) diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index b6d6d927a6..7bca16a6f7 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -42,6 +42,8 @@ export interface ExtendedPackageJSON extends PackageJSON { exports?: JsonValue; typesVersions?: Record>; + + files?: string[]; } export type ExtendedPackage = { diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index c58cdab5a0..9f11c10222 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -212,6 +212,9 @@ async function writeExportsEntryPoints( }, { encoding: 'utf8', spaces: 2 }, ); + if (Array.isArray(pkg.files) && !pkg.files.includes(entryPoint.name)) { + pkg.files.push(entryPoint.name); + } } if (Object.keys(exp).length > 0) { From 801b2551e357cea9dd855201a2d99fd3a7caad41 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 00:17:32 +0100 Subject: [PATCH 320/417] repo-tools: add release tag validation option Signed-off-by: Patrik Oldsberg --- package.json | 2 +- .../src/commands/api-reports/api-extractor.ts | 26 +++++++++++++++++++ .../src/commands/api-reports/api-reports.ts | 2 ++ packages/repo-tools/src/commands/index.ts | 4 +++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5383ba3d51..c06d353501 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build:backend": "yarn workspace backend build", "build:all": "backstage-cli repo build --all", "build:api-reports": "yarn build:api-reports:only --tsc", - "build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings 'packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type", + "build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings 'packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type --validate-release-tags", "build:api-docs": "LANG=en_EN yarn build:api-reports --docs", "tsc": "tsc", "tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false", diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index c9081255b8..91df053f22 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -334,6 +334,7 @@ interface ApiExtractionOptions { tsconfigFilePath: string; allowWarnings?: boolean | string[]; omitMessages?: string[]; + validateReleaseTags?: boolean; } export async function runApiExtraction({ @@ -343,6 +344,7 @@ export async function runApiExtraction({ tsconfigFilePath, allowWarnings = false, omitMessages = [], + validateReleaseTags = false, }: ApiExtractionOptions) { await fs.remove(outputDir); @@ -494,6 +496,30 @@ export async function runApiExtraction({ compilerState, }); + // This release tag validation makes sure that the release tag of known entry points match expectations. + // The root index entrypoint is only allowed @public exports, while /alpha and /beta only allow @alpha and @beta. + if (validateReleaseTags) { + if (['index', 'alpha', 'beta'].includes(name)) { + const report = await fs.readFile( + extractorConfig.reportFilePath, + 'utf8', + ); + const lines = report.split(/\r?\n/); + const expectedTag = name === 'index' ? 'public' : name; + for (let i = 0; i < lines.length; i += 1) { + const line = lines[i]; + const match = line.match(/^\/\/ @(alpha|beta|public)/); + if (match && match[1] !== expectedTag) { + throw new Error( + `Unexpected release tag ${match[1]} in ${ + extractorConfig.reportFilePath + } at line ${i + 1}`, + ); + } + } + } + } + if (!extractorResult.succeeded) { if (shouldLogInstructions) { logApiReportInstructions(); diff --git a/packages/repo-tools/src/commands/api-reports/api-reports.ts b/packages/repo-tools/src/commands/api-reports/api-reports.ts index 66436644d2..a917975750 100644 --- a/packages/repo-tools/src/commands/api-reports/api-reports.ts +++ b/packages/repo-tools/src/commands/api-reports/api-reports.ts @@ -33,6 +33,7 @@ type Options = { allowWarnings?: string; allowAllWarnings?: boolean; omitMessages?: string; + validateReleaseTags?: boolean; } & OptionValues; export const buildApiReports = async (paths: string[] = [], opts: Options) => { @@ -90,6 +91,7 @@ export const buildApiReports = async (paths: string[] = [], opts: Options) => { tsconfigFilePath, allowWarnings: allowAllWarnings || allowWarnings, omitMessages: Array.isArray(omitMessages) ? omitMessages : [], + validateReleaseTags: opts.validateReleaseTags, }); } if (cliPackageDirs.length > 0) { diff --git a/packages/repo-tools/src/commands/index.ts b/packages/repo-tools/src/commands/index.ts index f7a16b6d4e..f283e9c743 100644 --- a/packages/repo-tools/src/commands/index.ts +++ b/packages/repo-tools/src/commands/index.ts @@ -37,6 +37,10 @@ export function registerCommands(program: Command) { '-o, --omit-messages ', 'select some message code to be omited on the API Extractor (comma separated values i.e ae-cyclic-inherit-doc,ae-missing-getter )', ) + .option( + '--validate-release-tags', + 'Turn on release tag validation for the public, beta, and alpha APIs', + ) .description('Generate an API report for selected packages') .action( lazy(() => From cae21dc41271773f82c212faa8891b5951f6ac6f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 00:34:03 +0100 Subject: [PATCH 321/417] catalog-backend-module-github: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../alpha-api-report.md | 14 ++++++++++++ .../api-report.md | 4 ---- .../package.json | 22 ++++++++++++++----- .../src/alpha.ts | 17 ++++++++++++++ .../src/index.ts | 1 - 5 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 plugins/catalog-backend-module-github/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-github/src/alpha.ts diff --git a/plugins/catalog-backend-module-github/alpha-api-report.md b/plugins/catalog-backend-module-github/alpha-api-report.md new file mode 100644 index 0000000000..8522344433 --- /dev/null +++ b/plugins/catalog-backend-module-github/alpha-api-report.md @@ -0,0 +1,14 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-github" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-catalog-backend-module-github" does not have an export "GithubEntityProvider" +// +// @alpha +export const githubEntityProviderCatalogModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-github/api-report.md b/plugins/catalog-backend-module-github/api-report.md index a66ec712c7..e2b73d267b 100644 --- a/plugins/catalog-backend-module-github/api-report.md +++ b/plugins/catalog-backend-module-github/api-report.md @@ -4,7 +4,6 @@ ```ts import { AnalyzeOptions } from '@backstage/plugin-catalog-backend'; -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; @@ -100,9 +99,6 @@ export class GithubEntityProvider implements EntityProvider, EventSubscriber { supportsEventTopics(): string[]; } -// @alpha -export const githubEntityProviderCatalogModule: () => BackendFeature; - // @public (undocumented) export class GithubLocationAnalyzer implements ScmLocationAnalyzer { constructor(options: GithubLocationAnalyzerOptions); diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 5d8c5f3659..6ef4fea0c7 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -24,7 +35,7 @@ "backstage" ], "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -64,7 +75,6 @@ }, "files": [ "dist", - "alpha", "config.d.ts" ], "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-github/src/alpha.ts b/plugins/catalog-backend-module-github/src/alpha.ts new file mode 100644 index 0000000000..1b83eead82 --- /dev/null +++ b/plugins/catalog-backend-module-github/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { githubEntityProviderCatalogModule } from './service/GithubEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-github/src/index.ts b/plugins/catalog-backend-module-github/src/index.ts index b005780758..17c769419f 100644 --- a/plugins/catalog-backend-module-github/src/index.ts +++ b/plugins/catalog-backend-module-github/src/index.ts @@ -28,7 +28,6 @@ export { GithubOrgReaderProcessor } from './processors/GithubOrgReaderProcessor' export { GithubEntityProvider } from './providers/GithubEntityProvider'; export { GithubOrgEntityProvider } from './providers/GithubOrgEntityProvider'; export type { GithubOrgEntityProviderOptions } from './providers/GithubOrgEntityProvider'; -export { githubEntityProviderCatalogModule } from './service/GithubEntityProviderCatalogModule'; export { type GithubMultiOrgConfig, type GithubTeam, From c09421fed85e0ad7d9e635a68f465c9c74042cf8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 00:34:26 +0100 Subject: [PATCH 322/417] cli: make migrate package-exports remove legacy publishConfig fields Signed-off-by: Patrik Oldsberg --- .../src/commands/migrate/packageExports.ts | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/cli/src/commands/migrate/packageExports.ts b/packages/cli/src/commands/migrate/packageExports.ts index 3a59c02375..754a25e32b 100644 --- a/packages/cli/src/commands/migrate/packageExports.ts +++ b/packages/cli/src/commands/migrate/packageExports.ts @@ -16,7 +16,7 @@ import fs from 'fs-extra'; import { resolve as resolvePath } from 'path'; -import { PackageGraph } from '../../lib/monorepo'; +import { ExtendedPackageJSON, PackageGraph } from '../../lib/monorepo'; function trimRelative(path: string): string { if (path.startsWith('./')) { @@ -35,10 +35,12 @@ export async function command() { return; } + let changed = false; + let newPackageJson = packageJson; + const existingTypesVersions = JSON.stringify(packageJson.typesVersions); const typeEntries: Record = {}; - for (const [path, value] of Object.entries(exp)) { const newPath = path === '.' ? '*' : trimRelative(path); @@ -58,10 +60,9 @@ export async function command() { } const typesVersions = { '*': typeEntries }; - if (existingTypesVersions !== JSON.stringify(typesVersions)) { console.log(`Synchronizing exports in ${packageJson.name}`); - const newPkgEntries = Object.entries(packageJson).filter( + const newPkgEntries = Object.entries(newPackageJson).filter( ([name]) => name !== 'typesVersions', ); newPkgEntries.splice( @@ -70,13 +71,29 @@ export async function command() { ['typesVersions', typesVersions], ); - await fs.writeJson( - resolvePath(dir, 'package.json'), - Object.fromEntries(newPkgEntries), - { - spaces: 2, - }, - ); + newPackageJson = Object.fromEntries( + newPkgEntries, + ) as ExtendedPackageJSON; + changed = true; + } + + // Remove the legacy fields from publishConfig, which are no longer needed + const publishConfig = newPackageJson.publishConfig as + | Record + | undefined; + if (publishConfig) { + for (const field of ['main', 'module', 'browser', 'types']) { + if (publishConfig[field]) { + delete publishConfig[field]; + changed = true; + } + } + } + + if (changed) { + await fs.writeJson(resolvePath(dir, 'package.json'), newPackageJson, { + spaces: 2, + }); } }), ); From 6b9eefae6b98d7c471390262f8848883580df247 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 00:37:38 +0100 Subject: [PATCH 323/417] backend-common: migrate to use exports Signed-off-by: Patrik Oldsberg --- packages/backend-common/alpha-api-report.md | 32 +++++++++++++++++++++ packages/backend-common/api-report.md | 24 ---------------- packages/backend-common/package.json | 21 ++++++++++---- packages/backend-common/src/alpha.ts | 17 +++++++++++ packages/backend-common/src/index.ts | 1 - 5 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 packages/backend-common/alpha-api-report.md create mode 100644 packages/backend-common/src/alpha.ts diff --git a/packages/backend-common/alpha-api-report.md b/packages/backend-common/alpha-api-report.md new file mode 100644 index 0000000000..9d60b68b6b --- /dev/null +++ b/packages/backend-common/alpha-api-report.md @@ -0,0 +1,32 @@ +## API Report File for "@backstage/backend-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Duration } from 'luxon'; + +// @alpha +export interface Context { + readonly abortSignal: AbortSignal; + readonly deadline: Date | undefined; + value(key: string): T | undefined; +} + +// @alpha +export class Contexts { + static root(): Context; + static withAbort( + parentCtx: Context, + source: AbortController | AbortSignal, + ): Context; + static withTimeoutDuration(parentCtx: Context, timeout: Duration): Context; + static withTimeoutMillis(parentCtx: Context, timeout: number): Context; + static withValue( + parentCtx: Context, + key: string, + value: unknown | ((previous: unknown | undefined) => unknown), + ): Context; +} + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index d21ef30a0b..1cde27877b 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -20,7 +20,6 @@ import { Config } from '@backstage/config'; import { ConfigService } from '@backstage/backend-plugin-api'; import cors from 'cors'; import Docker from 'dockerode'; -import { Duration } from 'luxon'; import { ErrorRequestHandler } from 'express'; import express from 'express'; import { GerritIntegration } from '@backstage/integration'; @@ -211,29 +210,6 @@ export interface ContainerRunner { runContainer(opts: RunContainerOptions): Promise; } -// @alpha -export interface Context { - readonly abortSignal: AbortSignal; - readonly deadline: Date | undefined; - value(key: string): T | undefined; -} - -// @alpha -export class Contexts { - static root(): Context; - static withAbort( - parentCtx: Context, - source: AbortController | AbortSignal, - ): Context; - static withTimeoutDuration(parentCtx: Context, timeout: Duration): Context; - static withTimeoutMillis(parentCtx: Context, timeout: number): Context; - static withValue( - parentCtx: Context, - key: string, - value: unknown | ((previous: unknown | undefined) => unknown), - ): Context; -} - // @public export function createDatabaseClient( dbConfig: Config, diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index d356d67fab..e778e6830c 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -5,10 +5,21 @@ "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "node-library" @@ -24,7 +35,7 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/packages/backend-common/src/alpha.ts b/packages/backend-common/src/alpha.ts new file mode 100644 index 0000000000..e0a5b2ddc2 --- /dev/null +++ b/packages/backend-common/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './context'; diff --git a/packages/backend-common/src/index.ts b/packages/backend-common/src/index.ts index 46639a1923..afb12115b2 100644 --- a/packages/backend-common/src/index.ts +++ b/packages/backend-common/src/index.ts @@ -24,7 +24,6 @@ export { legacyPlugin, makeLegacyPlugin } from './legacy'; export type { LegacyCreateRouter } from './legacy'; export * from './cache'; export { loadBackendConfig } from './config'; -export * from './context'; export * from './database'; export * from './discovery'; export * from './hot'; From 817a5cde69cae5c054907465f6fefe538f407f03 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 00:44:50 +0100 Subject: [PATCH 324/417] sonarcube-react: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/sonarqube-react/alpha-api-report.md | 65 +++++++++++++++++++++ plugins/sonarqube-react/package.json | 17 ++++-- 2 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 plugins/sonarqube-react/alpha-api-report.md diff --git a/plugins/sonarqube-react/alpha-api-report.md b/plugins/sonarqube-react/alpha-api-report.md new file mode 100644 index 0000000000..4fad469d12 --- /dev/null +++ b/plugins/sonarqube-react/alpha-api-report.md @@ -0,0 +1,65 @@ +## API Report File for "@backstage/plugin-sonarqube-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ApiRef } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; + +// @public (undocumented) +export interface FindingSummary { + // (undocumented) + getComponentMeasuresUrl: SonarUrlProcessorFunc; + // (undocumented) + getIssuesUrl: SonarUrlProcessorFunc; + // (undocumented) + getSecurityHotspotsUrl: () => string; + // (undocumented) + lastAnalysis: string; + // (undocumented) + metrics: Metrics; + // (undocumented) + projectUrl: string; +} + +// @public (undocumented) +export type MetricKey = + | 'alert_status' + | 'bugs' + | 'reliability_rating' + | 'vulnerabilities' + | 'security_rating' + | 'code_smells' + | 'sqale_rating' + | 'security_hotspots_reviewed' + | 'security_review_rating' + | 'coverage' + | 'duplicated_lines_density'; + +// @public +export type Metrics = { + [key in MetricKey]: string | undefined; +}; + +// @public (undocumented) +export type SonarQubeApi = { + getFindingSummary(options: { + componentKey?: string; + projectInstance?: string; + }): Promise; +}; + +// @public (undocumented) +export const sonarQubeApiRef: ApiRef; + +// @public (undocumented) +export type SonarUrlProcessorFunc = (identifier: string) => string; + +// @public +export const useProjectInfo: (entity: Entity) => { + projectInstance: string | undefined; + projectKey: string | undefined; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 9006d77e84..f473d52f16 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -5,10 +5,17 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ] + } }, "backstage": { "role": "web-library" @@ -23,7 +30,7 @@ "backstage" ], "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", From 2113984b961f40235ac7a0162c497959d2e56fea Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 00:46:59 +0100 Subject: [PATCH 325/417] scaffolder-react: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/scaffolder-react/alpha-api-report.md | 225 ++++++++++++++++++ plugins/scaffolder-react/api-report.md | 204 +--------------- plugins/scaffolder-react/package.json | 24 +- plugins/scaffolder-react/src/alpha.ts | 18 ++ plugins/scaffolder-react/src/index.ts | 2 - .../src/next/components/Stepper/Stepper.tsx | 4 +- .../src/next/extensions/index.tsx | 3 +- .../src/next/extensions/types.ts | 2 +- .../next/hooks/useTemplateParameterSchema.ts | 7 +- .../src/next/hooks/useTemplateSchema.test.tsx | 2 +- .../src/next/hooks/useTemplateSchema.ts | 2 +- .../next/hooks/useTransformSchemaToProps.ts | 2 +- plugins/scaffolder-react/src/next/types.ts | 2 +- 13 files changed, 275 insertions(+), 222 deletions(-) create mode 100644 plugins/scaffolder-react/alpha-api-report.md create mode 100644 plugins/scaffolder-react/src/alpha.ts diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md new file mode 100644 index 0000000000..75d2e4fd79 --- /dev/null +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -0,0 +1,225 @@ +## API Report File for "@backstage/plugin-scaffolder-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ApiHolder } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; +import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; +import { Dispatch } from 'react'; +import { Extension } from '@backstage/core-plugin-api'; +import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; +import { FieldProps } from '@rjsf/utils'; +import { FieldValidation } from '@rjsf/utils'; +import { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { IconComponent } from '@backstage/core-plugin-api'; +import { JsonObject } from '@backstage/types'; +import { JsonValue } from '@backstage/types'; +import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { PropsWithChildren } from 'react'; +import { default as React_2 } from 'react'; +import { ReactNode } from 'react'; +import { RJSFSchema } from '@rjsf/utils'; +import { SetStateAction } from 'react'; +import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; +import { UIOptionsType } from '@rjsf/utils'; +import { UiSchema } from '@rjsf/utils'; + +// @alpha +export const createFieldValidation: () => FieldValidation; + +// @alpha +export function createNextScaffolderFieldExtension< + TReturnValue = unknown, + TInputProps extends UIOptionsType = {}, +>( + options: NextFieldExtensionOptions, +): Extension>; + +// @alpha +export const DefaultTemplateOutputs: (props: { + output?: ScaffolderTaskOutput; +}) => JSX.Element | null; + +// @alpha (undocumented) +export const EmbeddableWorkflow: (props: WorkflowProps) => JSX.Element; + +// @alpha +export const extractSchemaFromStep: (inputStep: JsonObject) => { + uiSchema: UiSchema; + schema: JsonObject; +}; + +// @alpha (undocumented) +export const Form: ComponentType>; + +// @alpha +export type FormProps = Pick< + FormProps_2, + 'transformErrors' | 'noHtml5Validate' +>; + +// @alpha +export type NextCustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidation, + context: { + apiHolder: ApiHolder; + formData: JsonObject; + schema: JsonObject; + }, +) => void | Promise; + +// @alpha +export interface NextFieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> extends PropsWithChildren> { + // (undocumented) + uiSchema?: UiSchema & { + 'ui:options'?: TUiOptions & UIOptionsType; + }; +} + +// @alpha +export type NextFieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: NextFieldExtensionComponentProps, + ) => JSX.Element | null; + validation?: NextCustomFieldValidator; + schema?: CustomFieldExtensionSchema; +}; + +// @alpha +export interface ParsedTemplateSchema { + // (undocumented) + description?: string; + // (undocumented) + mergedSchema: JsonObject; + // (undocumented) + schema: JsonObject; + // (undocumented) + title: string; + // (undocumented) + uiSchema: UiSchema; +} + +// @alpha +export const ReviewState: (props: ReviewStateProps) => JSX.Element; + +// @alpha +export type ReviewStateProps = { + schemas: ParsedTemplateSchema[]; + formState: JsonObject; +}; + +// @alpha +export const Stepper: (stepperProps: StepperProps) => JSX.Element; + +// @alpha +export type StepperProps = { + manifest: TemplateParameterSchema; + extensions: NextFieldExtensionOptions[]; + templateName?: string; + FormProps?: FormProps; + initialState?: Record; + onCreate: (values: Record) => Promise; + components?: { + ReviewStateComponent?: (props: ReviewStateProps) => JSX.Element; + createButtonText?: ReactNode; + reviewButtonText?: ReactNode; + }; + layouts?: LayoutOptions[]; +}; + +// @alpha +export const TemplateCard: (props: TemplateCardProps) => JSX.Element; + +// @alpha +export interface TemplateCardProps { + // (undocumented) + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + // (undocumented) + onSelected?: (template: TemplateEntityV1beta3) => void; + // (undocumented) + template: TemplateEntityV1beta3; +} + +// @alpha +export const TemplateGroup: (props: TemplateGroupProps) => JSX.Element; + +// @alpha +export interface TemplateGroupProps { + // (undocumented) + components?: { + CardComponent?: React_2.ComponentType; + }; + // (undocumented) + onSelected: (template: TemplateEntityV1beta3) => void; + // (undocumented) + templates: { + template: TemplateEntityV1beta3; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + }[]; + // (undocumented) + title: React_2.ReactNode; +} + +// @alpha +export const useFormDataFromQuery: ( + initialState?: Record, +) => [Record, Dispatch>>]; + +// @alpha (undocumented) +export const useTemplateParameterSchema: (templateRef: string) => { + manifest: TemplateParameterSchema; + loading: boolean; + error: Error | undefined; +}; + +// @alpha +export const useTemplateSchema: (manifest: TemplateParameterSchema) => { + steps: ParsedTemplateSchema[]; +}; + +// @alpha (undocumented) +export const Workflow: (workflowProps: WorkflowProps) => JSX.Element | null; + +// @alpha (undocumented) +export type WorkflowProps = { + title?: string; + description?: string; + namespace: string; + templateName: string; + onError(error: Error | undefined): JSX.Element | null; +} & Pick< + StepperProps, + | 'extensions' + | 'FormProps' + | 'components' + | 'onCreate' + | 'initialState' + | 'layouts' +>; + +// Warnings were encountered during analysis: +// +// src/next/components/TemplateOutputs/DefaultTemplateOutputs.d.ts:9:5 - (ae-forgotten-export) The symbol "ScaffolderTaskOutput" needs to be exported by the entry point alpha.d.ts + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 69bffbf724..9b50eef884 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -7,29 +7,18 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; -import { ComponentType } from 'react'; -import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; import { FieldProps } from '@rjsf/core'; -import { FieldProps as FieldProps_2 } from '@rjsf/utils'; import { FieldValidation } from '@rjsf/core'; -import { FieldValidation as FieldValidation_2 } from '@rjsf/utils'; -import { FormProps as FormProps_2 } from '@rjsf/core-v5'; -import { IconComponent } from '@backstage/core-plugin-api'; +import type { FormProps } from '@rjsf/core-v5'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { Observable } from '@backstage/types'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; -import { ReactNode } from 'react'; -import { RJSFSchema } from '@rjsf/utils'; -import { SetStateAction } from 'react'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; -import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { UIOptionsType } from '@rjsf/utils'; -import { UiSchema } from '@rjsf/utils'; // @public export type Action = { @@ -48,17 +37,6 @@ export type ActionExample = { example: string; }; -// @alpha -export const createFieldValidation: () => FieldValidation_2; - -// @alpha -export function createNextScaffolderFieldExtension< - TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, ->( - options: NextFieldExtensionOptions, -): Extension>; - // @public export function createScaffolderFieldExtension< TReturnValue = unknown, @@ -87,20 +65,6 @@ export type CustomFieldValidator = ( }, ) => void | Promise; -// @alpha -export const DefaultTemplateOutputs: (props: { - output?: ScaffolderTaskOutput; -}) => JSX.Element | null; - -// @alpha (undocumented) -export const EmbeddableWorkflow: (props: WorkflowProps) => JSX.Element; - -// @alpha -export const extractSchemaFromStep: (inputStep: JsonObject) => { - uiSchema: UiSchema; - schema: JsonObject; -}; - // @public export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; @@ -128,15 +92,6 @@ export type FieldExtensionOptions< schema?: CustomFieldExtensionSchema; }; -// @alpha (undocumented) -export const Form: ComponentType>; - -// @public -export type FormProps = Pick< - FormProps_2, - 'transformErrors' | 'noHtml5Validate' ->; - // @public export type LayoutComponent<_TInputProps> = () => null; @@ -150,7 +105,7 @@ export interface LayoutOptions

    { // @public export type LayoutTemplate = NonNullable< - FormProps_2['uiSchema'] + FormProps['uiSchema'] >['ui:ObjectFieldTemplate']; // @public @@ -169,64 +124,6 @@ export type LogEvent = { taskId: string; }; -// @alpha -export type NextCustomFieldValidator = ( - data: TFieldReturnValue, - field: FieldValidation_2, - context: { - apiHolder: ApiHolder; - formData: JsonObject; - schema: JsonObject; - }, -) => void | Promise; - -// @alpha -export interface NextFieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren> { - // (undocumented) - uiSchema?: UiSchema & { - 'ui:options'?: TUiOptions & UIOptionsType; - }; -} - -// @alpha -export type NextFieldExtensionOptions< - TFieldReturnValue = unknown, - TInputProps = unknown, -> = { - name: string; - component: ( - props: NextFieldExtensionComponentProps, - ) => JSX.Element | null; - validation?: NextCustomFieldValidator; - schema?: CustomFieldExtensionSchema; -}; - -// @alpha -export interface ParsedTemplateSchema { - // (undocumented) - description?: string; - // (undocumented) - mergedSchema: JsonObject; - // (undocumented) - schema: JsonObject; - // (undocumented) - title: string; - // (undocumented) - uiSchema: UiSchema; -} - -// @alpha -export const ReviewState: (props: ReviewStateProps) => JSX.Element; - -// @alpha -export type ReviewStateProps = { - schemas: ParsedTemplateSchema[]; - formState: JsonObject; -}; - // @public export interface ScaffolderApi { // (undocumented) @@ -380,66 +277,6 @@ export const SecretsContextProvider: ({ children, }: PropsWithChildren<{}>) => JSX.Element; -// @alpha -export const Stepper: (stepperProps: StepperProps) => JSX.Element; - -// @alpha -export type StepperProps = { - manifest: TemplateParameterSchema; - extensions: NextFieldExtensionOptions[]; - templateName?: string; - FormProps?: FormProps; - initialState?: Record; - onCreate: (values: Record) => Promise; - components?: { - ReviewStateComponent?: (props: ReviewStateProps) => JSX.Element; - createButtonText?: ReactNode; - reviewButtonText?: ReactNode; - }; - layouts?: LayoutOptions[]; -}; - -// @alpha -export const TemplateCard: (props: TemplateCardProps) => JSX.Element; - -// @alpha -export interface TemplateCardProps { - // (undocumented) - additionalLinks?: { - icon: IconComponent; - text: string; - url: string; - }[]; - // (undocumented) - onSelected?: (template: TemplateEntityV1beta3) => void; - // (undocumented) - template: TemplateEntityV1beta3; -} - -// @alpha -export const TemplateGroup: (props: TemplateGroupProps) => JSX.Element; - -// @alpha -export interface TemplateGroupProps { - // (undocumented) - components?: { - CardComponent?: React_2.ComponentType; - }; - // (undocumented) - onSelected: (template: TemplateEntityV1beta3) => void; - // (undocumented) - templates: { - template: TemplateEntityV1beta3; - additionalLinks?: { - icon: IconComponent; - text: string; - url: string; - }[]; - }[]; - // (undocumented) - title: React_2.ReactNode; -} - // @public export type TemplateParameterSchema = { title: string; @@ -463,45 +300,8 @@ export const useCustomLayouts: >( outlet: React.ReactNode, ) => TComponentDataType[]; -// @alpha -export const useFormDataFromQuery: ( - initialState?: Record, -) => [Record, Dispatch>>]; - -// @alpha (undocumented) -export const useTemplateParameterSchema: (templateRef: string) => { - manifest: TemplateParameterSchema | undefined; - loading: boolean; - error: Error | undefined; -}; - -// @alpha -export const useTemplateSchema: (manifest: TemplateParameterSchema) => { - steps: ParsedTemplateSchema[]; -}; - // @public export const useTemplateSecrets: () => ScaffolderUseTemplateSecrets; -// @alpha (undocumented) -export const Workflow: (workflowProps: WorkflowProps) => JSX.Element | null; - -// @alpha (undocumented) -export type WorkflowProps = { - title?: string; - description?: string; - namespace: string; - templateName: string; - onError(error: Error | undefined): JSX.Element | null; -} & Pick< - StepperProps, - | 'extensions' - | 'FormProps' - | 'components' - | 'onCreate' - | 'initialState' - | 'layouts' ->; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 043c9d5ee2..4a4d94debf 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "web-library" @@ -24,7 +35,7 @@ "backstage" ], "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -80,7 +91,6 @@ "@testing-library/user-event": "^14.0.0" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/plugins/scaffolder-react/src/alpha.ts b/plugins/scaffolder-react/src/alpha.ts new file mode 100644 index 0000000000..731b8e07d9 --- /dev/null +++ b/plugins/scaffolder-react/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 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 './next'; +export type { FormProps } from './next'; diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index 67703e3ed1..1b20c19414 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -20,5 +20,3 @@ export * from './secrets'; export * from './api'; export * from './hooks'; export * from './layouts'; - -export * from './next'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index bb2844fd52..444e463064 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -26,7 +26,7 @@ import { type IChangeEvent } from '@rjsf/core-v5'; import { ErrorSchema } from '@rjsf/utils'; import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; import { NextFieldExtensionOptions } from '../../extensions'; -import { TemplateParameterSchema } from '../../../types'; +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; import { createAsyncValidators, type FormValidation, @@ -36,7 +36,7 @@ import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import validator from '@rjsf/validator-ajv8'; import { useFormDataFromQuery } from '../../hooks'; import { FormProps } from '../../types'; -import { LayoutOptions } from '../../../layouts'; +import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; import { hasErrors } from './utils'; import * as FieldOverrides from './FieldOverrides'; diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/next/extensions/index.tsx index ee9b1cd326..b2d402c93f 100644 --- a/plugins/scaffolder-react/src/next/extensions/index.tsx +++ b/plugins/scaffolder-react/src/next/extensions/index.tsx @@ -21,7 +21,8 @@ import { } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { UIOptionsType } from '@rjsf/utils'; -import { FieldExtensionComponent } from '../../extensions'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; import { FIELD_EXTENSION_KEY } from '../../extensions/keys'; /** diff --git a/plugins/scaffolder-react/src/next/extensions/types.ts b/plugins/scaffolder-react/src/next/extensions/types.ts index 1e4c671511..0917efe85d 100644 --- a/plugins/scaffolder-react/src/next/extensions/types.ts +++ b/plugins/scaffolder-react/src/next/extensions/types.ts @@ -22,7 +22,7 @@ import { } from '@rjsf/utils'; import { PropsWithChildren } from 'react'; import { JsonObject } from '@backstage/types'; -import { CustomFieldExtensionSchema } from '../../extensions'; +import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; /** * Type for Field Extension Props for RJSF v5 diff --git a/plugins/scaffolder-react/src/next/hooks/useTemplateParameterSchema.ts b/plugins/scaffolder-react/src/next/hooks/useTemplateParameterSchema.ts index 36b8b1e0bc..d060b9a09f 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTemplateParameterSchema.ts +++ b/plugins/scaffolder-react/src/next/hooks/useTemplateParameterSchema.ts @@ -1,5 +1,3 @@ -import { useApi } from '@backstage/core-plugin-api'; - /* * Copyright 2023 The Backstage Authors * @@ -15,8 +13,11 @@ import { useApi } from '@backstage/core-plugin-api'; * See the License for the specific language governing permissions and * limitations under the License. */ + import useAsync from 'react-use/lib/useAsync'; import { scaffolderApiRef } from '../../api/ref'; +import { useApi } from '@backstage/core-plugin-api'; +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; /** * @alpha @@ -28,5 +29,5 @@ export const useTemplateParameterSchema = (templateRef: string) => { [scaffolderApi, templateRef], ); - return { manifest: value, loading, error }; + return { manifest: value as TemplateParameterSchema, loading, error }; }; diff --git a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx index 153c48468d..ab33652338 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx +++ b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx @@ -18,7 +18,7 @@ import { renderHook } from '@testing-library/react-hooks'; import { TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { featureFlagsApiRef } from '@backstage/core-plugin-api'; -import { TemplateParameterSchema } from '../../types'; +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; describe('useTemplateSchema', () => { it('should generate the correct schema', () => { diff --git a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts index 2b2e48cf68..26980b15cf 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts +++ b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts @@ -16,7 +16,7 @@ import { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { UiSchema } from '@rjsf/utils'; -import { TemplateParameterSchema } from '../../types'; +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; import { extractSchemaFromStep } from '../lib'; /** diff --git a/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.ts b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.ts index 881c4f90c5..612ad5427b 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.ts +++ b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { type ParsedTemplateSchema } from './useTemplateSchema'; -import { type LayoutOptions } from '../../layouts'; +import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; interface Options { layouts?: LayoutOptions[]; diff --git a/plugins/scaffolder-react/src/next/types.ts b/plugins/scaffolder-react/src/next/types.ts index 54a64a5323..192fdf4146 100644 --- a/plugins/scaffolder-react/src/next/types.ts +++ b/plugins/scaffolder-react/src/next/types.ts @@ -23,7 +23,7 @@ import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; /** * Any `@rjsf/core` form properties that are publicly exposed to the `NextScaffolderpage` * - * @public + * @alpha */ export type FormProps = Pick< SchemaFormProps, From 8fc53d440f2abbb40ee3338d7a0f190e5d67aeee Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 00:51:27 +0100 Subject: [PATCH 326/417] scaffolder-backend: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../scaffolder-backend/alpha-api-report.md | 30 +++++++++++++++++++ plugins/scaffolder-backend/api-report.md | 18 ----------- plugins/scaffolder-backend/package.json | 22 ++++++++++---- .../src/ScaffolderPlugin.ts | 8 +++-- plugins/scaffolder-backend/src/alpha.ts | 19 ++++++++++++ plugins/scaffolder-backend/src/index.ts | 3 -- 6 files changed, 71 insertions(+), 29 deletions(-) create mode 100644 plugins/scaffolder-backend/alpha-api-report.md create mode 100644 plugins/scaffolder-backend/src/alpha.ts diff --git a/plugins/scaffolder-backend/alpha-api-report.md b/plugins/scaffolder-backend/alpha-api-report.md new file mode 100644 index 0000000000..3199444c6b --- /dev/null +++ b/plugins/scaffolder-backend/alpha-api-report.md @@ -0,0 +1,30 @@ +## API Report File for "@backstage/plugin-scaffolder-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { TaskBroker } from '@backstage/plugin-scaffolder-backend'; +import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { TemplateFilter } from '@backstage/plugin-scaffolder-backend'; +import { TemplateGlobal } from '@backstage/plugin-scaffolder-backend'; + +// @alpha +export const catalogModuleTemplateKind: () => BackendFeature; + +// @alpha +export const scaffolderPlugin: ( + options: ScaffolderPluginOptions, +) => BackendFeature; + +// @alpha +export type ScaffolderPluginOptions = { + actions?: TemplateAction[]; + taskWorkers?: number; + taskBroker?: TaskBroker; + additionalTemplateFilters?: Record; + additionalTemplateGlobals?: Record; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 0d745862a1..293ff7ed29 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -6,7 +6,6 @@ /// import { ActionContext as ActionContext_2 } from '@backstage/plugin-scaffolder-node'; -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; @@ -38,9 +37,6 @@ import { Writable } from 'stream'; // @public @deprecated (undocumented) export type ActionContext = ActionContext_2; -// @alpha -export const catalogModuleTemplateKind: () => BackendFeature; - // @public export const createBuiltinActions: ( options: CreateBuiltInActionsOptions, @@ -666,20 +662,6 @@ export class ScaffolderEntitiesProcessor implements CatalogProcessor { validateEntityKind(entity: Entity): Promise; } -// @alpha -export const scaffolderPlugin: ( - options: ScaffolderPluginOptions, -) => BackendFeature; - -// @alpha -export type ScaffolderPluginOptions = { - actions?: TemplateAction_2[]; - taskWorkers?: number; - taskBroker?: TaskBroker; - additionalTemplateFilters?: Record; - additionalTemplateGlobals?: Record; -}; - // @public export type SerializedTask = { id: string; diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index e9c21deeb2..3eda8bd678 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -100,7 +111,6 @@ "yaml": "^2.0.0" }, "files": [ - "alpha", "dist", "migrations", "config.d.ts", diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 3b0d26be21..852c0f73e2 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -26,8 +26,12 @@ import { ScaffolderActionsExtensionPoint, TemplateAction, } from '@backstage/plugin-scaffolder-node'; -import { TemplateFilter, TemplateGlobal } from './lib'; -import { createBuiltinActions, TaskBroker } from './scaffolder'; +import { + TemplateFilter, + TemplateGlobal, + TaskBroker, +} from '@backstage/plugin-scaffolder-backend'; +import { createBuiltinActions } from './scaffolder'; import { createRouter } from './service/router'; /** diff --git a/plugins/scaffolder-backend/src/alpha.ts b/plugins/scaffolder-backend/src/alpha.ts new file mode 100644 index 0000000000..ac96f081ad --- /dev/null +++ b/plugins/scaffolder-backend/src/alpha.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './modules'; +export { scaffolderPlugin } from './ScaffolderPlugin'; +export type { ScaffolderPluginOptions } from './ScaffolderPlugin'; diff --git a/plugins/scaffolder-backend/src/index.ts b/plugins/scaffolder-backend/src/index.ts index ba69a55a24..ba2c25f80a 100644 --- a/plugins/scaffolder-backend/src/index.ts +++ b/plugins/scaffolder-backend/src/index.ts @@ -24,8 +24,5 @@ export * from './scaffolder'; export * from './service/router'; export * from './lib'; export * from './processor'; -export * from './modules'; -export { scaffolderPlugin } from './ScaffolderPlugin'; -export type { ScaffolderPluginOptions } from './ScaffolderPlugin'; export * from './deprecated'; From 7543832df1bbf8f02f42b7d482f932b42c318d86 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 01:01:48 +0100 Subject: [PATCH 327/417] scaffolder: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/scaffolder/alpha-api-report.md | 70 +++++++++++++++++++ plugins/scaffolder/api-report.md | 65 ++--------------- plugins/scaffolder/package.json | 24 +++++-- plugins/scaffolder/src/alpha.ts | 25 +++++++ .../MultistepJsonForm/MultistepJsonForm.tsx | 6 +- plugins/scaffolder/src/index.ts | 11 --- .../src/next/OngoingTask/OngoingTask.tsx | 6 +- plugins/scaffolder/src/next/Router/Router.tsx | 4 +- .../CustomFieldExplorer.tsx | 2 +- .../TemplateEditorPage/TemplateEditor.tsx | 6 +- .../TemplateEditorPage/TemplateEditorForm.tsx | 6 +- .../TemplateEditorPage/TemplateEditorPage.tsx | 6 +- .../TemplateFormPreviewer.tsx | 6 +- .../TemplateListPage/TemplateGroups.test.tsx | 2 +- .../next/TemplateListPage/TemplateGroups.tsx | 2 +- .../TemplateWizardPage/TemplateWizardPage.tsx | 6 +- 16 files changed, 141 insertions(+), 106 deletions(-) create mode 100644 plugins/scaffolder/alpha-api-report.md create mode 100644 plugins/scaffolder/src/alpha.ts diff --git a/plugins/scaffolder/alpha-api-report.md b/plugins/scaffolder/alpha-api-report.md new file mode 100644 index 0000000000..bf37acafc3 --- /dev/null +++ b/plugins/scaffolder/alpha-api-report.md @@ -0,0 +1,70 @@ +## API Report File for "@backstage/plugin-scaffolder" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { Entity } from '@backstage/catalog-model'; +import { FormProps as FormProps_2 } from '@backstage/plugin-scaffolder-react/alpha'; +import type { FormProps as FormProps_3 } from '@rjsf/core-v5'; +import { PathParams } from '@backstage/core-plugin-api'; +import { PropsWithChildren } from 'react'; +import { default as React_2 } from 'react'; +import { RouteRef } from '@backstage/core-plugin-api'; +import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; +import { SubRouteRef } from '@backstage/core-plugin-api'; +import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; + +// @alpha @deprecated +export type FormProps = Pick< + FormProps_3, + 'transformErrors' | 'noHtml5Validate' +>; + +// @alpha (undocumented) +export const nextRouteRef: RouteRef; + +// @alpha +export type NextRouterProps = { + components?: { + TemplateCardComponent?: React_2.ComponentType<{ + template: TemplateEntityV1beta3; + }>; + TaskPageComponent?: React_2.ComponentType<{}>; + TemplateOutputsComponent?: React_2.ComponentType<{ + output?: ScaffolderTaskOutput; + }>; + }; + groups?: TemplateGroupFilter[]; + FormProps?: FormProps_2; + contextMenu?: { + editor?: boolean; + actions?: boolean; + tasks?: boolean; + }; +}; + +// @alpha +export const NextScaffolderPage: ( + props: PropsWithChildren, +) => JSX.Element; + +// @alpha (undocumented) +export const nextScaffolderTaskRouteRef: SubRouteRef< + PathParams<'/tasks/:taskId'> +>; + +// @alpha (undocumented) +export const nextSelectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> +>; + +// @alpha (undocumented) +export type TemplateGroupFilter = { + title?: React_2.ReactNode; + filter: (entity: Entity) => boolean; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 43b885b81a..7030affeea 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -21,8 +21,6 @@ import { FieldExtensionComponent as FieldExtensionComponent_2 } from '@backstage import { FieldExtensionComponentProps as FieldExtensionComponentProps_2 } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionOptions as FieldExtensionOptions_2 } from '@backstage/plugin-scaffolder-react'; import { FieldValidation } from '@rjsf/core'; -import { FormProps as FormProps_2 } from '@backstage/plugin-scaffolder-react'; -import type { FormProps as FormProps_3 } from '@rjsf/core-v5'; import { IdentityApi } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { LayoutOptions as LayoutOptions_2 } from '@backstage/plugin-scaffolder-react'; @@ -31,7 +29,6 @@ import { ListActionsResponse as ListActionsResponse_2 } from '@backstage/plugin- import { LogEvent as LogEvent_2 } from '@backstage/plugin-scaffolder-react'; import { Observable } from '@backstage/types'; import { PathParams } from '@backstage/core-plugin-api'; -import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -112,9 +109,9 @@ export type EntityPickerUiOptions = export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< string[], { - showCounts?: boolean | undefined; - kinds?: string[] | undefined; helperText?: string | undefined; + kinds?: string[] | undefined; + showCounts?: boolean | undefined; } >; @@ -122,9 +119,9 @@ export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< export const EntityTagsPickerFieldSchema: FieldSchema< string[], { - showCounts?: boolean | undefined; - kinds?: string[] | undefined; helperText?: string | undefined; + kinds?: string[] | undefined; + showCounts?: boolean | undefined; } >; @@ -155,12 +152,6 @@ export interface FieldSchema { readonly uiOptionsType: TUiOptions; } -// @alpha @deprecated -export type FormProps = Pick< - FormProps_3, - 'transformErrors' | 'noHtml5Validate' ->; - // @public @deprecated (undocumented) export type LayoutOptions = LayoutOptions_2; @@ -187,44 +178,6 @@ export function makeFieldSchemaFromZod< : never >; -// @alpha (undocumented) -export const nextRouteRef: RouteRef; - -// @alpha -export type NextRouterProps = { - components?: { - TemplateCardComponent?: React_2.ComponentType<{ - template: TemplateEntityV1beta3; - }>; - TaskPageComponent?: React_2.ComponentType<{}>; - TemplateOutputsComponent?: React_2.ComponentType<{ - output?: ScaffolderTaskOutput_2; - }>; - }; - groups?: TemplateGroupFilter[]; - FormProps?: FormProps_2; - contextMenu?: { - editor?: boolean; - actions?: boolean; - tasks?: boolean; - }; -}; - -// @alpha -export const NextScaffolderPage: ( - props: PropsWithChildren, -) => JSX.Element; - -// @alpha (undocumented) -export const nextScaffolderTaskRouteRef: SubRouteRef< - PathParams<'/tasks/:taskId'> ->; - -// @alpha (undocumented) -export const nextSelectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> ->; - // @public export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2< string, @@ -306,8 +259,8 @@ export const RepoUrlPickerFieldExtension: FieldExtensionComponent_2< | { azure?: string[] | undefined; github?: string[] | undefined; - gitlab?: string[] | undefined; bitbucket?: string[] | undefined; + gitlab?: string[] | undefined; gerrit?: string[] | undefined; } | undefined; @@ -332,8 +285,8 @@ export const RepoUrlPickerFieldSchema: FieldSchema< | { azure?: string[] | undefined; github?: string[] | undefined; - gitlab?: string[] | undefined; bitbucket?: string[] | undefined; + gitlab?: string[] | undefined; gerrit?: string[] | undefined; } | undefined; @@ -514,12 +467,6 @@ export type TaskPageProps = { loadingText?: string; }; -// @alpha (undocumented) -export type TemplateGroupFilter = { - title?: React_2.ReactNode; - filter: (entity: Entity) => boolean; -}; - // @public @deprecated (undocumented) export type TemplateParameterSchema = TemplateParameterSchema_2; diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 5eac3c7a0d..b4fb81fb9c 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "frontend-plugin" @@ -24,7 +35,7 @@ "backstage" ], "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "start": "backstage-cli package start", "lint": "backstage-cli package lint", "test": "backstage-cli package test", @@ -99,7 +110,6 @@ "msw": "^0.49.0" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/plugins/scaffolder/src/alpha.ts b/plugins/scaffolder/src/alpha.ts new file mode 100644 index 0000000000..a460b0d7cc --- /dev/null +++ b/plugins/scaffolder/src/alpha.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { NextScaffolderPage } from './plugin'; +export { + nextRouteRef, + nextScaffolderTaskRouteRef, + nextSelectedTemplateRouteRef, + type TemplateGroupFilter, + type NextRouterProps, + type FormProps, +} from './next'; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index a74b65b885..0924c4f2e6 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -37,11 +37,9 @@ import cloneDeep from 'lodash/cloneDeep'; import * as fieldOverrides from './FieldOverrides'; import { ReviewStepProps } from '../types'; import { ReviewStep } from './ReviewStep'; -import { - extractSchemaFromStep, - type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; +import { extractSchemaFromStep } from '@backstage/plugin-scaffolder-react/alpha'; import { selectedTemplateRouteRef } from '../../routes'; +import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; const Form = withTheme(MuiTheme); diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index aa78874f9d..bc56629a2c 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -34,14 +34,3 @@ export { export * from './components'; export * from './deprecated'; - -/** next exports */ -export { NextScaffolderPage } from './plugin'; -export { - nextRouteRef, - nextScaffolderTaskRouteRef, - nextSelectedTemplateRouteRef, - type TemplateGroupFilter, - type NextRouterProps, - type FormProps, -} from './next'; diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx index a68df01ed5..d0aaf4b838 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -25,10 +25,8 @@ import { nextSelectedTemplateRouteRef } from '../routes'; import { useRouteRef } from '@backstage/core-plugin-api'; import qs from 'qs'; import { ContextMenu } from './ContextMenu'; -import { - DefaultTemplateOutputs, - ScaffolderTaskOutput, -} from '@backstage/plugin-scaffolder-react'; +import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; +import { DefaultTemplateOutputs } from '@backstage/plugin-scaffolder-react/alpha'; const useStyles = makeStyles({ contentWrapper: { diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index ded344b048..5e199cae9b 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -19,11 +19,13 @@ import { TemplateListPage } from '../TemplateListPage'; import { TemplateWizardPage } from '../TemplateWizardPage'; import { NextFieldExtensionOptions, + FormProps, +} from '@backstage/plugin-scaffolder-react/alpha'; +import { ScaffolderTaskOutput, SecretsContextProvider, useCustomFieldExtensions, useCustomLayouts, - type FormProps, } from '@backstage/plugin-scaffolder-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx index d0852a6a31..823d5b164a 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx @@ -34,7 +34,7 @@ import yaml from 'yaml'; import { NextFieldExtensionOptions, Form, -} from '@backstage/plugin-scaffolder-react'; +} from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateEditorForm } from './TemplateEditorForm'; import validator from '@rjsf/validator-ajv8'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx index 4cdd383f83..16067e8095 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx @@ -15,10 +15,8 @@ */ import { makeStyles } from '@material-ui/core'; import React, { useState } from 'react'; -import type { - LayoutOptions, - NextFieldExtensionOptions, -} from '@backstage/plugin-scaffolder-react'; +import type { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateDirectoryAccess } from '../../lib/filesystem'; import { DirectoryEditorProvider } from '../../components/TemplateEditorPage/DirectoryEditorContext'; import { DryRunProvider } from '../../components/TemplateEditorPage/DryRunContext'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx index 5dc841cf20..898487e200 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx @@ -21,10 +21,12 @@ import useDebounce from 'react-use/lib/useDebounce'; import yaml from 'yaml'; import { LayoutOptions, - NextFieldExtensionOptions, - Stepper, TemplateParameterSchema, } from '@backstage/plugin-scaffolder-react'; +import { + NextFieldExtensionOptions, + Stepper, +} from '@backstage/plugin-scaffolder-react/alpha'; import { useDryRun } from '../../components/TemplateEditorPage/DryRunContext'; import { useDirectoryEditor } from '../../components/TemplateEditorPage/DirectoryEditorContext'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx index 92387fd69d..9863e99c73 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -22,10 +22,8 @@ import { import { CustomFieldExplorer } from './CustomFieldExplorer'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; -import { - NextFieldExtensionOptions, - type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; +import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateEditorIntro } from '../../components/TemplateEditorPage/TemplateEditorIntro'; type Selection = diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx index 1476cda2d0..2aa1cc764d 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -32,10 +32,8 @@ import CloseIcon from '@material-ui/icons/Close'; import React, { useCallback, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import yaml from 'yaml'; -import { - NextFieldExtensionOptions, - type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; +import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateEditorForm } from './TemplateEditorForm'; import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx index f76c1a4ab6..19a9728f37 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx @@ -27,7 +27,7 @@ import { useEntityList } from '@backstage/plugin-catalog-react'; import { TemplateGroups } from './TemplateGroups'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; -import { TemplateGroup } from '@backstage/plugin-scaffolder-react'; +import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha'; import { nextRouteRef } from '../routes'; describe('TemplateGroups', () => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx index 485b0e40cd..590ef802bd 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx @@ -30,7 +30,7 @@ import { useApp, useRouteRef, } from '@backstage/core-plugin-api'; -import { TemplateGroup } from '@backstage/plugin-scaffolder-react'; +import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha'; import { viewTechDocRouteRef } from '../../routes'; import { nextSelectedTemplateRouteRef } from '../routes'; import { useNavigate } from 'react-router-dom'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index b71d0bd7a3..4825715fcb 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -25,13 +25,13 @@ import { import { scaffolderApiRef, useTemplateSecrets, - Workflow, type LayoutOptions, } from '@backstage/plugin-scaffolder-react'; import { - NextFieldExtensionOptions, FormProps, -} from '@backstage/plugin-scaffolder-react'; + Workflow, + NextFieldExtensionOptions, +} from '@backstage/plugin-scaffolder-react/alpha'; import { JsonValue } from '@backstage/types'; import { Header, Page } from '@backstage/core-components'; import { From 334baa32b092ffece5f6ac505a39ddb0e5ee176f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 01:04:13 +0100 Subject: [PATCH 328/417] events-node: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/events-node/alpha-api-report.md | 36 +++++++++++++++++++++++++ plugins/events-node/api-report.md | 21 --------------- plugins/events-node/package.json | 22 ++++++++++----- plugins/events-node/src/alpha.ts | 18 +++++++++++++ plugins/events-node/src/index.ts | 2 -- 5 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 plugins/events-node/alpha-api-report.md create mode 100644 plugins/events-node/src/alpha.ts diff --git a/plugins/events-node/alpha-api-report.md b/plugins/events-node/alpha-api-report.md new file mode 100644 index 0000000000..161f80ff87 --- /dev/null +++ b/plugins/events-node/alpha-api-report.md @@ -0,0 +1,36 @@ +## API Report File for "@backstage/plugin-events-node" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ExtensionPoint } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export interface EventsExtensionPoint { + // Warning: (ae-forgotten-export) The symbol "HttpPostIngressOptions" needs to be exported by the entry point alpha.d.ts + // + // (undocumented) + addHttpPostIngress(options: HttpPostIngressOptions): void; + // Warning: (ae-forgotten-export) The symbol "EventPublisher" needs to be exported by the entry point alpha.d.ts + // + // (undocumented) + addPublishers( + ...publishers: Array> + ): void; + // Warning: (ae-forgotten-export) The symbol "EventSubscriber" needs to be exported by the entry point alpha.d.ts + // + // (undocumented) + addSubscribers( + ...subscribers: Array> + ): void; + // Warning: (ae-forgotten-export) The symbol "EventBroker" needs to be exported by the entry point alpha.d.ts + // + // (undocumented) + setEventBroker(eventBroker: EventBroker): void; +} + +// @alpha (undocumented) +export const eventsExtensionPoint: ExtensionPoint; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-node/api-report.md b/plugins/events-node/api-report.md index 8428003b85..dfda48d97e 100644 --- a/plugins/events-node/api-report.md +++ b/plugins/events-node/api-report.md @@ -3,8 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { ExtensionPoint } from '@backstage/backend-plugin-api'; - // @public export interface EventBroker { publish(params: EventParams): Promise; @@ -40,25 +38,6 @@ export abstract class EventRouter implements EventPublisher, EventSubscriber { abstract supportsEventTopics(): string[]; } -// @alpha (undocumented) -export interface EventsExtensionPoint { - // (undocumented) - addHttpPostIngress(options: HttpPostIngressOptions): void; - // (undocumented) - addPublishers( - ...publishers: Array> - ): void; - // (undocumented) - addSubscribers( - ...subscribers: Array> - ): void; - // (undocumented) - setEventBroker(eventBroker: EventBroker): void; -} - -// @alpha (undocumented) -export const eventsExtensionPoint: ExtensionPoint; - // @public export interface EventSubscriber { onEvent(params: EventParams): Promise; diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 9dffabcaac..060e450289 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -6,17 +6,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "node-library" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -30,7 +41,6 @@ "@backstage/cli": "workspace:^" }, "files": [ - "alpha", "dist" ] } diff --git a/plugins/events-node/src/alpha.ts b/plugins/events-node/src/alpha.ts new file mode 100644 index 0000000000..90666ba2f3 --- /dev/null +++ b/plugins/events-node/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type { EventsExtensionPoint } from './extensions'; +export { eventsExtensionPoint } from './extensions'; diff --git a/plugins/events-node/src/index.ts b/plugins/events-node/src/index.ts index 422eeb169e..2bdf456f13 100644 --- a/plugins/events-node/src/index.ts +++ b/plugins/events-node/src/index.ts @@ -21,5 +21,3 @@ */ export * from './api'; -export type { EventsExtensionPoint } from './extensions'; -export { eventsExtensionPoint } from './extensions'; From ec7857e390d5643fce8595d03f969c447969f0b8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 01:07:38 +0100 Subject: [PATCH 329/417] events-backend-module-gitlab: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../alpha-api-report.md | 19 ++++++++++++++++ .../api-report.md | 7 ------ .../events-backend-module-gitlab/package.json | 22 ++++++++++++++----- .../events-backend-module-gitlab/src/alpha.ts | 18 +++++++++++++++ .../events-backend-module-gitlab/src/index.ts | 2 -- .../GitlabEventRouterEventsModule.test.ts | 2 +- .../service/GitlabEventRouterEventsModule.ts | 2 +- .../service/GitlabWebhookEventsModule.test.ts | 2 +- .../src/service/GitlabWebhookEventsModule.ts | 2 +- 9 files changed, 57 insertions(+), 19 deletions(-) create mode 100644 plugins/events-backend-module-gitlab/alpha-api-report.md create mode 100644 plugins/events-backend-module-gitlab/src/alpha.ts diff --git a/plugins/events-backend-module-gitlab/alpha-api-report.md b/plugins/events-backend-module-gitlab/alpha-api-report.md new file mode 100644 index 0000000000..d8b1430df9 --- /dev/null +++ b/plugins/events-backend-module-gitlab/alpha-api-report.md @@ -0,0 +1,19 @@ +## API Report File for "@backstage/plugin-events-backend-module-gitlab" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-gitlab" does not have an export "GitlabEventRouter" +// +// @alpha +export const gitlabEventRouterEventsModule: () => BackendFeature; + +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-gitlab" does not have an export "GitlabEventRouter" +// +// @alpha +export const gitlabWebhookEventsModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-backend-module-gitlab/api-report.md b/plugins/events-backend-module-gitlab/api-report.md index 2a88295032..8a0c513857 100644 --- a/plugins/events-backend-module-gitlab/api-report.md +++ b/plugins/events-backend-module-gitlab/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { EventParams } from '@backstage/plugin-events-node'; import { RequestValidator } from '@backstage/plugin-events-node'; @@ -18,10 +17,4 @@ export class GitlabEventRouter extends SubTopicEventRouter { // (undocumented) protected determineSubTopic(params: EventParams): string | undefined; } - -// @alpha -export const gitlabEventRouterEventsModule: () => BackendFeature; - -// @alpha -export const gitlabWebhookEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 7e195bc447..be5ffc2318 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -5,17 +5,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -35,7 +46,6 @@ "supertest": "^6.1.3" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/events-backend-module-gitlab/src/alpha.ts b/plugins/events-backend-module-gitlab/src/alpha.ts new file mode 100644 index 0000000000..357c9f81ce --- /dev/null +++ b/plugins/events-backend-module-gitlab/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { gitlabEventRouterEventsModule } from './service/GitlabEventRouterEventsModule'; +export { gitlabWebhookEventsModule } from './service/GitlabWebhookEventsModule'; diff --git a/plugins/events-backend-module-gitlab/src/index.ts b/plugins/events-backend-module-gitlab/src/index.ts index 859a6c69c0..3788e02955 100644 --- a/plugins/events-backend-module-gitlab/src/index.ts +++ b/plugins/events-backend-module-gitlab/src/index.ts @@ -23,5 +23,3 @@ export { createGitlabTokenValidator } from './http/createGitlabTokenValidator'; export { GitlabEventRouter } from './router/GitlabEventRouter'; -export { gitlabEventRouterEventsModule } from './service/GitlabEventRouterEventsModule'; -export { gitlabWebhookEventsModule } from './service/GitlabWebhookEventsModule'; diff --git a/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.test.ts b/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.test.ts index f0ffca3397..f8b03bc0f3 100644 --- a/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.test.ts +++ b/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.test.ts @@ -15,7 +15,7 @@ */ import { startTestBackend } from '@backstage/backend-test-utils'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { gitlabEventRouterEventsModule } from './GitlabEventRouterEventsModule'; import { GitlabEventRouter } from '../router/GitlabEventRouter'; diff --git a/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts b/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts index 9ab2e1263e..45b7f37711 100644 --- a/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts +++ b/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts @@ -15,7 +15,7 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { GitlabEventRouter } from '../router/GitlabEventRouter'; /** diff --git a/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.test.ts b/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.test.ts index b139f46f55..b42f2c474e 100644 --- a/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.test.ts +++ b/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.test.ts @@ -17,8 +17,8 @@ import { coreServices } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { - eventsExtensionPoint, HttpPostIngressOptions, RequestDetails, } from '@backstage/plugin-events-node'; diff --git a/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts b/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts index 44f13f31ef..2fcee40589 100644 --- a/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts +++ b/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts @@ -18,7 +18,7 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { createGitlabTokenValidator } from '../http/createGitlabTokenValidator'; /** From 27f44f4ad834ec39f37127cb54b34e760291ec1b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 01:09:29 +0100 Subject: [PATCH 330/417] events-backend-module-github: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../alpha-api-report.md | 17 ++++++++++++++ .../api-report.md | 7 ------ .../events-backend-module-github/package.json | 22 ++++++++++++++----- .../events-backend-module-github/src/alpha.ts | 18 +++++++++++++++ .../events-backend-module-github/src/index.ts | 2 -- .../GithubEventRouterEventsModule.test.ts | 2 +- .../service/GithubEventRouterEventsModule.ts | 2 +- .../service/GithubWebhookEventsModule.test.ts | 2 +- .../src/service/GithubWebhookEventsModule.ts | 2 +- 9 files changed, 55 insertions(+), 19 deletions(-) create mode 100644 plugins/events-backend-module-github/alpha-api-report.md create mode 100644 plugins/events-backend-module-github/src/alpha.ts diff --git a/plugins/events-backend-module-github/alpha-api-report.md b/plugins/events-backend-module-github/alpha-api-report.md new file mode 100644 index 0000000000..aed740ed0d --- /dev/null +++ b/plugins/events-backend-module-github/alpha-api-report.md @@ -0,0 +1,17 @@ +## API Report File for "@backstage/plugin-events-backend-module-github" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-github" does not have an export "GithubEventRouter" +// +// @alpha +export const githubEventRouterEventsModule: () => BackendFeature; + +// @alpha +export const githubWebhookEventsModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-backend-module-github/api-report.md b/plugins/events-backend-module-github/api-report.md index 4f14bce789..bcf9b8ed74 100644 --- a/plugins/events-backend-module-github/api-report.md +++ b/plugins/events-backend-module-github/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { EventParams } from '@backstage/plugin-events-node'; import { RequestValidator } from '@backstage/plugin-events-node'; @@ -20,10 +19,4 @@ export class GithubEventRouter extends SubTopicEventRouter { // (undocumented) protected determineSubTopic(params: EventParams): string | undefined; } - -// @alpha -export const githubEventRouterEventsModule: () => BackendFeature; - -// @alpha -export const githubWebhookEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 1d266ea562..3145ee9e66 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -5,17 +5,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -36,7 +47,6 @@ "supertest": "^6.1.3" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/events-backend-module-github/src/alpha.ts b/plugins/events-backend-module-github/src/alpha.ts new file mode 100644 index 0000000000..8a712cacb1 --- /dev/null +++ b/plugins/events-backend-module-github/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { githubEventRouterEventsModule } from './service/GithubEventRouterEventsModule'; +export { githubWebhookEventsModule } from './service/GithubWebhookEventsModule'; diff --git a/plugins/events-backend-module-github/src/index.ts b/plugins/events-backend-module-github/src/index.ts index 8e5671d9d8..d02ea1deaf 100644 --- a/plugins/events-backend-module-github/src/index.ts +++ b/plugins/events-backend-module-github/src/index.ts @@ -23,5 +23,3 @@ export { createGithubSignatureValidator } from './http/createGithubSignatureValidator'; export { GithubEventRouter } from './router/GithubEventRouter'; -export { githubEventRouterEventsModule } from './service/GithubEventRouterEventsModule'; -export { githubWebhookEventsModule } from './service/GithubWebhookEventsModule'; diff --git a/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.test.ts b/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.test.ts index 694f5e1dbe..0e2ca69366 100644 --- a/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.test.ts +++ b/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.test.ts @@ -15,7 +15,7 @@ */ import { startTestBackend } from '@backstage/backend-test-utils'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { githubEventRouterEventsModule } from './GithubEventRouterEventsModule'; import { GithubEventRouter } from '../router/GithubEventRouter'; diff --git a/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts b/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts index 8914d07e71..e2e6fab266 100644 --- a/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts +++ b/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts @@ -15,7 +15,7 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { GithubEventRouter } from '../router/GithubEventRouter'; /** diff --git a/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.test.ts b/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.test.ts index 84233eedee..9e33cac6a0 100644 --- a/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.test.ts +++ b/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.test.ts @@ -17,8 +17,8 @@ import { coreServices } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { - eventsExtensionPoint, HttpPostIngressOptions, RequestDetails, } from '@backstage/plugin-events-node'; diff --git a/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.ts b/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.ts index 9a3202cb97..10cb12e431 100644 --- a/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.ts +++ b/plugins/events-backend-module-github/src/service/GithubWebhookEventsModule.ts @@ -18,7 +18,7 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { createGithubSignatureValidator } from '../http/createGithubSignatureValidator'; /** From 3bc17bd3b612a7d96c41fb5b8981fd9875efa585 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 01:10:51 +0100 Subject: [PATCH 331/417] events-backend-module-gerrit: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../events-backend-module-gerrit/package.json | 22 ++++++++++++++----- .../events-backend-module-gerrit/src/alpha.ts | 17 ++++++++++++++ .../events-backend-module-gerrit/src/index.ts | 1 - .../GerritEventRouterEventsModule.test.ts | 2 +- .../service/GerritEventRouterEventsModule.ts | 2 +- 5 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 plugins/events-backend-module-gerrit/src/alpha.ts diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 85e9ac92dc..5fe093893c 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -5,17 +5,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -34,7 +45,6 @@ "supertest": "^6.1.3" }, "files": [ - "alpha", "dist" ] } diff --git a/plugins/events-backend-module-gerrit/src/alpha.ts b/plugins/events-backend-module-gerrit/src/alpha.ts new file mode 100644 index 0000000000..26fd89b14d --- /dev/null +++ b/plugins/events-backend-module-gerrit/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { gerritEventRouterEventsModule } from './service/GerritEventRouterEventsModule'; diff --git a/plugins/events-backend-module-gerrit/src/index.ts b/plugins/events-backend-module-gerrit/src/index.ts index 1a9ebb03ee..dfc314667f 100644 --- a/plugins/events-backend-module-gerrit/src/index.ts +++ b/plugins/events-backend-module-gerrit/src/index.ts @@ -22,4 +22,3 @@ */ export { GerritEventRouter } from './router/GerritEventRouter'; -export { gerritEventRouterEventsModule } from './service/GerritEventRouterEventsModule'; diff --git a/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.test.ts b/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.test.ts index b5fd6a80ca..6a8f4f46ff 100644 --- a/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.test.ts +++ b/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.test.ts @@ -15,7 +15,7 @@ */ import { startTestBackend } from '@backstage/backend-test-utils'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { gerritEventRouterEventsModule } from './GerritEventRouterEventsModule'; import { GerritEventRouter } from '../router/GerritEventRouter'; diff --git a/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts b/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts index 734b574edd..6f8889eb2b 100644 --- a/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts +++ b/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts @@ -15,7 +15,7 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { GerritEventRouter } from '../router/GerritEventRouter'; /** From 7a01af72656bdad25bfc12d3f829d8e9b2e1073f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 09:48:02 +0100 Subject: [PATCH 332/417] events-backend-module-bitbucket-cloud: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../alpha-api-report.md | 14 ++++++++++++ .../api-report.md | 4 ---- .../package.json | 22 ++++++++++++++----- .../src/alpha.ts | 17 ++++++++++++++ .../src/index.ts | 1 - ...bucketCloudEventRouterEventsModule.test.ts | 2 +- .../BitbucketCloudEventRouterEventsModule.ts | 2 +- 7 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md create mode 100644 plugins/events-backend-module-bitbucket-cloud/src/alpha.ts diff --git a/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md b/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md new file mode 100644 index 0000000000..11b60fd12d --- /dev/null +++ b/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md @@ -0,0 +1,14 @@ +## API Report File for "@backstage/plugin-events-backend-module-bitbucket-cloud" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-bitbucket-cloud" does not have an export "BitbucketCloudEventRouter" +// +// @alpha +export const bitbucketCloudEventRouterEventsModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-backend-module-bitbucket-cloud/api-report.md b/plugins/events-backend-module-bitbucket-cloud/api-report.md index c47252ce17..4795edd89a 100644 --- a/plugins/events-backend-module-bitbucket-cloud/api-report.md +++ b/plugins/events-backend-module-bitbucket-cloud/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { EventParams } from '@backstage/plugin-events-node'; import { SubTopicEventRouter } from '@backstage/plugin-events-node'; @@ -13,7 +12,4 @@ export class BitbucketCloudEventRouter extends SubTopicEventRouter { // (undocumented) protected determineSubTopic(params: EventParams): string | undefined; } - -// @alpha -export const bitbucketCloudEventRouterEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 9fc879cfec..c377088b62 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -5,17 +5,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -34,7 +45,6 @@ "supertest": "^6.1.3" }, "files": [ - "alpha", "dist" ] } diff --git a/plugins/events-backend-module-bitbucket-cloud/src/alpha.ts b/plugins/events-backend-module-bitbucket-cloud/src/alpha.ts new file mode 100644 index 0000000000..e19ff9c9b5 --- /dev/null +++ b/plugins/events-backend-module-bitbucket-cloud/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { bitbucketCloudEventRouterEventsModule } from './service/BitbucketCloudEventRouterEventsModule'; diff --git a/plugins/events-backend-module-bitbucket-cloud/src/index.ts b/plugins/events-backend-module-bitbucket-cloud/src/index.ts index 0a58212de2..77aa9798ef 100644 --- a/plugins/events-backend-module-bitbucket-cloud/src/index.ts +++ b/plugins/events-backend-module-bitbucket-cloud/src/index.ts @@ -22,4 +22,3 @@ */ export { BitbucketCloudEventRouter } from './router/BitbucketCloudEventRouter'; -export { bitbucketCloudEventRouterEventsModule } from './service/BitbucketCloudEventRouterEventsModule'; diff --git a/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.test.ts b/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.test.ts index e456607a2b..60ce5b713e 100644 --- a/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.test.ts +++ b/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.test.ts @@ -15,7 +15,7 @@ */ import { startTestBackend } from '@backstage/backend-test-utils'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { bitbucketCloudEventRouterEventsModule } from './BitbucketCloudEventRouterEventsModule'; import { BitbucketCloudEventRouter } from '../router/BitbucketCloudEventRouter'; diff --git a/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts b/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts index 7f755a28f4..1f339a2bd1 100644 --- a/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts +++ b/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts @@ -15,7 +15,7 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { BitbucketCloudEventRouter } from '../router/BitbucketCloudEventRouter'; /** From 70cf02dd6b6100852394334626fddbdea4c38cf7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 09:48:22 +0100 Subject: [PATCH 333/417] events-backend-module-azure: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../alpha-api-report.md | 14 ++++++++++++ .../events-backend-module-azure/api-report.md | 4 ---- .../events-backend-module-azure/package.json | 22 ++++++++++++++----- .../events-backend-module-azure/src/alpha.ts | 17 ++++++++++++++ .../events-backend-module-azure/src/index.ts | 1 - ...AzureDevOpsEventRouterEventsModule.test.ts | 2 +- .../AzureDevOpsEventRouterEventsModule.ts | 2 +- 7 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 plugins/events-backend-module-azure/alpha-api-report.md create mode 100644 plugins/events-backend-module-azure/src/alpha.ts diff --git a/plugins/events-backend-module-azure/alpha-api-report.md b/plugins/events-backend-module-azure/alpha-api-report.md new file mode 100644 index 0000000000..ccae207a64 --- /dev/null +++ b/plugins/events-backend-module-azure/alpha-api-report.md @@ -0,0 +1,14 @@ +## API Report File for "@backstage/plugin-events-backend-module-azure" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-azure" does not have an export "AzureDevOpsEventRouter" +// +// @alpha +export const azureDevOpsEventRouterEventsModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-backend-module-azure/api-report.md b/plugins/events-backend-module-azure/api-report.md index 2e13a7ed4a..4460aeb510 100644 --- a/plugins/events-backend-module-azure/api-report.md +++ b/plugins/events-backend-module-azure/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { EventParams } from '@backstage/plugin-events-node'; import { SubTopicEventRouter } from '@backstage/plugin-events-node'; @@ -13,7 +12,4 @@ export class AzureDevOpsEventRouter extends SubTopicEventRouter { // (undocumented) protected determineSubTopic(params: EventParams): string | undefined; } - -// @alpha -export const azureDevOpsEventRouterEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 88c2dcc795..540a2c700f 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -5,17 +5,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -34,7 +45,6 @@ "supertest": "^6.1.3" }, "files": [ - "alpha", "dist" ] } diff --git a/plugins/events-backend-module-azure/src/alpha.ts b/plugins/events-backend-module-azure/src/alpha.ts new file mode 100644 index 0000000000..8eacbd8270 --- /dev/null +++ b/plugins/events-backend-module-azure/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { azureDevOpsEventRouterEventsModule } from './service/AzureDevOpsEventRouterEventsModule'; diff --git a/plugins/events-backend-module-azure/src/index.ts b/plugins/events-backend-module-azure/src/index.ts index 9a83f751f6..a1d56dc536 100644 --- a/plugins/events-backend-module-azure/src/index.ts +++ b/plugins/events-backend-module-azure/src/index.ts @@ -22,4 +22,3 @@ */ export { AzureDevOpsEventRouter } from './router/AzureDevOpsEventRouter'; -export { azureDevOpsEventRouterEventsModule } from './service/AzureDevOpsEventRouterEventsModule'; diff --git a/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.test.ts b/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.test.ts index 86ab7ea17d..dbd61782ae 100644 --- a/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.test.ts +++ b/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.test.ts @@ -15,7 +15,7 @@ */ import { startTestBackend } from '@backstage/backend-test-utils'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { azureDevOpsEventRouterEventsModule } from './AzureDevOpsEventRouterEventsModule'; import { AzureDevOpsEventRouter } from '../router/AzureDevOpsEventRouter'; diff --git a/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts b/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts index 1219452bd8..1ceefe5c4e 100644 --- a/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts +++ b/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts @@ -15,7 +15,7 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { AzureDevOpsEventRouter } from '../router/AzureDevOpsEventRouter'; /** From 888328305e21e1ba120d7dd8e37e2daea630ebc9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 09:50:14 +0100 Subject: [PATCH 334/417] events-backend-module-aws-sqs: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../alpha-api-report.md | 12 ++++++++++ .../api-report.md | 4 ---- .../package.json | 22 ++++++++++++++----- .../src/alpha.ts | 17 ++++++++++++++ .../src/index.ts | 1 - ...onsumingEventPublisherEventsModule.test.ts | 2 +- ...sSqsConsumingEventPublisherEventsModule.ts | 2 +- 7 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 plugins/events-backend-module-aws-sqs/alpha-api-report.md create mode 100644 plugins/events-backend-module-aws-sqs/src/alpha.ts diff --git a/plugins/events-backend-module-aws-sqs/alpha-api-report.md b/plugins/events-backend-module-aws-sqs/alpha-api-report.md new file mode 100644 index 0000000000..b9f60c4437 --- /dev/null +++ b/plugins/events-backend-module-aws-sqs/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-events-backend-module-aws-sqs" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +export const awsSqsConsumingEventPublisherEventsModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-backend-module-aws-sqs/api-report.md b/plugins/events-backend-module-aws-sqs/api-report.md index ede18f2787..ffa9c888d6 100644 --- a/plugins/events-backend-module-aws-sqs/api-report.md +++ b/plugins/events-backend-module-aws-sqs/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { EventBroker } from '@backstage/plugin-events-node'; import { EventPublisher } from '@backstage/plugin-events-node'; @@ -21,7 +20,4 @@ export class AwsSqsConsumingEventPublisher implements EventPublisher { // (undocumented) setEventBroker(eventBroker: EventBroker): Promise; } - -// @alpha -export const awsSqsConsumingEventPublisherEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index a4ec624c91..19aec3108a 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -5,17 +5,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -42,7 +53,6 @@ "aws-sdk-client-mock": "^2.0.0" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/events-backend-module-aws-sqs/src/alpha.ts b/plugins/events-backend-module-aws-sqs/src/alpha.ts new file mode 100644 index 0000000000..00f08e4417 --- /dev/null +++ b/plugins/events-backend-module-aws-sqs/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { awsSqsConsumingEventPublisherEventsModule } from './service/AwsSqsConsumingEventPublisherEventsModule'; diff --git a/plugins/events-backend-module-aws-sqs/src/index.ts b/plugins/events-backend-module-aws-sqs/src/index.ts index 73b950856b..57f409c044 100644 --- a/plugins/events-backend-module-aws-sqs/src/index.ts +++ b/plugins/events-backend-module-aws-sqs/src/index.ts @@ -24,4 +24,3 @@ */ export { AwsSqsConsumingEventPublisher } from './publisher/AwsSqsConsumingEventPublisher'; -export { awsSqsConsumingEventPublisherEventsModule } from './service/AwsSqsConsumingEventPublisherEventsModule'; diff --git a/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.test.ts b/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.test.ts index 589b8c93fa..3963b9a8b6 100644 --- a/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.test.ts +++ b/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.test.ts @@ -18,7 +18,7 @@ import { getVoidLogger } from '@backstage/backend-common'; import { coreServices } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { TestEventBroker } from '@backstage/plugin-events-backend-test-utils'; import { awsSqsConsumingEventPublisherEventsModule } from './AwsSqsConsumingEventPublisherEventsModule'; import { AwsSqsConsumingEventPublisher } from '../publisher/AwsSqsConsumingEventPublisher'; diff --git a/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts b/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts index 50812f321b..4205bd231b 100644 --- a/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts +++ b/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts @@ -19,7 +19,7 @@ import { createBackendModule, } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { AwsSqsConsumingEventPublisher } from '../publisher/AwsSqsConsumingEventPublisher'; /** From 28e8d59d58f0fd1be2a459e16b4aac2d4f1ab743 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 09:52:00 +0100 Subject: [PATCH 335/417] events-backend: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/events-backend/alpha-api-report.md | 12 ++++++++++ plugins/events-backend/api-report.md | 4 ---- plugins/events-backend/package.json | 22 ++++++++++++++----- plugins/events-backend/src/alpha.ts | 17 ++++++++++++++ plugins/events-backend/src/index.ts | 1 - .../src/service/EventsPlugin.test.ts | 2 +- .../src/service/EventsPlugin.ts | 6 +++-- 7 files changed, 50 insertions(+), 14 deletions(-) create mode 100644 plugins/events-backend/alpha-api-report.md create mode 100644 plugins/events-backend/src/alpha.ts diff --git a/plugins/events-backend/alpha-api-report.md b/plugins/events-backend/alpha-api-report.md new file mode 100644 index 0000000000..3e32f769c1 --- /dev/null +++ b/plugins/events-backend/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-events-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +export const eventsPlugin: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-backend/api-report.md b/plugins/events-backend/api-report.md index 28437772ae..7d8ede1979 100644 --- a/plugins/events-backend/api-report.md +++ b/plugins/events-backend/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { EventBroker } from '@backstage/plugin-events-node'; import { EventPublisher } from '@backstage/plugin-events-node'; @@ -28,9 +27,6 @@ export class EventsBackend { start(): Promise; } -// @alpha -export const eventsPlugin: () => BackendFeature; - // @public export class HttpPostIngressEventPublisher implements EventPublisher { // (undocumented) diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index fce00f668c..4534dac9de 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -5,17 +5,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -40,7 +51,6 @@ "supertest": "^6.1.3" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/events-backend/src/alpha.ts b/plugins/events-backend/src/alpha.ts new file mode 100644 index 0000000000..4403da1636 --- /dev/null +++ b/plugins/events-backend/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { eventsPlugin } from './service/EventsPlugin'; diff --git a/plugins/events-backend/src/index.ts b/plugins/events-backend/src/index.ts index 5026729015..4645e9a479 100644 --- a/plugins/events-backend/src/index.ts +++ b/plugins/events-backend/src/index.ts @@ -21,5 +21,4 @@ */ export { EventsBackend } from './service/EventsBackend'; -export { eventsPlugin } from './service/EventsPlugin'; export { HttpPostIngressEventPublisher } from './service/http'; diff --git a/plugins/events-backend/src/service/EventsPlugin.test.ts b/plugins/events-backend/src/service/EventsPlugin.test.ts index 0570b16d01..73578ae222 100644 --- a/plugins/events-backend/src/service/EventsPlugin.test.ts +++ b/plugins/events-backend/src/service/EventsPlugin.test.ts @@ -21,7 +21,7 @@ import { createBackendModule, } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { TestEventBroker, TestEventPublisher, diff --git a/plugins/events-backend/src/service/EventsPlugin.ts b/plugins/events-backend/src/service/EventsPlugin.ts index 402104b56c..1ae038a2ac 100644 --- a/plugins/events-backend/src/service/EventsPlugin.ts +++ b/plugins/events-backend/src/service/EventsPlugin.ts @@ -19,12 +19,14 @@ import { coreServices, } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + eventsExtensionPoint, + EventsExtensionPoint, +} from '@backstage/plugin-events-node/alpha'; import { EventBroker, EventPublisher, EventSubscriber, - eventsExtensionPoint, - EventsExtensionPoint, HttpPostIngressOptions, } from '@backstage/plugin-events-node'; import { InMemoryEventBroker } from './InMemoryEventBroker'; From e1c35fbaab7f60e108db847c9e95714d7d543774 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 09:55:20 +0100 Subject: [PATCH 336/417] catalog-react: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/catalog-react/alpha-api-report.md | 22 +++++++++++++++++++++ plugins/catalog-react/api-report.md | 13 ------------ plugins/catalog-react/package.json | 24 ++++++++++++++++------- plugins/catalog-react/src/alpha.ts | 18 +++++++++++++++++ plugins/catalog-react/src/hooks/index.ts | 1 - plugins/catalog-react/src/index.ts | 6 +----- 6 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 plugins/catalog-react/alpha-api-report.md create mode 100644 plugins/catalog-react/src/alpha.ts diff --git a/plugins/catalog-react/alpha-api-report.md b/plugins/catalog-react/alpha-api-report.md new file mode 100644 index 0000000000..f9b740c07c --- /dev/null +++ b/plugins/catalog-react/alpha-api-report.md @@ -0,0 +1,22 @@ +## API Report File for "@backstage/plugin-catalog-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Entity } from '@backstage/catalog-model'; +import { ResourcePermission } from '@backstage/plugin-permission-common'; + +// @alpha +export function isOwnerOf(owner: Entity, entity: Entity): boolean; + +// @alpha +export function useEntityPermission( + permission: ResourcePermission<'catalog-entity'>, +): { + loading: boolean; + allowed: boolean; + error?: Error; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 4756432857..55c72122f5 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -20,7 +20,6 @@ import { Overrides } from '@material-ui/core/styles/overrides'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; -import { ResourcePermission } from '@backstage/plugin-permission-common'; import { RouteRef } from '@backstage/core-plugin-api'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { StyleRules } from '@material-ui/core/styles/withStyles'; @@ -474,9 +473,6 @@ export function InspectEntityDialog(props: { onClose: () => void; }): JSX.Element | null; -// @alpha -export function isOwnerOf(owner: Entity, entity: Entity): boolean; - // @public (undocumented) export function MockEntityListContextProvider< T extends DefaultEntityFilters = DefaultEntityFilters, @@ -538,15 +534,6 @@ export function useEntityOwnership(): { isOwnedEntity: (entity: Entity) => boolean; }; -// @alpha -export function useEntityPermission( - permission: ResourcePermission<'catalog-entity'>, -): { - loading: boolean; - allowed: boolean; - error?: Error; -}; - // @public export function useEntityTypeFilter(): { loading: boolean; diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index e66c2b4bb1..0ca4e3c9e4 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "web-library" @@ -24,7 +35,7 @@ "backstage" ], "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -78,7 +89,6 @@ "react-test-renderer": "^16.13.1" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/plugins/catalog-react/src/alpha.ts b/plugins/catalog-react/src/alpha.ts new file mode 100644 index 0000000000..e8ff21609e --- /dev/null +++ b/plugins/catalog-react/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { isOwnerOf } from './utils'; +export { useEntityPermission } from './hooks/useEntityPermission'; diff --git a/plugins/catalog-react/src/hooks/index.ts b/plugins/catalog-react/src/hooks/index.ts index 3570ed897c..ffd32206ef 100644 --- a/plugins/catalog-react/src/hooks/index.ts +++ b/plugins/catalog-react/src/hooks/index.ts @@ -38,4 +38,3 @@ export { useRelatedEntities } from './useRelatedEntities'; export { useStarredEntities } from './useStarredEntities'; export { useStarredEntity } from './useStarredEntity'; export { useEntityOwnership } from './useEntityOwnership'; -export { useEntityPermission } from './useEntityPermission'; diff --git a/plugins/catalog-react/src/index.ts b/plugins/catalog-react/src/index.ts index 2ca7d67d59..b511116f84 100644 --- a/plugins/catalog-react/src/index.ts +++ b/plugins/catalog-react/src/index.ts @@ -31,9 +31,5 @@ export { entityRouteParams, entityRouteRef } from './routes'; export * from './testUtils'; export * from './types'; export * from './overridableComponents'; -export { - getEntityRelations, - getEntitySourceLocation, - isOwnerOf, -} from './utils'; +export { getEntityRelations, getEntitySourceLocation } from './utils'; export type { EntitySourceLocation } from './utils'; From dac6ddfae808ab1565ae337b129b607f32d458f2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 09:57:40 +0100 Subject: [PATCH 337/417] catalog-node: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/catalog-node/alpha-api-report.md | 39 ++++++++++++++++++++++++ plugins/catalog-node/api-report.md | 21 ------------- plugins/catalog-node/package.json | 24 ++++++++++----- plugins/catalog-node/src/alpha.ts | 19 ++++++++++++ plugins/catalog-node/src/index.ts | 3 -- 5 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 plugins/catalog-node/alpha-api-report.md create mode 100644 plugins/catalog-node/src/alpha.ts diff --git a/plugins/catalog-node/alpha-api-report.md b/plugins/catalog-node/alpha-api-report.md new file mode 100644 index 0000000000..1bfb3f3566 --- /dev/null +++ b/plugins/catalog-node/alpha-api-report.md @@ -0,0 +1,39 @@ +## API Report File for "@backstage/plugin-catalog-node" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { CatalogApi } from '@backstage/catalog-client'; +import { CompoundEntityRef } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; +import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { JsonValue } from '@backstage/types'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; +import { ServiceRef } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export interface CatalogProcessingExtensionPoint { + // Warning: (ae-forgotten-export) The symbol "EntityProvider" needs to be exported by the entry point alpha.d.ts + // + // (undocumented) + addEntityProvider( + ...providers: Array> + ): void; + // Warning: (ae-forgotten-export) The symbol "CatalogProcessor" needs to be exported by the entry point alpha.d.ts + // + // (undocumented) + addProcessor( + ...processors: Array> + ): void; +} + +// @alpha (undocumented) +export const catalogProcessingExtensionPoint: ExtensionPoint; + +// @alpha +export const catalogServiceRef: ServiceRef; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-node/api-report.md b/plugins/catalog-node/api-report.md index 9e9045db84..87da0b6944 100644 --- a/plugins/catalog-node/api-report.md +++ b/plugins/catalog-node/api-report.md @@ -5,28 +5,10 @@ ```ts /// -import { CatalogApi } from '@backstage/catalog-client'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { Entity } from '@backstage/catalog-model'; -import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { JsonValue } from '@backstage/types'; import { LocationSpec as LocationSpec_2 } from '@backstage/plugin-catalog-common'; -import { ServiceRef } from '@backstage/backend-plugin-api'; - -// @alpha (undocumented) -export interface CatalogProcessingExtensionPoint { - // (undocumented) - addEntityProvider( - ...providers: Array> - ): void; - // (undocumented) - addProcessor( - ...processors: Array> - ): void; -} - -// @alpha (undocumented) -export const catalogProcessingExtensionPoint: ExtensionPoint; // @public (undocumented) export type CatalogProcessor = { @@ -109,9 +91,6 @@ export type CatalogProcessorResult = | CatalogProcessorErrorResult | CatalogProcessorRefreshKeysResult; -// @alpha -export const catalogServiceRef: ServiceRef; - // @public export type DeferredEntity = { entity: Entity; diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 248b808645..d949bfaabb 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -6,17 +6,28 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "node-library" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -37,7 +48,6 @@ "@backstage/cli": "workspace:^" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/plugins/catalog-node/src/alpha.ts b/plugins/catalog-node/src/alpha.ts new file mode 100644 index 0000000000..4fb07bbc25 --- /dev/null +++ b/plugins/catalog-node/src/alpha.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { catalogServiceRef } from './catalogService'; +export type { CatalogProcessingExtensionPoint } from './extensions'; +export { catalogProcessingExtensionPoint } from './extensions'; diff --git a/plugins/catalog-node/src/index.ts b/plugins/catalog-node/src/index.ts index 6393c55f31..6a1accfcbd 100644 --- a/plugins/catalog-node/src/index.ts +++ b/plugins/catalog-node/src/index.ts @@ -20,8 +20,5 @@ * @packageDocumentation */ -export type { CatalogProcessingExtensionPoint } from './extensions'; -export { catalogProcessingExtensionPoint } from './extensions'; -export { catalogServiceRef } from './catalogService'; export * from './api'; export * from './processing'; From 57d39ea54aa8de51bad8f0c9f1caf212b713cbc4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 09:59:08 +0100 Subject: [PATCH 338/417] catalog-common: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/catalog-common/alpha-api-report.md | 45 ++++++++++++++++++++++ plugins/catalog-common/api-report.md | 37 ------------------ plugins/catalog-common/package.json | 25 ++++++++---- plugins/catalog-common/src/alpha.ts | 28 ++++++++++++++ plugins/catalog-common/src/index.ts | 13 ------- 5 files changed, 90 insertions(+), 58 deletions(-) create mode 100644 plugins/catalog-common/alpha-api-report.md create mode 100644 plugins/catalog-common/src/alpha.ts diff --git a/plugins/catalog-common/alpha-api-report.md b/plugins/catalog-common/alpha-api-report.md new file mode 100644 index 0000000000..12e0806a9c --- /dev/null +++ b/plugins/catalog-common/alpha-api-report.md @@ -0,0 +1,45 @@ +## API Report File for "@backstage/plugin-catalog-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BasicPermission } from '@backstage/plugin-permission-common'; +import { ResourcePermission } from '@backstage/plugin-permission-common'; + +// @alpha +export const catalogEntityCreatePermission: BasicPermission; + +// @alpha +export const catalogEntityDeletePermission: ResourcePermission<'catalog-entity'>; + +// @alpha +export type CatalogEntityPermission = ResourcePermission< + typeof RESOURCE_TYPE_CATALOG_ENTITY +>; + +// @alpha +export const catalogEntityReadPermission: ResourcePermission<'catalog-entity'>; + +// @alpha +export const catalogEntityRefreshPermission: ResourcePermission<'catalog-entity'>; + +// @alpha +export const catalogLocationCreatePermission: BasicPermission; + +// @alpha +export const catalogLocationDeletePermission: BasicPermission; + +// @alpha +export const catalogLocationReadPermission: BasicPermission; + +// @alpha +export const catalogPermissions: ( + | BasicPermission + | ResourcePermission<'catalog-entity'> +)[]; + +// @alpha +export const RESOURCE_TYPE_CATALOG_ENTITY = 'catalog-entity'; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-common/api-report.md b/plugins/catalog-common/api-report.md index 1bef626c79..231c8aac34 100644 --- a/plugins/catalog-common/api-report.md +++ b/plugins/catalog-common/api-report.md @@ -3,10 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BasicPermission } from '@backstage/plugin-permission-common'; import { Entity } from '@backstage/catalog-model'; import { IndexableDocument } from '@backstage/plugin-search-common'; -import { ResourcePermission } from '@backstage/plugin-permission-common'; // @public (undocumented) export type AnalyzeLocationEntityField = { @@ -44,12 +42,6 @@ export type AnalyzeLocationResponse = { generateEntities: AnalyzeLocationGenerateEntity[]; }; -// @alpha -export const catalogEntityCreatePermission: BasicPermission; - -// @alpha -export const catalogEntityDeletePermission: ResourcePermission<'catalog-entity'>; - // @public export interface CatalogEntityDocument extends IndexableDocument { // @deprecated (undocumented) @@ -66,39 +58,10 @@ export interface CatalogEntityDocument extends IndexableDocument { type: string; } -// @alpha -export type CatalogEntityPermission = ResourcePermission< - typeof RESOURCE_TYPE_CATALOG_ENTITY ->; - -// @alpha -export const catalogEntityReadPermission: ResourcePermission<'catalog-entity'>; - -// @alpha -export const catalogEntityRefreshPermission: ResourcePermission<'catalog-entity'>; - -// @alpha -export const catalogLocationCreatePermission: BasicPermission; - -// @alpha -export const catalogLocationDeletePermission: BasicPermission; - -// @alpha -export const catalogLocationReadPermission: BasicPermission; - -// @alpha -export const catalogPermissions: ( - | BasicPermission - | ResourcePermission<'catalog-entity'> -)[]; - // @public export type LocationSpec = { type: string; target: string; presence?: 'optional' | 'required'; }; - -// @alpha -export const RESOURCE_TYPE_CATALOG_ENTITY = 'catalog-entity'; ``` diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 0ffaf3cff7..55680e679c 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -6,11 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "module": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "common-library" @@ -25,7 +35,7 @@ "backstage" ], "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -41,7 +51,6 @@ "@backstage/cli": "workspace:^" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/plugins/catalog-common/src/alpha.ts b/plugins/catalog-common/src/alpha.ts new file mode 100644 index 0000000000..2dfc028332 --- /dev/null +++ b/plugins/catalog-common/src/alpha.ts @@ -0,0 +1,28 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + RESOURCE_TYPE_CATALOG_ENTITY, + catalogEntityReadPermission, + catalogEntityCreatePermission, + catalogEntityDeletePermission, + catalogEntityRefreshPermission, + catalogLocationReadPermission, + catalogLocationCreatePermission, + catalogLocationDeletePermission, + catalogPermissions, +} from './permissions'; +export type { CatalogEntityPermission } from './permissions'; diff --git a/plugins/catalog-common/src/index.ts b/plugins/catalog-common/src/index.ts index 95bd65bc92..52860a0e66 100644 --- a/plugins/catalog-common/src/index.ts +++ b/plugins/catalog-common/src/index.ts @@ -21,19 +21,6 @@ * @packageDocumentation */ -export { - RESOURCE_TYPE_CATALOG_ENTITY, - catalogEntityReadPermission, - catalogEntityCreatePermission, - catalogEntityDeletePermission, - catalogEntityRefreshPermission, - catalogLocationReadPermission, - catalogLocationCreatePermission, - catalogLocationDeletePermission, - catalogPermissions, -} from './permissions'; -export type { CatalogEntityPermission } from './permissions'; - export * from './search'; export * from './ingestion'; export type { LocationSpec } from './common'; From 69ffa70600f039f55c42add5e9a58a4da217d1e9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 10:13:39 +0100 Subject: [PATCH 339/417] catalog-backend-module-*: migrate to use exports Signed-off-by: Patrik Oldsberg --- .../alpha-api-report.md | 12 +++++++++ .../catalog-backend-module-aws/api-report.md | 4 --- .../catalog-backend-module-aws/package.json | 22 ++++++++++----- .../catalog-backend-module-aws/src/alpha.ts | 17 ++++++++++++ .../catalog-backend-module-aws/src/index.ts | 1 - .../AwsS3EntityProviderCatalogModule.test.ts | 2 +- .../AwsS3EntityProviderCatalogModule.ts | 2 +- .../alpha-api-report.md | 12 +++++++++ .../api-report.md | 4 --- .../catalog-backend-module-azure/package.json | 22 ++++++++++----- .../catalog-backend-module-azure/src/alpha.ts | 17 ++++++++++++ .../catalog-backend-module-azure/src/index.ts | 1 - ...eDevOpsEntityProviderCatalogModule.test.ts | 2 +- .../AzureDevOpsEntityProviderCatalogModule.ts | 2 +- .../alpha-api-report.md | 12 +++++++++ .../api-report.md | 4 --- .../package.json | 22 ++++++++++----- .../src/alpha.ts | 17 ++++++++++++ .../src/index.ts | 1 - ...etCloudEntityProviderCatalogModule.test.ts | 4 +-- ...tbucketCloudEntityProviderCatalogModule.ts | 4 +-- .../alpha-api-report.md | 12 +++++++++ .../api-report.md | 4 --- .../package.json | 22 ++++++++++----- .../src/alpha.ts | 17 ++++++++++++ .../src/index.ts | 1 - ...tServerEntityProviderCatalogModule.test.ts | 2 +- ...bucketServerEntityProviderCatalogModule.ts | 2 +- .../alpha-api-report.md | 12 +++++++++ .../api-report.md | 4 --- .../package.json | 21 +++++++++++---- .../src/alpha.ts | 17 ++++++++++++ .../src/index.ts | 1 - .../GerritEntityProviderCatalogModule.test.ts | 2 +- .../GerritEntityProviderCatalogModule.ts | 2 +- .../GithubEntityProviderCatalogModule.test.ts | 2 +- .../GithubEntityProviderCatalogModule.ts | 2 +- .../alpha-api-report.md | 12 +++++++++ .../api-report.md | 4 --- .../package.json | 22 ++++++++++----- .../src/alpha.ts | 17 ++++++++++++ .../src/index.ts | 1 - ...scoveryEntityProviderCatalogModule.test.ts | 2 +- ...labDiscoveryEntityProviderCatalogModule.ts | 2 +- .../alpha-api-report.md | 24 +++++++++++++++++ .../api-report.md | 11 -------- .../package.json | 22 ++++++++++----- .../src/alpha.ts | 17 ++++++++++++ .../src/index.ts | 1 - ...gestionEntityProviderCatalogModule.test.ts | 2 +- ...talIngestionEntityProviderCatalogModule.ts | 2 +- .../src/run.ts | 6 ++--- .../alpha-api-report.md | 27 +++++++++++++++++++ .../api-report.md | 13 --------- .../package.json | 22 ++++++++++----- .../src/alpha.ts | 18 +++++++++++++ .../src/index.ts | 2 -- ...raphOrgEntityProviderCatalogModule.test.ts | 2 +- ...softGraphOrgEntityProviderCatalogModule.ts | 2 +- 59 files changed, 410 insertions(+), 128 deletions(-) create mode 100644 plugins/catalog-backend-module-aws/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-aws/src/alpha.ts create mode 100644 plugins/catalog-backend-module-azure/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-azure/src/alpha.ts create mode 100644 plugins/catalog-backend-module-bitbucket-cloud/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-bitbucket-cloud/src/alpha.ts create mode 100644 plugins/catalog-backend-module-bitbucket-server/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-bitbucket-server/src/alpha.ts create mode 100644 plugins/catalog-backend-module-gerrit/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-gerrit/src/alpha.ts create mode 100644 plugins/catalog-backend-module-gitlab/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-gitlab/src/alpha.ts create mode 100644 plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-incremental-ingestion/src/alpha.ts create mode 100644 plugins/catalog-backend-module-msgraph/alpha-api-report.md create mode 100644 plugins/catalog-backend-module-msgraph/src/alpha.ts diff --git a/plugins/catalog-backend-module-aws/alpha-api-report.md b/plugins/catalog-backend-module-aws/alpha-api-report.md new file mode 100644 index 0000000000..8781975085 --- /dev/null +++ b/plugins/catalog-backend-module-aws/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-aws" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +export const awsS3EntityProviderCatalogModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-aws/api-report.md b/plugins/catalog-backend-module-aws/api-report.md index 1725692cb1..5086ec1ea7 100644 --- a/plugins/catalog-backend-module-aws/api-report.md +++ b/plugins/catalog-backend-module-aws/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorParser } from '@backstage/plugin-catalog-backend'; @@ -88,7 +87,4 @@ export class AwsS3EntityProvider implements EntityProvider { // (undocumented) refresh(logger: Logger): Promise; } - -// @alpha -export const awsS3EntityProviderCatalogModule: () => BackendFeature; ``` diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index f583d64792..c309ee995e 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -60,7 +71,6 @@ "yaml": "^2.0.0" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/catalog-backend-module-aws/src/alpha.ts b/plugins/catalog-backend-module-aws/src/alpha.ts new file mode 100644 index 0000000000..3ae30df0cb --- /dev/null +++ b/plugins/catalog-backend-module-aws/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { awsS3EntityProviderCatalogModule } from './service/AwsS3EntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-aws/src/index.ts b/plugins/catalog-backend-module-aws/src/index.ts index 804fd97e91..212308edaa 100644 --- a/plugins/catalog-backend-module-aws/src/index.ts +++ b/plugins/catalog-backend-module-aws/src/index.ts @@ -22,5 +22,4 @@ export * from './processors'; export * from './providers'; -export { awsS3EntityProviderCatalogModule } from './service/AwsS3EntityProviderCatalogModule'; export * from './types'; diff --git a/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.test.ts index c0d36ad3c2..868a9535b4 100644 --- a/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.test.ts @@ -22,7 +22,7 @@ import { } from '@backstage/backend-tasks'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { awsS3EntityProviderCatalogModule } from './AwsS3EntityProviderCatalogModule'; import { AwsS3EntityProvider } from '../providers'; diff --git a/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts b/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts index cbc137ab40..5d4170ec1c 100644 --- a/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts @@ -19,7 +19,7 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { AwsS3EntityProvider } from '../providers'; /** diff --git a/plugins/catalog-backend-module-azure/alpha-api-report.md b/plugins/catalog-backend-module-azure/alpha-api-report.md new file mode 100644 index 0000000000..486aac7775 --- /dev/null +++ b/plugins/catalog-backend-module-azure/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-azure" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +export const azureDevOpsEntityProviderCatalogModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-azure/api-report.md b/plugins/catalog-backend-module-azure/api-report.md index 5ffae14b6b..8fb7edeb53 100644 --- a/plugins/catalog-backend-module-azure/api-report.md +++ b/plugins/catalog-backend-module-azure/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; @@ -56,7 +55,4 @@ export class AzureDevOpsEntityProvider implements EntityProvider { // (undocumented) refresh(logger: Logger): Promise; } - -// @alpha -export const azureDevOpsEntityProviderCatalogModule: () => BackendFeature; ``` diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 518d7b89ad..b68015cb87 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -56,7 +67,6 @@ "msw": "^0.49.0" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/catalog-backend-module-azure/src/alpha.ts b/plugins/catalog-backend-module-azure/src/alpha.ts new file mode 100644 index 0000000000..cc3c4a83af --- /dev/null +++ b/plugins/catalog-backend-module-azure/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { azureDevOpsEntityProviderCatalogModule } from './service/AzureDevOpsEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-azure/src/index.ts b/plugins/catalog-backend-module-azure/src/index.ts index aa3a94fda2..a71c40ee6c 100644 --- a/plugins/catalog-backend-module-azure/src/index.ts +++ b/plugins/catalog-backend-module-azure/src/index.ts @@ -22,4 +22,3 @@ export { AzureDevOpsDiscoveryProcessor } from './processors'; export { AzureDevOpsEntityProvider } from './providers'; -export { azureDevOpsEntityProviderCatalogModule } from './service/AzureDevOpsEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.test.ts index a11e6b14f2..a8e526e871 100644 --- a/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.test.ts @@ -22,7 +22,7 @@ import { } from '@backstage/backend-tasks'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { azureDevOpsEntityProviderCatalogModule } from './AzureDevOpsEntityProviderCatalogModule'; import { AzureDevOpsEntityProvider } from '../providers'; diff --git a/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts index bd59cec29b..3fc1ddf3a4 100644 --- a/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts @@ -19,7 +19,7 @@ import { createBackendModule, coreServices, } from '@backstage/backend-plugin-api'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { AzureDevOpsEntityProvider } from '../providers'; /** diff --git a/plugins/catalog-backend-module-bitbucket-cloud/alpha-api-report.md b/plugins/catalog-backend-module-bitbucket-cloud/alpha-api-report.md new file mode 100644 index 0000000000..77b4b77410 --- /dev/null +++ b/plugins/catalog-backend-module-bitbucket-cloud/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-bitbucket-cloud" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export const bitbucketCloudEntityProviderCatalogModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-bitbucket-cloud/api-report.md b/plugins/catalog-backend-module-bitbucket-cloud/api-report.md index 7ad6b3b3e0..456ea62dd3 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/api-report.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { EntityProvider } from '@backstage/plugin-catalog-backend'; @@ -46,7 +45,4 @@ export class BitbucketCloudEntityProvider // (undocumented) supportsEventTopics(): string[]; } - -// @alpha (undocumented) -export const bitbucketCloudEntityProviderCatalogModule: () => BackendFeature; ``` diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index d9b1c6613f..9f2243b0cd 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -56,7 +67,6 @@ "msw": "^0.49.0" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/alpha.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/alpha.ts new file mode 100644 index 0000000000..e949dcb894 --- /dev/null +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { bitbucketCloudEntityProviderCatalogModule } from './service/BitbucketCloudEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/index.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/index.ts index c1f04b8877..1c15ad4e8f 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/index.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/index.ts @@ -21,4 +21,3 @@ */ export { BitbucketCloudEntityProvider } from './BitbucketCloudEntityProvider'; -export { bitbucketCloudEntityProviderCatalogModule } from './service/BitbucketCloudEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts index 1b18ab0ed9..630c18b134 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts @@ -20,8 +20,8 @@ import { TaskScheduleDefinition, } from '@backstage/backend-tasks'; import { startTestBackend, mockServices } from '@backstage/backend-test-utils'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { Duration } from 'luxon'; import { bitbucketCloudEntityProviderCatalogModule } from './BitbucketCloudEntityProviderCatalogModule'; import { BitbucketCloudEntityProvider } from '../BitbucketCloudEntityProvider'; diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts index d17656a473..a95d99ceef 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts @@ -22,8 +22,8 @@ import { import { catalogProcessingExtensionPoint, catalogServiceRef, -} from '@backstage/plugin-catalog-node'; -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +} from '@backstage/plugin-catalog-node/alpha'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { BitbucketCloudEntityProvider } from '../BitbucketCloudEntityProvider'; /** diff --git a/plugins/catalog-backend-module-bitbucket-server/alpha-api-report.md b/plugins/catalog-backend-module-bitbucket-server/alpha-api-report.md new file mode 100644 index 0000000000..3177828f51 --- /dev/null +++ b/plugins/catalog-backend-module-bitbucket-server/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-bitbucket-server" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export const bitbucketServerEntityProviderCatalogModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-bitbucket-server/api-report.md b/plugins/catalog-backend-module-bitbucket-server/api-report.md index 213f5d2573..6c840883af 100644 --- a/plugins/catalog-backend-module-bitbucket-server/api-report.md +++ b/plugins/catalog-backend-module-bitbucket-server/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { BitbucketServerIntegrationConfig } from '@backstage/integration'; import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; @@ -68,9 +67,6 @@ export class BitbucketServerEntityProvider implements EntityProvider { refresh(logger: Logger): Promise; } -// @alpha (undocumented) -export const bitbucketServerEntityProviderCatalogModule: () => BackendFeature; - // @public (undocumented) export type BitbucketServerListOptions = { [key: string]: number | undefined; diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index fdfc5649a5..d11b9136e6 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -5,10 +5,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -24,7 +35,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -53,7 +64,6 @@ "msw": "^0.49.0" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/catalog-backend-module-bitbucket-server/src/alpha.ts b/plugins/catalog-backend-module-bitbucket-server/src/alpha.ts new file mode 100644 index 0000000000..d6227c29f1 --- /dev/null +++ b/plugins/catalog-backend-module-bitbucket-server/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { bitbucketServerEntityProviderCatalogModule } from './service/BitbucketServerEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-bitbucket-server/src/index.ts b/plugins/catalog-backend-module-bitbucket-server/src/index.ts index f139078cfb..34ac3a9966 100644 --- a/plugins/catalog-backend-module-bitbucket-server/src/index.ts +++ b/plugins/catalog-backend-module-bitbucket-server/src/index.ts @@ -29,4 +29,3 @@ export type { } from './lib'; export { BitbucketServerEntityProvider } from './providers'; export type { BitbucketServerLocationParser } from './providers'; -export { bitbucketServerEntityProviderCatalogModule } from './service/BitbucketServerEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.test.ts index 474431dc7a..bdd7209364 100644 --- a/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.test.ts @@ -22,7 +22,7 @@ import { TaskScheduleDefinition, } from '@backstage/backend-tasks'; import { startTestBackend } from '@backstage/backend-test-utils'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { bitbucketServerEntityProviderCatalogModule } from './BitbucketServerEntityProviderCatalogModule'; import { Duration } from 'luxon'; import { BitbucketServerEntityProvider } from '../providers'; diff --git a/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts index 46712d29dd..deab47c9e9 100644 --- a/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts @@ -19,7 +19,7 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { BitbucketServerEntityProvider } from '../providers'; /** diff --git a/plugins/catalog-backend-module-gerrit/alpha-api-report.md b/plugins/catalog-backend-module-gerrit/alpha-api-report.md new file mode 100644 index 0000000000..03f5d099b9 --- /dev/null +++ b/plugins/catalog-backend-module-gerrit/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-gerrit" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export const gerritEntityProviderCatalogModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-gerrit/api-report.md b/plugins/catalog-backend-module-gerrit/api-report.md index 870937f7ec..1dee786da1 100644 --- a/plugins/catalog-backend-module-gerrit/api-report.md +++ b/plugins/catalog-backend-module-gerrit/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { EntityProvider } from '@backstage/plugin-catalog-backend'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; @@ -30,8 +29,5 @@ export class GerritEntityProvider implements EntityProvider { refresh(logger: Logger): Promise; } -// @alpha (undocumented) -export const gerritEntityProviderCatalogModule: () => BackendFeature; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index d945fed9fd..23d2db3073 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -5,10 +5,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -21,7 +32,7 @@ }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", diff --git a/plugins/catalog-backend-module-gerrit/src/alpha.ts b/plugins/catalog-backend-module-gerrit/src/alpha.ts new file mode 100644 index 0000000000..8b03d9312a --- /dev/null +++ b/plugins/catalog-backend-module-gerrit/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { gerritEntityProviderCatalogModule } from './service/GerritEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-gerrit/src/index.ts b/plugins/catalog-backend-module-gerrit/src/index.ts index 38ede69926..133772d4b1 100644 --- a/plugins/catalog-backend-module-gerrit/src/index.ts +++ b/plugins/catalog-backend-module-gerrit/src/index.ts @@ -15,4 +15,3 @@ */ export { GerritEntityProvider } from './providers/GerritEntityProvider'; -export { gerritEntityProviderCatalogModule } from './service/GerritEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.test.ts index 9d61cabdb9..51c1749c66 100644 --- a/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.test.ts @@ -22,7 +22,7 @@ import { } from '@backstage/backend-tasks'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { gerritEntityProviderCatalogModule } from './GerritEntityProviderCatalogModule'; import { GerritEntityProvider } from '../providers/GerritEntityProvider'; diff --git a/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts index 8c61038c8f..782c724094 100644 --- a/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts @@ -19,7 +19,7 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { GerritEntityProvider } from '../providers/GerritEntityProvider'; /** diff --git a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.test.ts index d8ebc8d0ad..7c08e8947d 100644 --- a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.test.ts @@ -22,7 +22,7 @@ import { } from '@backstage/backend-tasks'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { githubEntityProviderCatalogModule } from './GithubEntityProviderCatalogModule'; import { GithubEntityProvider } from '../providers/GithubEntityProvider'; diff --git a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts index d9dc0a12aa..fc319534f3 100644 --- a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts @@ -19,7 +19,7 @@ import { coreServices, } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { GithubEntityProvider } from '../providers/GithubEntityProvider'; /** diff --git a/plugins/catalog-backend-module-gitlab/alpha-api-report.md b/plugins/catalog-backend-module-gitlab/alpha-api-report.md new file mode 100644 index 0000000000..8912b4a7b2 --- /dev/null +++ b/plugins/catalog-backend-module-gitlab/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-gitlab" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +export const gitlabDiscoveryEntityProviderCatalogModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-gitlab/api-report.md b/plugins/catalog-backend-module-gitlab/api-report.md index 0195975d4b..68ea45169f 100644 --- a/plugins/catalog-backend-module-gitlab/api-report.md +++ b/plugins/catalog-backend-module-gitlab/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; @@ -33,9 +32,6 @@ export class GitlabDiscoveryEntityProvider implements EntityProvider { refresh(logger: Logger): Promise; } -// @alpha -export const gitlabDiscoveryEntityProviderCatalogModule: () => BackendFeature; - // @public export class GitLabDiscoveryProcessor implements CatalogProcessor { // (undocumented) diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 4fb26eeb7e..a53da3a97f 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -57,7 +68,6 @@ "msw": "^0.49.0" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/catalog-backend-module-gitlab/src/alpha.ts b/plugins/catalog-backend-module-gitlab/src/alpha.ts new file mode 100644 index 0000000000..883ffc13c4 --- /dev/null +++ b/plugins/catalog-backend-module-gitlab/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { gitlabDiscoveryEntityProviderCatalogModule } from './service/GitlabDiscoveryEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-gitlab/src/index.ts b/plugins/catalog-backend-module-gitlab/src/index.ts index 30efac4924..2dd19c041d 100644 --- a/plugins/catalog-backend-module-gitlab/src/index.ts +++ b/plugins/catalog-backend-module-gitlab/src/index.ts @@ -25,4 +25,3 @@ export { GitlabDiscoveryEntityProvider, GitlabOrgDiscoveryEntityProvider, } from './providers'; -export { gitlabDiscoveryEntityProviderCatalogModule } from './service/GitlabDiscoveryEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.test.ts index ca8d86f555..efb86e4223 100644 --- a/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.test.ts @@ -22,7 +22,7 @@ import { } from '@backstage/backend-tasks'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { gitlabDiscoveryEntityProviderCatalogModule } from './GitlabDiscoveryEntityProviderCatalogModule'; import { GitlabDiscoveryEntityProvider } from '../providers'; diff --git a/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts index bb4fb656a8..0adf5b18f2 100644 --- a/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts @@ -19,7 +19,7 @@ import { coreServices, } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { GitlabDiscoveryEntityProvider } from '../providers'; /** diff --git a/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md b/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md new file mode 100644 index 0000000000..f762503b53 --- /dev/null +++ b/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md @@ -0,0 +1,24 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-incremental-ingestion" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import type { DeferredEntity } from '@backstage/plugin-catalog-backend'; +import type { DurationObjectUnits } from 'luxon'; + +// @alpha +export const incrementalIngestionEntityProviderCatalogModule: (options: { + providers: { + provider: IncrementalEntityProvider; + options: IncrementalEntityProviderOptions; + }[]; +}) => BackendFeature; + +// Warnings were encountered during analysis: +// +// src/module/incrementalIngestionEntityProviderCatalogModule.d.ts:9:9 - (ae-forgotten-export) The symbol "IncrementalEntityProvider" needs to be exported by the entry point alpha.d.ts +// src/module/incrementalIngestionEntityProviderCatalogModule.d.ts:10:9 - (ae-forgotten-export) The symbol "IncrementalEntityProviderOptions" needs to be exported by the entry point alpha.d.ts + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-incremental-ingestion/api-report.md b/plugins/catalog-backend-module-incremental-ingestion/api-report.md index fe9ef24777..27ea35a34c 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/api-report.md +++ b/plugins/catalog-backend-module-incremental-ingestion/api-report.md @@ -3,9 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -/// - -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; import type { Config } from '@backstage/config'; import type { DeferredEntity } from '@backstage/plugin-catalog-backend'; @@ -80,14 +77,6 @@ export interface IncrementalEntityProviderOptions { restLength: DurationObjectUnits; } -// @alpha -export const incrementalIngestionEntityProviderCatalogModule: (options: { - providers: { - provider: IncrementalEntityProvider; - options: IncrementalEntityProviderOptions; - }[]; -}) => BackendFeature; - // @public (undocumented) export type PluginEnvironment = { logger: Logger; diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index ff8272e29e..8cc1ebbf8e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "clean": "backstage-cli package clean", @@ -61,7 +72,6 @@ "@backstage/plugin-catalog-backend": "workspace:^" }, "files": [ - "alpha", "dist", "migrations/**/*.{js,d.ts}" ] diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/alpha.ts b/plugins/catalog-backend-module-incremental-ingestion/src/alpha.ts new file mode 100644 index 0000000000..c277a0a680 --- /dev/null +++ b/plugins/catalog-backend-module-incremental-ingestion/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './module'; diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/index.ts b/plugins/catalog-backend-module-incremental-ingestion/src/index.ts index 976c91a1ce..ff1ee1faa1 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/index.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/index.ts @@ -20,7 +20,6 @@ * @packageDocumentation */ -export * from './module'; export * from './service'; export { type EntityIteratorResult, diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.test.ts index 06cbcb010e..dbadf573a4 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.test.ts @@ -18,7 +18,7 @@ import { getVoidLogger } from '@backstage/backend-common'; import { coreServices } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { IncrementalEntityProvider } from '../types'; import { incrementalIngestionEntityProviderCatalogModule } from './incrementalIngestionEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts index b173b2d2ef..52fcef2cc9 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts @@ -18,7 +18,7 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { IncrementalEntityProvider, IncrementalEntityProviderOptions, diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index eb66140fe2..745fc70883 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -20,10 +20,8 @@ import { } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; import { catalogPlugin } from '@backstage/plugin-catalog-backend'; -import { - IncrementalEntityProvider, - incrementalIngestionEntityProviderCatalogModule, -} from '.'; +import { IncrementalEntityProvider } from '.'; +import { incrementalIngestionEntityProviderCatalogModule } from './alpha'; const provider: IncrementalEntityProvider = { getProviderName: () => 'test-provider', diff --git a/plugins/catalog-backend-module-msgraph/alpha-api-report.md b/plugins/catalog-backend-module-msgraph/alpha-api-report.md new file mode 100644 index 0000000000..c0daedc038 --- /dev/null +++ b/plugins/catalog-backend-module-msgraph/alpha-api-report.md @@ -0,0 +1,27 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-msgraph" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { GroupEntity } from '@backstage/catalog-model'; +import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; +import { UserEntity } from '@backstage/catalog-model'; + +// @alpha +export const microsoftGraphOrgEntityProviderCatalogModule: () => BackendFeature; + +// @alpha +export interface MicrosoftGraphOrgEntityProviderCatalogModuleOptions { + // Warning: (ae-forgotten-export) The symbol "GroupTransformer" needs to be exported by the entry point alpha.d.ts + groupTransformer?: GroupTransformer | Record; + // Warning: (ae-forgotten-export) The symbol "OrganizationTransformer" needs to be exported by the entry point alpha.d.ts + organizationTransformer?: + | OrganizationTransformer + | Record; + // Warning: (ae-forgotten-export) The symbol "UserTransformer" needs to be exported by the entry point alpha.d.ts + userTransformer?: UserTransformer | Record; +} + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index 09770614b4..10a4f405c0 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; @@ -139,18 +138,6 @@ export class MicrosoftGraphOrgEntityProvider implements EntityProvider { read(options?: { logger?: Logger }): Promise; } -// @alpha -export const microsoftGraphOrgEntityProviderCatalogModule: () => BackendFeature; - -// @alpha -export interface MicrosoftGraphOrgEntityProviderCatalogModuleOptions { - groupTransformer?: GroupTransformer | Record; - organizationTransformer?: - | OrganizationTransformer - | Record; - userTransformer?: UserTransformer | Record; -} - // @public @deprecated export interface MicrosoftGraphOrgEntityProviderLegacyOptions { groupTransformer?: GroupTransformer; diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 65a58e2620..e1d0ede5fc 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "alphaTypes": "dist/index.alpha.d.ts", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin-module" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -59,7 +70,6 @@ "msw": "^0.49.0" }, "files": [ - "alpha", "config.d.ts", "dist" ], diff --git a/plugins/catalog-backend-module-msgraph/src/alpha.ts b/plugins/catalog-backend-module-msgraph/src/alpha.ts new file mode 100644 index 0000000000..137808d881 --- /dev/null +++ b/plugins/catalog-backend-module-msgraph/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { microsoftGraphOrgEntityProviderCatalogModule } from './service/MicrosoftGraphOrgEntityProviderCatalogModule'; +export type { MicrosoftGraphOrgEntityProviderCatalogModuleOptions } from './service/MicrosoftGraphOrgEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-msgraph/src/index.ts b/plugins/catalog-backend-module-msgraph/src/index.ts index b80a0b3863..f98cb907ec 100644 --- a/plugins/catalog-backend-module-msgraph/src/index.ts +++ b/plugins/catalog-backend-module-msgraph/src/index.ts @@ -22,5 +22,3 @@ export * from './microsoftGraph'; export * from './processors'; -export { microsoftGraphOrgEntityProviderCatalogModule } from './service/MicrosoftGraphOrgEntityProviderCatalogModule'; -export type { MicrosoftGraphOrgEntityProviderCatalogModuleOptions } from './service/MicrosoftGraphOrgEntityProviderCatalogModule'; diff --git a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.test.ts index 27ae5b9dd8..3763553162 100644 --- a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.test.ts @@ -22,7 +22,7 @@ import { } from '@backstage/backend-tasks'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; import { microsoftGraphOrgEntityProviderCatalogModule } from './MicrosoftGraphOrgEntityProviderCatalogModule'; import { MicrosoftGraphOrgEntityProvider } from '../processors'; diff --git a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts index fc63867a23..5cad504829 100644 --- a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts @@ -19,7 +19,7 @@ import { createBackendModule, } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { GroupTransformer, OrganizationTransformer, From c64fcc84437eac065ae3845c4c56518cd3aedbb8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 10:37:24 +0100 Subject: [PATCH 340/417] catalog-backend: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/catalog-backend/alpha-api-report.md | 154 ++++++++++++++++++ plugins/catalog-backend/api-report.md | 141 +--------------- plugins/catalog-backend/package.json | 22 ++- plugins/catalog-backend/src/alpha.ts | 18 ++ plugins/catalog-backend/src/index.ts | 1 - .../src/permissions/conditionExports.ts | 2 +- .../permissions/rules/createPropertyRule.ts | 2 +- .../src/permissions/rules/hasAnnotation.ts | 2 +- .../src/permissions/rules/hasLabel.ts | 2 +- .../src/permissions/rules/isEntityKind.ts | 2 +- .../src/permissions/rules/isEntityOwner.ts | 2 +- .../src/permissions/rules/util.ts | 2 +- .../src/search/DefaultCatalogCollator.ts | 6 +- .../search/DefaultCatalogCollatorFactory.ts | 6 +- .../src/service/AuthorizedEntitiesCatalog.ts | 2 +- .../src/service/AuthorizedLocationService.ts | 2 +- .../src/service/AuthorizedRefreshService.ts | 2 +- .../src/service/CatalogBuilder.ts | 24 ++- .../src/service/CatalogPlugin.ts | 4 +- .../src/service/createRouter.test.ts | 2 +- plugins/catalog-backend/src/service/index.ts | 6 +- 21 files changed, 229 insertions(+), 175 deletions(-) create mode 100644 plugins/catalog-backend/alpha-api-report.md create mode 100644 plugins/catalog-backend/src/alpha.ts diff --git a/plugins/catalog-backend/alpha-api-report.md b/plugins/catalog-backend/alpha-api-report.md new file mode 100644 index 0000000000..6a40829d64 --- /dev/null +++ b/plugins/catalog-backend/alpha-api-report.md @@ -0,0 +1,154 @@ +## API Report File for "@backstage/plugin-catalog-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; +import { Conditions } from '@backstage/plugin-permission-node'; +import { Entity } from '@backstage/catalog-model'; +import { PermissionCondition } from '@backstage/plugin-permission-common'; +import { PermissionCriteria } from '@backstage/plugin-permission-common'; +import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; +import { ResourcePermission } from '@backstage/plugin-permission-common'; + +// @alpha +export const catalogConditions: Conditions<{ + hasAnnotation: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + value?: string | undefined; + annotation: string; + } + >; + hasLabel: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + label: string; + } + >; + hasMetadata: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + value?: string | undefined; + key: string; + } + >; + hasSpec: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + value?: string | undefined; + key: string; + } + >; + isEntityKind: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + kinds: string[]; + } + >; + isEntityOwner: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + claims: string[]; + } + >; +}>; + +// @alpha +export type CatalogPermissionRule< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule; + +// @alpha +export const catalogPlugin: () => BackendFeature; + +// @alpha +export const createCatalogConditionalDecision: ( + permission: ResourcePermission<'catalog-entity'>, + conditions: PermissionCriteria< + PermissionCondition<'catalog-entity', PermissionRuleParams> + >, +) => ConditionalPolicyDecision; + +// @alpha +export const createCatalogPermissionRule: < + TParams extends PermissionRuleParams = undefined, +>( + rule: PermissionRule, +) => PermissionRule; + +// @alpha +export const permissionRules: { + hasAnnotation: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + value?: string | undefined; + annotation: string; + } + >; + hasLabel: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + label: string; + } + >; + hasMetadata: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + value?: string | undefined; + key: string; + } + >; + hasSpec: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + value?: string | undefined; + key: string; + } + >; + isEntityKind: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + kinds: string[]; + } + >; + isEntityOwner: PermissionRule< + Entity, + EntitiesSearchFilter, + 'catalog-entity', + { + claims: string[]; + } + >; +}; + +// Warnings were encountered during analysis: +// +// src/permissions/conditionExports.d.ts:8:5 - (ae-forgotten-export) The symbol "EntitiesSearchFilter" needs to be exported by the entry point alpha.d.ts + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index f15f6b9ba9..00c13a31ea 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -10,7 +10,6 @@ import { AnalyzeLocationExistingEntity as AnalyzeLocationExistingEntity_2 } from import { AnalyzeLocationGenerateEntity as AnalyzeLocationGenerateEntity_2 } from '@backstage/plugin-catalog-common'; import { AnalyzeLocationRequest as AnalyzeLocationRequest_2 } from '@backstage/plugin-catalog-common'; import { AnalyzeLocationResponse as AnalyzeLocationResponse_2 } from '@backstage/plugin-catalog-common'; -import { BackendFeature } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; import { CatalogProcessor } from '@backstage/plugin-catalog-node'; @@ -23,8 +22,6 @@ import { CatalogProcessorParser } from '@backstage/plugin-catalog-node'; import { CatalogProcessorRefreshKeysResult } from '@backstage/plugin-catalog-node'; import { CatalogProcessorRelationResult } from '@backstage/plugin-catalog-node'; import { CatalogProcessorResult } from '@backstage/plugin-catalog-node'; -import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; -import { Conditions } from '@backstage/plugin-permission-node'; import { Config } from '@backstage/config'; import { DeferredEntity } from '@backstage/plugin-catalog-node'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; @@ -41,8 +38,6 @@ import { LocationSpec as LocationSpec_2 } from '@backstage/plugin-catalog-common import { Logger } from 'winston'; import { Permission } from '@backstage/plugin-permission-common'; import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; -import { PermissionCondition } from '@backstage/plugin-permission-common'; -import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; @@ -50,7 +45,6 @@ import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { processingResult } from '@backstage/plugin-catalog-node'; import { Readable } from 'stream'; -import { ResourcePermission } from '@backstage/plugin-permission-common'; import { Router } from 'express'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { TokenManager } from '@backstage/backend-common'; @@ -128,10 +122,9 @@ export class CatalogBuilder { addLocationAnalyzers( ...analyzers: Array> ): CatalogBuilder; - // @alpha addPermissionRules( ...permissionRules: Array< - CatalogPermissionRule | Array + CatalogPermissionRuleInput | Array > ): this; addProcessor( @@ -172,61 +165,6 @@ export type CatalogCollatorEntityTransformer = ( entity: Entity, ) => Omit; -// @alpha -export const catalogConditions: Conditions<{ - hasAnnotation: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - value?: string | undefined; - annotation: string; - } - >; - hasLabel: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - label: string; - } - >; - hasMetadata: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - value?: string | undefined; - key: string; - } - >; - hasSpec: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - value?: string | undefined; - key: string; - } - >; - isEntityKind: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - kinds: string[]; - } - >; - isEntityOwner: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - claims: string[]; - } - >; -}>; - // @public (undocumented) export type CatalogEnvironment = { logger: Logger; @@ -236,14 +174,11 @@ export type CatalogEnvironment = { permissions: PermissionEvaluator | PermissionAuthorizer; }; -// @alpha -export type CatalogPermissionRule< +// @public +export type CatalogPermissionRuleInput< TParams extends PermissionRuleParams = PermissionRuleParams, > = PermissionRule; -// @alpha -export const catalogPlugin: () => BackendFeature; - // @public export interface CatalogProcessingEngine { // (undocumented) @@ -293,21 +228,6 @@ export class CodeOwnersProcessor implements CatalogProcessor { preProcessEntity(entity: Entity, location: LocationSpec_2): Promise; } -// @alpha -export const createCatalogConditionalDecision: ( - permission: ResourcePermission<'catalog-entity'>, - conditions: PermissionCriteria< - PermissionCondition<'catalog-entity', PermissionRuleParams> - >, -) => ConditionalPolicyDecision; - -// @alpha -export const createCatalogPermissionRule: < - TParams extends PermissionRuleParams = undefined, ->( - rule: PermissionRule, -) => PermissionRule; - // @public export function createRandomProcessingInterval(options: { minSeconds: number; @@ -466,61 +386,6 @@ export function parseEntityYaml( location: LocationSpec_2, ): Iterable; -// @alpha -export const permissionRules: { - hasAnnotation: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - value?: string | undefined; - annotation: string; - } - >; - hasLabel: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - label: string; - } - >; - hasMetadata: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - value?: string | undefined; - key: string; - } - >; - hasSpec: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - value?: string | undefined; - key: string; - } - >; - isEntityKind: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - kinds: string[]; - } - >; - isEntityOwner: PermissionRule< - Entity, - EntitiesSearchFilter, - 'catalog-entity', - { - claims: string[]; - } - >; -}; - // @public export class PlaceholderProcessor implements CatalogProcessor { constructor(options: PlaceholderProcessorOptions); diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 297242d6e8..468cc13b34 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -88,7 +99,6 @@ }, "files": [ "dist", - "alpha", "migrations/**/*.{js,d.ts}", "config.d.ts" ], diff --git a/plugins/catalog-backend/src/alpha.ts b/plugins/catalog-backend/src/alpha.ts new file mode 100644 index 0000000000..51a6a72923 --- /dev/null +++ b/plugins/catalog-backend/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './permissions'; +export { catalogPlugin } from './service/CatalogPlugin'; diff --git a/plugins/catalog-backend/src/index.ts b/plugins/catalog-backend/src/index.ts index 000dd94e8b..e52336f036 100644 --- a/plugins/catalog-backend/src/index.ts +++ b/plugins/catalog-backend/src/index.ts @@ -42,7 +42,6 @@ export { processingResult } from '@backstage/plugin-catalog-node'; export * from './catalog'; export * from './ingestion'; export * from './modules'; -export * from './permissions'; export * from './processing'; export * from './search'; export * from './service'; diff --git a/plugins/catalog-backend/src/permissions/conditionExports.ts b/plugins/catalog-backend/src/permissions/conditionExports.ts index 1c1ba70631..c9406cdc0e 100644 --- a/plugins/catalog-backend/src/permissions/conditionExports.ts +++ b/plugins/catalog-backend/src/permissions/conditionExports.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { createConditionExports } from '@backstage/plugin-permission-node'; import { permissionRules } from './rules'; diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts index fd51a1a060..73f40da8c8 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts @@ -15,7 +15,7 @@ */ import { get } from 'lodash'; -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { createCatalogPermissionRule } from './util'; import { z } from 'zod'; diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts index ae9b1c3963..315d7fa8d0 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { z } from 'zod'; import { createCatalogPermissionRule } from './util'; diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts index 16c5917585..2d6289dd26 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { z } from 'zod'; import { createCatalogPermissionRule } from './util'; diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts index 94aaa63567..8ebad5521c 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { z } from 'zod'; import { EntitiesSearchFilter } from '../../catalog/types'; import { createCatalogPermissionRule } from './util'; diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts index d0cc1d9280..86493315dc 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts @@ -15,7 +15,7 @@ */ import { RELATION_OWNED_BY } from '@backstage/catalog-model'; -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { z } from 'zod'; import { createCatalogPermissionRule } from './util'; diff --git a/plugins/catalog-backend/src/permissions/rules/util.ts b/plugins/catalog-backend/src/permissions/rules/util.ts index ea25e115d2..466f5ce70b 100644 --- a/plugins/catalog-backend/src/permissions/rules/util.ts +++ b/plugins/catalog-backend/src/permissions/rules/util.ts @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { makeCreatePermissionRule, diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 70ec0ee948..42c6930422 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -29,10 +29,8 @@ import { CatalogClient, GetEntitiesRequest, } from '@backstage/catalog-client'; -import { - catalogEntityReadPermission, - CatalogEntityDocument, -} from '@backstage/plugin-catalog-common'; +import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha'; +import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; import { Permission } from '@backstage/plugin-permission-common'; /** diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollatorFactory.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollatorFactory.ts index 1c03836e51..ed81d39bbb 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollatorFactory.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollatorFactory.ts @@ -25,10 +25,8 @@ import { GetEntitiesRequest, } from '@backstage/catalog-client'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; -import { - catalogEntityReadPermission, - CatalogEntityDocument, -} from '@backstage/plugin-catalog-common'; +import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha'; +import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; import { Permission } from '@backstage/plugin-permission-common'; import { Readable } from 'stream'; import { CatalogCollatorEntityTransformer } from './CatalogCollatorEntityTransformer'; diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index c62e9f9a84..b5492e21cf 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -18,7 +18,7 @@ import { NotAllowedError } from '@backstage/errors'; import { catalogEntityDeletePermission, catalogEntityReadPermission, -} from '@backstage/plugin-catalog-common'; +} from '@backstage/plugin-catalog-common/alpha'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { AuthorizeResult, diff --git a/plugins/catalog-backend/src/service/AuthorizedLocationService.ts b/plugins/catalog-backend/src/service/AuthorizedLocationService.ts index a73597649e..68bb1553a8 100644 --- a/plugins/catalog-backend/src/service/AuthorizedLocationService.ts +++ b/plugins/catalog-backend/src/service/AuthorizedLocationService.ts @@ -21,7 +21,7 @@ import { catalogLocationCreatePermission, catalogLocationDeletePermission, catalogLocationReadPermission, -} from '@backstage/plugin-catalog-common'; +} from '@backstage/plugin-catalog-common/alpha'; import { AuthorizeResult, PermissionEvaluator, diff --git a/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts b/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts index 8634fbf86d..cbc728750a 100644 --- a/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts +++ b/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts @@ -15,7 +15,7 @@ */ import { NotAllowedError } from '@backstage/errors'; -import { catalogEntityRefreshPermission } from '@backstage/plugin-catalog-common'; +import { catalogEntityRefreshPermission } from '@backstage/plugin-catalog-common/alpha'; import { AuthorizeResult, PermissionEvaluator, diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 48bf6a08ef..b7040796f2 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -76,10 +76,10 @@ import { DefaultCatalogRulesEnforcer } from '../ingestion/CatalogRules'; import { Config } from '@backstage/config'; import { Logger } from 'winston'; import { connectEntityProviders } from '../processing/connectEntityProviders'; -import { - CatalogPermissionRule, - permissionRules as catalogPermissionRules, -} from '../permissions/rules'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; +import { EntitiesSearchFilter } from '../catalog/types'; +import { permissionRules as catalogPermissionRules } from '../permissions/rules'; +import { PermissionRule } from '@backstage/plugin-permission-node'; import { PermissionAuthorizer, PermissionEvaluator, @@ -94,11 +94,20 @@ import { basicEntityFilter } from './request/basicEntityFilter'; import { catalogPermissions, RESOURCE_TYPE_CATALOG_ENTITY, -} from '@backstage/plugin-catalog-common'; +} from '@backstage/plugin-catalog-common/alpha'; import { AuthorizedLocationService } from './AuthorizedLocationService'; import { DefaultProviderDatabase } from '../database/DefaultProviderDatabase'; import { DefaultCatalogDatabase } from '../database/DefaultCatalogDatabase'; +/** + * This is a duplicate of the alpha `CatalogPermissionRule` type, for use in the stable API. + * + * @public + */ +export type CatalogPermissionRuleInput< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule; + /** @public */ export type CatalogEnvironment = { logger: Logger; @@ -154,7 +163,7 @@ export class CatalogBuilder { maxSeconds: 150, }); private locationAnalyzer: LocationAnalyzer | undefined = undefined; - private readonly permissionRules: CatalogPermissionRule[]; + private readonly permissionRules: CatalogPermissionRuleInput[]; private allowedLocationType: string[]; private legacySingleProcessorValidation = false; @@ -379,11 +388,10 @@ export class CatalogBuilder { * {@link @backstage/plugin-permission-node#PermissionRule}. * * @param permissionRules - Additional permission rules - * @alpha */ addPermissionRules( ...permissionRules: Array< - CatalogPermissionRule | Array + CatalogPermissionRuleInput | Array > ) { this.permissionRules.push(...permissionRules.flat()); diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index 5abb630668..a6b164001c 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -19,9 +19,11 @@ import { } from '@backstage/backend-plugin-api'; import { CatalogBuilder } from './CatalogBuilder'; import { - CatalogProcessor, CatalogProcessingExtensionPoint, catalogProcessingExtensionPoint, +} from '@backstage/plugin-catalog-node/alpha'; +import { + CatalogProcessor, EntityProvider, } from '@backstage/plugin-catalog-node'; import { loggerToWinstonLogger } from '@backstage/backend-common'; diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 6379d65043..2fa06f8694 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -34,7 +34,7 @@ import { createPermissionIntegrationRouter, createPermissionRule, } from '@backstage/plugin-permission-node'; -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { CatalogProcessingOrchestrator } from '../processing/types'; import { z } from 'zod'; diff --git a/plugins/catalog-backend/src/service/index.ts b/plugins/catalog-backend/src/service/index.ts index 7e0c6025c3..44645d39fe 100644 --- a/plugins/catalog-backend/src/service/index.ts +++ b/plugins/catalog-backend/src/service/index.ts @@ -14,6 +14,8 @@ * limitations under the License. */ -export type { CatalogEnvironment } from './CatalogBuilder'; +export type { + CatalogEnvironment, + CatalogPermissionRuleInput, +} from './CatalogBuilder'; export { CatalogBuilder } from './CatalogBuilder'; -export { catalogPlugin } from './CatalogPlugin'; From dcc79493bfaa99d26422e0eae0ae870cf7dc20bd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 10:41:48 +0100 Subject: [PATCH 341/417] app-backend: migrate to use exports Signed-off-by: Patrik Oldsberg --- plugins/app-backend/alpha-api-report.md | 21 +++++++++++++++++++++ plugins/app-backend/api-report.md | 12 ------------ plugins/app-backend/package.json | 22 ++++++++++++++++------ plugins/app-backend/src/alpha.ts | 18 ++++++++++++++++++ plugins/app-backend/src/index.ts | 2 -- 5 files changed, 55 insertions(+), 20 deletions(-) create mode 100644 plugins/app-backend/alpha-api-report.md create mode 100644 plugins/app-backend/src/alpha.ts diff --git a/plugins/app-backend/alpha-api-report.md b/plugins/app-backend/alpha-api-report.md new file mode 100644 index 0000000000..20a2902557 --- /dev/null +++ b/plugins/app-backend/alpha-api-report.md @@ -0,0 +1,21 @@ +## API Report File for "@backstage/plugin-app-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import express from 'express'; + +// @alpha +export const appPlugin: (options: AppPluginOptions) => BackendFeature; + +// @alpha (undocumented) +export type AppPluginOptions = { + appPackageName?: string; + staticFallbackHandler?: express.Handler; + disableConfigInjection?: boolean; + disableStaticFallbackCache?: boolean; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/app-backend/api-report.md b/plugins/app-backend/api-report.md index b52132ef51..0383129823 100644 --- a/plugins/app-backend/api-report.md +++ b/plugins/app-backend/api-report.md @@ -3,23 +3,11 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; -// @alpha -export const appPlugin: (options: AppPluginOptions) => BackendFeature; - -// @alpha (undocumented) -export type AppPluginOptions = { - appPackageName?: string; - staticFallbackHandler?: express.Handler; - disableConfigInjection?: boolean; - disableStaticFallbackCache?: boolean; -}; - // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 4b8f4ece73..d52ab37abe 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -6,10 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "backend-plugin" @@ -25,7 +36,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -63,7 +74,6 @@ }, "files": [ "dist", - "alpha", "migrations/**/*.{js,d.ts}", "static" ] diff --git a/plugins/app-backend/src/alpha.ts b/plugins/app-backend/src/alpha.ts new file mode 100644 index 0000000000..cc8276b853 --- /dev/null +++ b/plugins/app-backend/src/alpha.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { appPlugin } from './service/appPlugin'; +export type { AppPluginOptions } from './service/appPlugin'; diff --git a/plugins/app-backend/src/index.ts b/plugins/app-backend/src/index.ts index 167dc041fc..c91416eac1 100644 --- a/plugins/app-backend/src/index.ts +++ b/plugins/app-backend/src/index.ts @@ -21,5 +21,3 @@ */ export * from './service/router'; -export { appPlugin } from './service/appPlugin'; -export type { AppPluginOptions } from './service/appPlugin'; From 76a21aad7e7d3aca2975585f267241e028768ec7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 10:47:31 +0100 Subject: [PATCH 342/417] test-utils: migrate to use exports Signed-off-by: Patrik Oldsberg --- packages/test-utils/alpha-api-report.md | 14 +++++++++++ packages/test-utils/api-report.md | 6 ----- packages/test-utils/package.json | 24 +++++++++++++------ packages/test-utils/src/alpha.ts | 17 +++++++++++++ .../{providers.tsx => MockPluginProvider.tsx} | 0 packages/test-utils/src/testUtils/index.tsx | 1 - 6 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 packages/test-utils/alpha-api-report.md create mode 100644 packages/test-utils/src/alpha.ts rename packages/test-utils/src/testUtils/{providers.tsx => MockPluginProvider.tsx} (100%) diff --git a/packages/test-utils/alpha-api-report.md b/packages/test-utils/alpha-api-report.md new file mode 100644 index 0000000000..3e0c4aa6c2 --- /dev/null +++ b/packages/test-utils/alpha-api-report.md @@ -0,0 +1,14 @@ +## API Report File for "@backstage/test-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { PropsWithChildren } from 'react'; + +// @alpha +export const MockPluginProvider: ({ + children, +}: PropsWithChildren<{}>) => JSX.Element; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index e11072f5a6..37650ff18a 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -26,7 +26,6 @@ import { JsonValue } from '@backstage/types'; import { MatcherFunction } from '@testing-library/react'; import { Observable } from '@backstage/types'; import { PermissionApi } from '@backstage/plugin-permission-react'; -import { PropsWithChildren } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RenderOptions } from '@testing-library/react'; @@ -167,11 +166,6 @@ export class MockPermissionApi implements PermissionApi { ): Promise; } -// @alpha -export const MockPluginProvider: ({ - children, -}: PropsWithChildren<{}>) => JSX.Element; - // @public export class MockStorageApi implements StorageApi { // (undocumented) diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 9e82ccc1d7..4148f62a3f 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -3,10 +3,21 @@ "description": "Utilities to test Backstage plugins and apps.", "version": "1.2.5", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "web-library" @@ -24,7 +35,7 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -60,7 +71,6 @@ "msw": "^0.49.0" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/packages/test-utils/src/alpha.ts b/packages/test-utils/src/alpha.ts new file mode 100644 index 0000000000..0b2a6a8d1c --- /dev/null +++ b/packages/test-utils/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './testUtils/MockPluginProvider'; diff --git a/packages/test-utils/src/testUtils/providers.tsx b/packages/test-utils/src/testUtils/MockPluginProvider.tsx similarity index 100% rename from packages/test-utils/src/testUtils/providers.tsx rename to packages/test-utils/src/testUtils/MockPluginProvider.tsx diff --git a/packages/test-utils/src/testUtils/index.tsx b/packages/test-utils/src/testUtils/index.tsx index 8fc1395eb8..1510af106e 100644 --- a/packages/test-utils/src/testUtils/index.tsx +++ b/packages/test-utils/src/testUtils/index.tsx @@ -25,7 +25,6 @@ export { export type { TestAppOptions } from './appWrappers'; export * from './msw'; export * from './logCollector'; -export * from './providers'; export * from './testingLibrary'; export { TestApiProvider, TestApiRegistry } from './TestApiProvider'; export type { TestApiProviderProps } from './TestApiProvider'; From 7b76628a6a03729cb9c48f9cded6495c7fc51653 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 10:54:24 +0100 Subject: [PATCH 343/417] core-plugin-api: migrate to use exports Signed-off-by: Patrik Oldsberg --- packages/core-plugin-api/alpha-api-report.md | 27 ++++++++++++++++++++ packages/core-plugin-api/api-report.md | 16 ------------ packages/core-plugin-api/package.json | 24 ++++++++++++----- packages/core-plugin-api/src/alpha.ts | 17 ++++++++++++ packages/core-plugin-api/src/index.ts | 1 - 5 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 packages/core-plugin-api/alpha-api-report.md create mode 100644 packages/core-plugin-api/src/alpha.ts diff --git a/packages/core-plugin-api/alpha-api-report.md b/packages/core-plugin-api/alpha-api-report.md new file mode 100644 index 0000000000..b66fee8207 --- /dev/null +++ b/packages/core-plugin-api/alpha-api-report.md @@ -0,0 +1,27 @@ +## API Report File for "@backstage/core-plugin-api" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ReactNode } from 'react'; + +// @alpha +export interface PluginOptionsProviderProps { + // (undocumented) + children: ReactNode; + // Warning: (ae-forgotten-export) The symbol "BackstagePlugin" needs to be exported by the entry point alpha.d.ts + // + // (undocumented) + plugin?: BackstagePlugin; +} + +// @alpha +export const PluginProvider: (props: PluginOptionsProviderProps) => JSX.Element; + +// @alpha +export function usePluginOptions< + TPluginOptions extends {} = {}, +>(): TPluginOptions; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index 91f05921bf..4887f0b7f2 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -649,17 +649,6 @@ export type PluginFeatureFlagConfig = { name: string; }; -// @alpha -export interface PluginOptionsProviderProps { - // (undocumented) - children: ReactNode; - // (undocumented) - plugin?: BackstagePlugin; -} - -// @alpha -export const PluginProvider: (props: PluginOptionsProviderProps) => JSX.Element; - // @public export type ProfileInfo = { email?: string; @@ -760,11 +749,6 @@ export function useElementFilter( dependencies?: any[], ): T; -// @alpha -export function usePluginOptions< - TPluginOptions extends {} = {}, ->(): TPluginOptions; - // @public export function useRouteRef( routeRef: ExternalRouteRef, diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index f1f023eedb..e01c99f384 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -3,10 +3,21 @@ "description": "Core API used by Backstage plugins", "version": "1.4.0", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "web-library" @@ -24,7 +35,7 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -60,7 +71,6 @@ "msw": "^0.49.0" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/packages/core-plugin-api/src/alpha.ts b/packages/core-plugin-api/src/alpha.ts new file mode 100644 index 0000000000..09983a48e9 --- /dev/null +++ b/packages/core-plugin-api/src/alpha.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './plugin-options'; diff --git a/packages/core-plugin-api/src/index.ts b/packages/core-plugin-api/src/index.ts index e8edd38ff3..30fc35b62a 100644 --- a/packages/core-plugin-api/src/index.ts +++ b/packages/core-plugin-api/src/index.ts @@ -22,7 +22,6 @@ export * from './analytics'; export * from './apis'; -export * from './plugin-options'; export * from './app'; export * from './extensions'; export * from './icons'; From 4a12dbbc45794a9a7cf9a1b38ba9f9997662c602 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 10:57:00 +0100 Subject: [PATCH 344/417] catalog-model: migrate to use exports Signed-off-by: Patrik Oldsberg --- packages/catalog-model/alpha-api-report.md | 34 +++++++++++++++++ packages/catalog-model/api-report.md | 22 ----------- packages/catalog-model/package.json | 25 +++++++++---- packages/catalog-model/src/alpha.ts | 22 +++++++++++ .../catalog-model/src/entity/AlphaEntity.ts | 37 +++++++++++++++++++ packages/catalog-model/src/entity/Entity.ts | 20 ---------- packages/catalog-model/src/entity/index.ts | 13 +------ 7 files changed, 111 insertions(+), 62 deletions(-) create mode 100644 packages/catalog-model/alpha-api-report.md create mode 100644 packages/catalog-model/src/alpha.ts create mode 100644 packages/catalog-model/src/entity/AlphaEntity.ts diff --git a/packages/catalog-model/alpha-api-report.md b/packages/catalog-model/alpha-api-report.md new file mode 100644 index 0000000000..639cba1fef --- /dev/null +++ b/packages/catalog-model/alpha-api-report.md @@ -0,0 +1,34 @@ +## API Report File for "@backstage/catalog-model" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { JsonObject } from '@backstage/types'; +import { SerializedError } from '@backstage/errors'; + +// Warning: (ae-forgotten-export) The symbol "Entity" needs to be exported by the entry point alpha.d.ts +// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/catalog-model" does not have an export "Entity" +// +// @alpha +export interface AlphaEntity extends Entity { + status?: EntityStatus; +} + +// @alpha +export type EntityStatus = { + items?: EntityStatusItem[]; +}; + +// @alpha +export type EntityStatusItem = { + type: string; + level: EntityStatusLevel; + message: string; + error?: SerializedError; +}; + +// @alpha +export type EntityStatusLevel = 'info' | 'warning' | 'error'; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index 15eec90f09..b8eb20c590 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -4,12 +4,6 @@ ```ts import { JsonObject } from '@backstage/types'; -import { SerializedError } from '@backstage/errors'; - -// @alpha -export interface AlphaEntity extends Entity { - status?: EntityStatus; -} // @public export const ANNOTATION_EDIT_URL = 'backstage.io/edit-url'; @@ -209,22 +203,6 @@ export function entitySchemaValidator( schema?: unknown, ): (data: unknown) => T; -// @alpha -export type EntityStatus = { - items?: EntityStatusItem[]; -}; - -// @alpha -export type EntityStatusItem = { - type: string; - level: EntityStatusLevel; - message: string; - error?: SerializedError; -}; - -// @alpha -export type EntityStatusLevel = 'info' | 'warning' | 'error'; - // @public export class FieldFormatEntityPolicy implements EntityPolicy { constructor(validators?: Validators); diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 00f9543f52..b07e2df915 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -6,11 +6,21 @@ "types": "src/index.ts", "license": "Apache-2.0", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "module": "dist/index.esm.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ], + "alpha": [ + "src/alpha.ts" + ] + } }, "backstage": { "role": "common-library" @@ -25,7 +35,7 @@ "backstage" ], "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -48,7 +58,6 @@ "yaml": "^2.0.0" }, "files": [ - "dist", - "alpha" + "dist" ] } diff --git a/packages/catalog-model/src/alpha.ts b/packages/catalog-model/src/alpha.ts new file mode 100644 index 0000000000..1d29c97464 --- /dev/null +++ b/packages/catalog-model/src/alpha.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type { + EntityStatus, + EntityStatusItem, + EntityStatusLevel, +} from './entity/EntityStatus'; +export type { AlphaEntity } from './entity/AlphaEntity'; diff --git a/packages/catalog-model/src/entity/AlphaEntity.ts b/packages/catalog-model/src/entity/AlphaEntity.ts new file mode 100644 index 0000000000..57a1954f52 --- /dev/null +++ b/packages/catalog-model/src/entity/AlphaEntity.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity } from './Entity'; +import { EntityStatus } from './EntityStatus'; + +/** + * A version of the {@link Entity} type that contains unstable alpha fields. + * + * @remarks + * + * Available via the `@backstage/catalog-model/alpha` import. + * + * @alpha + */ +export interface AlphaEntity extends Entity { + /** + * The current status of the entity, as claimed by various sources. + * + * The keys are implementation defined and the values can be any JSON object + * with semantics that match that implementation. + */ + status?: EntityStatus; +} diff --git a/packages/catalog-model/src/entity/Entity.ts b/packages/catalog-model/src/entity/Entity.ts index 80c9adaffb..8d36fe0134 100644 --- a/packages/catalog-model/src/entity/Entity.ts +++ b/packages/catalog-model/src/entity/Entity.ts @@ -15,7 +15,6 @@ */ import { JsonObject } from '@backstage/types'; -import { EntityStatus } from './EntityStatus'; /** * The parts of the format that's common to all versions/kinds of entity. @@ -54,25 +53,6 @@ export type Entity = { relations?: EntityRelation[]; }; -/** - * A version of the {@link Entity} type that contains unstable alpha fields. - * - * @remarks - * - * Available via the `@backstage/catalog-model/alpha` import. - * - * @alpha - */ -export interface AlphaEntity extends Entity { - /** - * The current status of the entity, as claimed by various sources. - * - * The keys are implementation defined and the values can be any JSON object - * with semantics that match that implementation. - */ - status?: EntityStatus; -} - /** * Metadata fields common to all versions/kinds of entity. * diff --git a/packages/catalog-model/src/entity/index.ts b/packages/catalog-model/src/entity/index.ts index 87f414cc9c..269d56ec86 100644 --- a/packages/catalog-model/src/entity/index.ts +++ b/packages/catalog-model/src/entity/index.ts @@ -16,19 +16,8 @@ export * from './conditions'; export * from './constants'; -export type { - AlphaEntity, - Entity, - EntityLink, - EntityMeta, - EntityRelation, -} from './Entity'; +export type { Entity, EntityLink, EntityMeta, EntityRelation } from './Entity'; export type { EntityEnvelope } from './EntityEnvelope'; -export type { - EntityStatus, - EntityStatusItem, - EntityStatusLevel, -} from './EntityStatus'; export * from './policies'; export { getCompoundEntityRef, From 03104255933339aabc8568788dffb13ee256ef06 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 10:59:35 +0100 Subject: [PATCH 345/417] backend-test-utils: migrate to use exports Signed-off-by: Patrik Oldsberg --- packages/backend-test-utils/package.json | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index a6f02257d8..6330b161e1 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -5,10 +5,17 @@ "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts", - "alphaTypes": "dist/index.alpha.d.ts" + "access": "public" + }, + "exports": { + ".": "./src/index.ts" + }, + "typesVersions": { + "*": { + "*": [ + "src/index.ts" + ] + } }, "backstage": { "role": "node-library" @@ -25,7 +32,7 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli package build --experimental-type-build", + "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -55,7 +62,6 @@ "supertest": "^6.1.3" }, "files": [ - "dist", - "alpha" + "dist" ] } From 8d14fb7a9b8a120b578d2ecec88f3a744c2661da Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 13:03:57 +0100 Subject: [PATCH 346/417] docs: document sub-path exports Signed-off-by: Patrik Oldsberg --- docs/local-dev/cli-build-system.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index cf8ac626b9..a784e0eff9 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -650,8 +650,34 @@ The following is an excerpt of a typical setup of an isomorphic library package: "files": ["dist"], ``` +## Sub-path Exports + +The Backstage CLI supports implementation of sub-path exports through the `"exports"` field in `package.json`. It might for example look like this: + +```json + "name": "@backstage/plugin-foo", + "exports": { + ".": "./src/index.ts", + "./components": "./src/components.ts", + }, +``` + +This in turn would allow you to import anything exported in `src/index.ts` via `@backstage/plugins-foo`, and `src/components.ts` via `@backstage/plugins-foo/components`. Note that patterns are not supported, meaning the exports may not contain `*` wildcards. + +As with the rest of the Backstage CLI build system, the setup is optimized for local development, which is why the `"exports"` targets point directly to source files. The `package build` command will detect the `"exports"` field and automatically generate the corresponding `dist` files, and the `prepublish` command will rewrite the `"exports"` field to point to the `dist` files, as well as generating folder-based entry points for backwards compatibility. + +TypeScript support is currently handled though the `typesVersions` field, as there is not yet a module resolution mode that works well with `"exports"`. You can craft the `typesVersions` yourself, but it will also be automatically generated by the `migrate package-exports` command. + +To add sub-path exports to an existing package, simply add the desired `"exports"` fields and then run the following command: + +```bash +yarn backstage-cli package migrate package-exports +``` + ## Experimental Type Build +> Note: Experimental type builds are deprecated and will be removed in the future. They have been replaced by [sub-path exports](#sub-path-exports). + The Backstage CLI has an experimental feature where multiple different type definition files can be generated for different release stages. The release stages are marked in the [TSDoc](https://tsdoc.org/) for each individual export, using either `@public`, `@alpha`, or `@beta`. Rather than just building a single `index.d.ts` file, the build process will instead output `index.d.ts`, `index.beta.d.ts`, and `index.alpha.d.ts`. Each of these files will have exports from more unstable release stages stripped, meaning that `index.d.ts` will omit all exports marked with `@alpha` or `@beta`, while `index.beta.d.ts` will omit all exports marked with `@alpha`. This feature is aimed at projects that publish to package registries and wish to maintain different levels of API stability within each package. There is no need to use this within a single monorepo, as it has no effect due to only applying to built and published packages. From 55937a25ae24a303cb1811c09b1ba16587079c75 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 13:06:33 +0100 Subject: [PATCH 347/417] prettier: ignore *-api-report.md Signed-off-by: Patrik Oldsberg --- .prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.prettierignore b/.prettierignore index 8f1fae0456..ad2bd355ed 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,6 +5,7 @@ coverage *.hbs templates api-report.md +*-api-report.md cli-report.md plugins/scaffolder-backend/sample-templates .vscode From 57934df9848f0e211d38e39a1438bff0da7c2dba Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 16 Jan 2023 23:06:59 +0100 Subject: [PATCH 348/417] repo-tools: fix warning counter for non-index API reports Signed-off-by: Patrik Oldsberg --- .../src/commands/api-reports/api-extractor.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index 91df053f22..c05fd0a01e 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -237,10 +237,9 @@ export async function createTemporaryTsConfig(includedPackageDirs: string[]) { return path; } -export async function countApiReportWarnings(projectFolder: string) { - const path = resolvePath(projectFolder, 'api-report.md'); +export async function countApiReportWarnings(reportPath: string) { try { - const content = await fs.readFile(path, 'utf8'); + const content = await fs.readFile(reportPath, 'utf8'); const lines = content.split('\n'); const lineWarnings = lines.filter(line => @@ -380,9 +379,12 @@ export async function runApiExtraction({ packageDir, ); - const warningCountBefore = await countApiReportWarnings(projectFolder); - const prefix = name === 'index' ? '' : `${name}-`; + const reportFileName = `${prefix}api-report.md`; + const reportPath = resolvePath(projectFolder, reportFileName); + + const warningCountBefore = await countApiReportWarnings(reportPath); + const extractorConfig = ExtractorConfig.prepare({ configObject: { mainEntryPointFilePath: resolvePath(packageFolder, `src/${name}.d.ts`), @@ -394,7 +396,7 @@ export async function runApiExtraction({ apiReport: { enabled: true, - reportFileName: `${prefix}api-report.md`, + reportFileName, reportFolder: projectFolder, reportTempFolder: resolvePath( outputDir, @@ -547,7 +549,7 @@ export async function runApiExtraction({ ); } - const warningCountAfter = await countApiReportWarnings(projectFolder); + const warningCountAfter = await countApiReportWarnings(reportPath); if (noBail) { console.log(`Skipping warnings check for ${packageDir}`); } From 556df7ff0c2dfb07afa11933855c6f8c942e212b Mon Sep 17 00:00:00 2001 From: djamaile Date: Tue, 21 Feb 2023 14:36:29 +0100 Subject: [PATCH 349/417] fix: only run changeset action if target is master Signed-off-by: djamaile --- .github/workflows/automate_changeset_feedback.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index d1dcd97644..f96a9fbb39 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -1,6 +1,7 @@ name: Automate changeset feedback on: pull_request_target: + branches: ['master'] permissions: pull-requests: write From 61055f106b011eb1364dfc0df0fc30d4ad0996af Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 09:43:21 +0100 Subject: [PATCH 350/417] update /alpha imports to fix all type issues Signed-off-by: Patrik Oldsberg --- docs/local-dev/cli-commands.md | 1 - packages/app/src/App.tsx | 4 ++-- .../components/scaffolder/customScaffolderExtensions.tsx | 3 ++- packages/backend-defaults/src/CreateBackend.test.ts | 2 +- packages/backend-next/src/index.ts | 6 +++--- packages/cli/src/commands/index.ts | 2 +- packages/test-utils/src/testUtils/MockPluginProvider.tsx | 3 ++- .../BitbucketCloudEntityProviderCatalogModule.test.ts | 5 ++++- .../src/run.ts | 2 +- plugins/catalog-backend/src/stitching/Stitcher.ts | 3 +-- .../InspectEntityDialog/components/OverviewPage.tsx | 2 +- plugins/catalog-react/src/filters.test.ts | 3 ++- plugins/catalog-react/src/filters.ts | 7 ++----- .../catalog-react/src/hooks/useEntityPermission.test.tsx | 2 +- .../components/CatalogPage/DefaultCatalogPage.test.tsx | 2 +- .../components/EntityContextMenu/EntityContextMenu.tsx | 4 ++-- .../EntityProcessingErrorsPanel.test.tsx | 3 ++- .../EntityProcessingErrorsPanel.tsx | 8 ++------ plugins/catalog/src/options.ts | 2 +- .../components/CostOverviewCard/CostOverviewCard.test.tsx | 3 ++- .../src/components/EntityCosts/EntityCost.test.tsx | 7 ++----- plugins/cost-insights/src/options.ts | 2 +- plugins/jenkins-common/src/permissions.ts | 2 +- .../src/components/BuildsPage/lib/CITable/CITable.tsx | 2 +- plugins/scaffolder-backend/src/ScaffolderPlugin.ts | 2 +- .../src/modules/catalogModuleTemplateKind.test.ts | 2 +- .../src/modules/catalogModuleTemplateKind.ts | 2 +- .../src/components/ScaffolderPage/ScaffolderPage.tsx | 2 +- .../src/next/TemplateListPage/RegisterExistingButton.tsx | 2 +- plugins/sonarqube/dev/index.tsx | 4 ++-- plugins/sonarqube/src/api/SonarQubeClient.test.ts | 2 +- plugins/sonarqube/src/api/SonarQubeClient.ts | 2 +- plugins/sonarqube/src/api/types.ts | 6 ++++-- .../src/components/SonarQubeCard/SonarQubeCard.tsx | 4 ++-- .../SonarQubeContentPage/SonarQubeContentPage.test.tsx | 6 ++++-- plugins/sonarqube/src/plugin.ts | 2 +- .../src/search/DefaultTechDocsCollator.ts | 2 +- .../src/search/DefaultTechDocsCollatorFactory.ts | 2 +- 38 files changed, 60 insertions(+), 60 deletions(-) diff --git a/docs/local-dev/cli-commands.md b/docs/local-dev/cli-commands.md index b43825d733..e34dd63295 100644 --- a/docs/local-dev/cli-commands.md +++ b/docs/local-dev/cli-commands.md @@ -120,7 +120,6 @@ Build a package for production deployment or publishing Options: --role <name> Run the command with an explicit package role --minify Minify the generated code. Does not apply to app or backend packages. - --experimental-type-build Enable experimental type build. Does not apply to app or backend packages. --skip-build-dependencies Skip the automatic building of local dependencies. Applies to backend packages only. --stats If bundle stats are available, write them to the output directory. Applies to app packages only. --config <path> Config files to load instead of app-config.yaml. Applies to app packages only. (default: []) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index dfd2437b6b..4dacbbc007 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -59,9 +59,9 @@ import { GraphiQLPage } from '@backstage/plugin-graphiql'; import { HomepageCompositionRoot } from '@backstage/plugin-home'; import { LighthousePage } from '@backstage/plugin-lighthouse'; import { NewRelicPage } from '@backstage/plugin-newrelic'; +import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; import { ScaffolderPage, - NextScaffolderPage, scaffolderPlugin, ScaffolderLayouts, } from '@backstage/plugin-scaffolder'; @@ -104,7 +104,7 @@ import * as plugins from './plugins'; import { techDocsPage } from './components/techdocs/TechDocsPage'; import { ApacheAirflowPage } from '@backstage/plugin-apache-airflow'; import { RequirePermission } from '@backstage/plugin-permission-react'; -import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; +import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; import { PlaylistIndexPage } from '@backstage/plugin-playlist'; import { TwoColumnLayout } from './components/scaffolder/customScaffolderLayouts'; import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card'; diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index 8a2e7fba53..b15d12979a 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -17,10 +17,11 @@ import React from 'react'; import type { FieldValidation } from '@rjsf/utils'; import { scaffolderPlugin } from '@backstage/plugin-scaffolder'; import { TextField } from '@material-ui/core'; - import { NextFieldExtensionComponentProps, createNextScaffolderFieldExtension, +} from '@backstage/plugin-scaffolder-react/alpha'; +import { createScaffolderFieldExtension, FieldExtensionComponentProps, } from '@backstage/plugin-scaffolder-react'; diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts index 8d56cd0986..cc6c93c0eb 100644 --- a/packages/backend-defaults/src/CreateBackend.test.ts +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -21,7 +21,7 @@ import { createServiceRef, createSharedEnvironment, } from '@backstage/backend-plugin-api'; -import { mockServices } from '@backstage/backend-test-utils'; +import { mockServices } from '@backstage/backend-test-utils/alpha'; import { createBackend } from './CreateBackend'; const fooServiceRef = createServiceRef({ id: 'foo', scope: 'root' }); diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index f4979760cf..8e29244ebf 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { catalogPlugin } from '@backstage/plugin-catalog-backend'; -import { catalogModuleTemplateKind } from '@backstage/plugin-scaffolder-backend'; +import { catalogPlugin } from '@backstage/plugin-catalog-backend/alpha'; +import { catalogModuleTemplateKind } from '@backstage/plugin-scaffolder-backend/alpha'; import { createBackend } from '@backstage/backend-defaults'; -import { appPlugin } from '@backstage/plugin-app-backend'; +import { appPlugin } from '@backstage/plugin-app-backend/alpha'; import { todoPlugin } from '@backstage/plugin-todo-backend'; const backend = createBackend(); diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 2fdd2442d4..3eb511e06d 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -116,7 +116,7 @@ export function registerScriptCommand(program: Command) { ) .option( '--experimental-type-build', - 'Enable experimental type build. Does not apply to app or backend packages.', + 'Enable experimental type build. Does not apply to app or backend packages. [DEPRECATED]', ) .option( '--skip-build-dependencies', diff --git a/packages/test-utils/src/testUtils/MockPluginProvider.tsx b/packages/test-utils/src/testUtils/MockPluginProvider.tsx index 8bc4b5122d..25442ae267 100644 --- a/packages/test-utils/src/testUtils/MockPluginProvider.tsx +++ b/packages/test-utils/src/testUtils/MockPluginProvider.tsx @@ -15,7 +15,8 @@ */ import React, { PropsWithChildren } from 'react'; -import { createPlugin, PluginProvider } from '@backstage/core-plugin-api'; +import { PluginProvider } from '@backstage/core-plugin-api/alpha'; +import { createPlugin } from '@backstage/core-plugin-api'; /** * Mock for PluginProvider to use in unit tests diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts index 630c18b134..13ad5dbf22 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts @@ -19,7 +19,10 @@ import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { startTestBackend, mockServices } from '@backstage/backend-test-utils'; +import { + startTestBackend, + mockServices, +} from '@backstage/backend-test-utils/alpha'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { Duration } from 'luxon'; diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index 745fc70883..c94af368d1 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -19,7 +19,7 @@ import { createServiceFactory, } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; -import { catalogPlugin } from '@backstage/plugin-catalog-backend'; +import { catalogPlugin } from '@backstage/plugin-catalog-backend/alpha'; import { IncrementalEntityProvider } from '.'; import { incrementalIngestionEntityProviderCatalogModule } from './alpha'; diff --git a/plugins/catalog-backend/src/stitching/Stitcher.ts b/plugins/catalog-backend/src/stitching/Stitcher.ts index bdf9f8791a..38d0fd263f 100644 --- a/plugins/catalog-backend/src/stitching/Stitcher.ts +++ b/plugins/catalog-backend/src/stitching/Stitcher.ts @@ -15,12 +15,11 @@ */ import { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from '@backstage/catalog-client'; +import { AlphaEntity, EntityStatusItem } from '@backstage/catalog-model/alpha'; import { - AlphaEntity, ANNOTATION_EDIT_URL, ANNOTATION_VIEW_URL, EntityRelation, - EntityStatusItem, } from '@backstage/catalog-model'; import { SerializedError, stringifyError } from '@backstage/errors'; import { Knex } from 'knex'; diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx index f0adb878d6..09b944605f 100644 --- a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx +++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { AlphaEntity } from '@backstage/catalog-model'; +import { AlphaEntity } from '@backstage/catalog-model/alpha'; import { Box, DialogContentText, diff --git a/plugins/catalog-react/src/filters.test.ts b/plugins/catalog-react/src/filters.test.ts index c2c92e033e..2a67190633 100644 --- a/plugins/catalog-react/src/filters.test.ts +++ b/plugins/catalog-react/src/filters.test.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { AlphaEntity, Entity } from '@backstage/catalog-model'; +import { AlphaEntity } from '@backstage/catalog-model/alpha'; +import { Entity } from '@backstage/catalog-model'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { EntityErrorFilter, diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index 056b3b92c1..5bd81780d6 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -14,11 +14,8 @@ * limitations under the License. */ -import { - AlphaEntity, - Entity, - RELATION_OWNED_BY, -} from '@backstage/catalog-model'; +import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { AlphaEntity } from '@backstage/catalog-model/alpha'; import { humanizeEntityRef } from './components/EntityRefLink'; import { EntityFilter, UserListFilterKind } from './types'; import { getEntityRelations } from './utils'; diff --git a/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx b/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx index 766b587da3..aed6676838 100644 --- a/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common'; +import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common/alpha'; import { renderHook } from '@testing-library/react-hooks'; import { useEntityPermission } from './useEntityPermission'; import { useAsyncEntity } from './useEntity'; diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index 10f06ca09e..7b92df5809 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -34,9 +34,9 @@ import { MockStarredEntitiesApi, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; +import { MockPluginProvider } from '@backstage/test-utils/alpha'; import { mockBreakpoint, - MockPluginProvider, MockStorageApi, renderWithEffects, TestApiProvider, diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index d22f9bde10..675f74fa8d 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -30,8 +30,8 @@ import MoreVert from '@material-ui/icons/MoreVert'; import FileCopyTwoToneIcon from '@material-ui/icons/FileCopyTwoTone'; import React, { useCallback, useState } from 'react'; import { IconComponent } from '@backstage/core-plugin-api'; -import { useEntityPermission } from '@backstage/plugin-catalog-react'; -import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common'; +import { useEntityPermission } from '@backstage/plugin-catalog-react/alpha'; +import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common/alpha'; import { BackstageTheme } from '@backstage/theme'; import { UnregisterEntity, UnregisterEntityOptions } from './UnregisterEntity'; import { useApi, alertApiRef } from '@backstage/core-plugin-api'; diff --git a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx index 350349fe95..b21c6292ff 100644 --- a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx +++ b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.test.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ -import { AlphaEntity, stringifyEntityRef } from '@backstage/catalog-model'; +import { AlphaEntity } from '@backstage/catalog-model/alpha'; +import { stringifyEntityRef } from '@backstage/catalog-model'; import { ApiProvider } from '@backstage/core-app-api'; import { CatalogApi, diff --git a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx index 2eaf505ec0..ef91e7b26e 100644 --- a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx +++ b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx @@ -14,12 +14,8 @@ * limitations under the License. */ -import { - Entity, - AlphaEntity, - stringifyEntityRef, - EntityStatusItem, -} from '@backstage/catalog-model'; +import { AlphaEntity, EntityStatusItem } from '@backstage/catalog-model/alpha'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { catalogApiRef, EntityRefLink, diff --git a/plugins/catalog/src/options.ts b/plugins/catalog/src/options.ts index bb248c16b6..4ea6449a4b 100644 --- a/plugins/catalog/src/options.ts +++ b/plugins/catalog/src/options.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { usePluginOptions } from '@backstage/core-plugin-api'; +import { usePluginOptions } from '@backstage/core-plugin-api/alpha'; export type CatalogPluginOptions = { createButtonTitle: string; diff --git a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.test.tsx b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.test.tsx index 0a9451c794..d4fdc66bdb 100644 --- a/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.test.tsx +++ b/plugins/cost-insights/src/components/CostOverviewCard/CostOverviewCard.test.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; import { fireEvent } from '@testing-library/react'; -import { MockPluginProvider, renderInTestApp } from '@backstage/test-utils'; +import { MockPluginProvider } from '@backstage/test-utils/alpha'; +import { renderInTestApp } from '@backstage/test-utils'; import { CostOverviewCard } from './CostOverviewCard'; import { Cost } from '@backstage/plugin-cost-insights-common'; import { diff --git a/plugins/cost-insights/src/components/EntityCosts/EntityCost.test.tsx b/plugins/cost-insights/src/components/EntityCosts/EntityCost.test.tsx index f288f54e9b..6eb3369b40 100644 --- a/plugins/cost-insights/src/components/EntityCosts/EntityCost.test.tsx +++ b/plugins/cost-insights/src/components/EntityCosts/EntityCost.test.tsx @@ -14,11 +14,8 @@ * limitations under the License. */ import React from 'react'; -import { - MockPluginProvider, - renderInTestApp, - TestApiProvider, -} from '@backstage/test-utils'; +import { MockPluginProvider } from '@backstage/test-utils/alpha'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { changeOf, MockAggregatedDailyCosts, diff --git a/plugins/cost-insights/src/options.ts b/plugins/cost-insights/src/options.ts index 287935d703..acc977771d 100644 --- a/plugins/cost-insights/src/options.ts +++ b/plugins/cost-insights/src/options.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { usePluginOptions } from '@backstage/core-plugin-api'; +import { usePluginOptions } from '@backstage/core-plugin-api/alpha'; export type CostInsightsPluginOptions = { hideTrendLine?: boolean; diff --git a/plugins/jenkins-common/src/permissions.ts b/plugins/jenkins-common/src/permissions.ts index 5ca5ec6adf..311bf993cc 100644 --- a/plugins/jenkins-common/src/permissions.ts +++ b/plugins/jenkins-common/src/permissions.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common'; +import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { createPermission } from '@backstage/plugin-permission-common'; /** diff --git a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx index 0217f00513..1bb6dbaefc 100644 --- a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -15,7 +15,7 @@ */ import { Link, Progress, Table, TableColumn } from '@backstage/core-components'; import { alertApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; -import { useEntityPermission } from '@backstage/plugin-catalog-react'; +import { useEntityPermission } from '@backstage/plugin-catalog-react/alpha'; import { Box, IconButton, Tooltip, Typography } from '@material-ui/core'; import RetryIcon from '@material-ui/icons/Replay'; import { default as React, useState } from 'react'; diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 852c0f73e2..182bb60223 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -20,7 +20,7 @@ import { } from '@backstage/backend-plugin-api'; import { loggerToWinstonLogger } from '@backstage/backend-common'; import { ScmIntegrations } from '@backstage/integration'; -import { catalogServiceRef } from '@backstage/plugin-catalog-node'; +import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; import { scaffolderActionsExtensionPoint, ScaffolderActionsExtensionPoint, diff --git a/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.test.ts b/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.test.ts index 7652f60386..7b8b99f5e2 100644 --- a/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.test.ts +++ b/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { ScaffolderEntitiesProcessor } from '../processor'; import { catalogModuleTemplateKind } from './catalogModuleTemplateKind'; import { startTestBackend } from '@backstage/backend-test-utils'; diff --git a/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.ts b/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.ts index 622e5a003a..3359bd1dba 100644 --- a/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.ts +++ b/plugins/scaffolder-backend/src/modules/catalogModuleTemplateKind.ts @@ -15,7 +15,7 @@ */ import { createBackendModule } from '@backstage/backend-plugin-api'; -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { ScaffolderEntitiesProcessor } from '../processor'; /** diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 50221f3a83..e153c2e232 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -36,7 +36,7 @@ import { import React, { ComponentType } from 'react'; import { TemplateList } from '../TemplateList'; import { TemplateTypePicker } from '../TemplateTypePicker'; -import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; +import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; import { usePermission } from '@backstage/plugin-permission-react'; import { ScaffolderPageContextMenu } from './ScaffolderPageContextMenu'; import { registerComponentRouteRef } from '../../routes'; diff --git a/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx b/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx index 16e0a355a3..069a2cc6c5 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx @@ -21,7 +21,7 @@ import useMediaQuery from '@material-ui/core/useMediaQuery'; import React from 'react'; import { Link as RouterLink, LinkProps } from 'react-router-dom'; import AddCircleOutline from '@material-ui/icons/AddCircleOutline'; -import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; +import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; import { usePermission } from '@backstage/plugin-permission-react'; /** diff --git a/plugins/sonarqube/dev/index.tsx b/plugins/sonarqube/dev/index.tsx index a34c4d4e82..98c48c56fc 100644 --- a/plugins/sonarqube/dev/index.tsx +++ b/plugins/sonarqube/dev/index.tsx @@ -22,10 +22,10 @@ import { EntitySonarQubeCard, sonarQubePlugin } from '../src'; import { Content, Header, Page } from '@backstage/core-components'; import { FindingSummary, - SONARQUBE_PROJECT_KEY_ANNOTATION, SonarQubeApi, sonarQubeApiRef, -} from '@backstage/plugin-sonarqube-react'; +} from '@backstage/plugin-sonarqube-react/alpha'; +import { SONARQUBE_PROJECT_KEY_ANNOTATION } from '@backstage/plugin-sonarqube-react'; const entity = (name?: string) => ({ diff --git a/plugins/sonarqube/src/api/SonarQubeClient.test.ts b/plugins/sonarqube/src/api/SonarQubeClient.test.ts index 592f08457f..441263afc8 100644 --- a/plugins/sonarqube/src/api/SonarQubeClient.test.ts +++ b/plugins/sonarqube/src/api/SonarQubeClient.test.ts @@ -21,7 +21,7 @@ import { SonarQubeClient } from './index'; import { InstanceUrlWrapper, FindingsWrapper } from './types'; import { UrlPatternDiscovery } from '@backstage/core-app-api'; import { IdentityApi } from '@backstage/core-plugin-api'; -import { FindingSummary } from '@backstage/plugin-sonarqube-react'; +import { FindingSummary } from '@backstage/plugin-sonarqube-react/alpha'; const server = setupServer(); diff --git a/plugins/sonarqube/src/api/SonarQubeClient.ts b/plugins/sonarqube/src/api/SonarQubeClient.ts index 14c7936e92..94d7a96243 100644 --- a/plugins/sonarqube/src/api/SonarQubeClient.ts +++ b/plugins/sonarqube/src/api/SonarQubeClient.ts @@ -19,7 +19,7 @@ import { FindingSummary, Metrics, SonarQubeApi, -} from '@backstage/plugin-sonarqube-react'; +} from '@backstage/plugin-sonarqube-react/alpha'; import { InstanceUrlWrapper, FindingsWrapper } from './types'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; diff --git a/plugins/sonarqube/src/api/types.ts b/plugins/sonarqube/src/api/types.ts index 470d05903a..f3ad690261 100644 --- a/plugins/sonarqube/src/api/types.ts +++ b/plugins/sonarqube/src/api/types.ts @@ -14,8 +14,10 @@ * limitations under the License. */ -import { MetricKey as NonDeprecatedMetricKey } from '@backstage/plugin-sonarqube-react'; -import { SonarUrlProcessorFunc as NonDeprecatedSonarUrlProcessorFunc } from '@backstage/plugin-sonarqube-react'; +import { + MetricKey as NonDeprecatedMetricKey, + SonarUrlProcessorFunc as NonDeprecatedSonarUrlProcessorFunc, +} from '@backstage/plugin-sonarqube-react/alpha'; export interface InstanceUrlWrapper { instanceUrl: string; diff --git a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx index 5bd1cd8e9f..3965c03b69 100644 --- a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx +++ b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx @@ -16,10 +16,10 @@ import { useEntity } from '@backstage/plugin-catalog-react'; import { - SONARQUBE_PROJECT_KEY_ANNOTATION, sonarQubeApiRef, useProjectInfo, -} from '@backstage/plugin-sonarqube-react'; +} from '@backstage/plugin-sonarqube-react/alpha'; +import { SONARQUBE_PROJECT_KEY_ANNOTATION } from '@backstage/plugin-sonarqube-react'; import { Chip, Grid } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import BugReport from '@material-ui/icons/BugReport'; diff --git a/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx b/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx index 59258e5312..91e85f9f25 100644 --- a/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx +++ b/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx @@ -18,10 +18,12 @@ import { EntityProvider } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { - isSonarQubeAvailable, - SONARQUBE_PROJECT_KEY_ANNOTATION, SonarQubeApi, sonarQubeApiRef, +} from '@backstage/plugin-sonarqube-react/alpha'; +import { + isSonarQubeAvailable, + SONARQUBE_PROJECT_KEY_ANNOTATION, } from '@backstage/plugin-sonarqube-react'; const Providers = ({ diff --git a/plugins/sonarqube/src/plugin.ts b/plugins/sonarqube/src/plugin.ts index c66d8c4e96..8da690abbf 100644 --- a/plugins/sonarqube/src/plugin.ts +++ b/plugins/sonarqube/src/plugin.ts @@ -22,7 +22,7 @@ import { discoveryApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { sonarQubeApiRef } from '@backstage/plugin-sonarqube-react'; +import { sonarQubeApiRef } from '@backstage/plugin-sonarqube-react/alpha'; /** @public */ export const sonarQubePlugin = createPlugin({ diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts index a76ea66729..86ab9e6cd8 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts @@ -29,7 +29,7 @@ import unescape from 'lodash/unescape'; import { Logger } from 'winston'; import pLimit from 'p-limit'; import { Config } from '@backstage/config'; -import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common'; +import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha'; import { Permission } from '@backstage/plugin-permission-common'; import { CatalogApi, diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts index aaddb4fa51..e2c6f5913c 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts @@ -30,7 +30,7 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common'; +import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/alpha'; import { Permission } from '@backstage/plugin-permission-common'; import { DocumentCollatorFactory } from '@backstage/plugin-search-common'; import { TechDocsDocument } from '@backstage/plugin-techdocs-node'; From 8baa40700e6fc4ab89ae9cca1154b44c912e2853 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 09:44:36 +0100 Subject: [PATCH 351/417] scipts/check-docs-quality: update to ignore all api reports Signed-off-by: Patrik Oldsberg --- scripts/check-docs-quality.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check-docs-quality.js b/scripts/check-docs-quality.js index 3dcbd6ef81..2890f1cf33 100755 --- a/scripts/check-docs-quality.js +++ b/scripts/check-docs-quality.js @@ -21,7 +21,7 @@ const IGNORED = [ /^ADOPTERS\.md$/, /^OWNERS\.md$/, /^.*[/\\]CHANGELOG\.md$/, - /^.*[/\\]api-report\.md$/, + /^.*[/\\]([^\/]+-)?api-report\.md$/, /^docs[/\\]releases[/\\].*-changelog\.md$/, /^docs[/\\]reference[/\\]/, ]; From e3474e5aaf8bce31808b3bd2bca3d1b93ac17c26 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 23:07:10 +0100 Subject: [PATCH 352/417] cli: hardcode build entry point to src/index.ts for non-exports for compatiblity Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/monorepo/entryPoints.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/cli/src/lib/monorepo/entryPoints.ts b/packages/cli/src/lib/monorepo/entryPoints.ts index 8a8bbd27f9..1e1fd7ed27 100644 --- a/packages/cli/src/lib/monorepo/entryPoints.ts +++ b/packages/cli/src/lib/monorepo/entryPoints.ts @@ -24,6 +24,15 @@ export interface EntryPoint { ext: string; } +// Unless explicitly specified in exports, the index entrypoint is always +// assumed to be at src/index.ts for backwards compatibility. +const defaultIndex = { + mount: '.', + path: 'src/index.ts', + name: 'index', + ext: '.ts', +}; + function parseEntryPoint(mount: string, path: string): EntryPoint { let name = mount; if (name === '.') { @@ -41,7 +50,7 @@ function parseEntryPoint(mount: string, path: string): EntryPoint { export function readEntryPoints(pkg: ExtendedPackageJSON): Array { const exp = pkg.exports; if (typeof exp === 'string') { - return [parseEntryPoint('.', exp)]; + return [defaultIndex]; } else if (exp && typeof exp === 'object' && !Array.isArray(exp)) { const entryPoints = new Array<{ mount: string; @@ -64,10 +73,5 @@ export function readEntryPoints(pkg: ExtendedPackageJSON): Array { return entryPoints; } - const main = pkg.main || pkg.module; - if (main) { - return [parseEntryPoint('.', main)]; - } - - return []; + return [defaultIndex]; } From 8da954740eebc1880fb432555a3798587b8b9bed Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 23:26:01 +0100 Subject: [PATCH 353/417] cli: fix production pack compatibility entry point writing Signed-off-by: Patrik Oldsberg --- .../cli/src/lib/packager/productionPack.ts | 60 ++++++++++++------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index 9f11c10222..4580b5981e 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -50,9 +50,10 @@ export async function productionPack(options: ProductionPackOptions) { } // This mutates pkg to fill in index exports, so call it before applying publishConfig - if (pkg.exports) { - await writeExportsEntryPoints(pkg, targetDir ?? packageDir); - } + const writeCompatibilityEntryPoints = await prepareExportsEntryPoints( + pkg, + packageDir, + ); // TODO(Rugvip): Once exports are rolled out more broadly we should deprecate and remove this behavior const publishConfig = pkg.publishConfig ?? {}; @@ -100,6 +101,9 @@ export async function productionPack(options: ProductionPackOptions) { if (publishConfig.betaTypes) { await writeReleaseStageEntrypoint(pkg, 'beta', targetDir ?? packageDir); } + if (writeCompatibilityEntryPoints) { + await writeCompatibilityEntryPoints(targetDir ?? packageDir); + } } // Reverts the changes made by productionPack when called without a targetDir. @@ -166,16 +170,20 @@ const EXPORT_MAP = { /** * Rewrites the exports field in package.json to point to dist files, as - * well as creating backwards compatibility entry points for importers - * that don't support exports. + * well as returning a function that creates backwards compatibility + * entry points for importers that don't support exports. */ -async function writeExportsEntryPoints( +async function prepareExportsEntryPoints( pkg: ExtendedPackageJSON, - targetDir: string, + packageDir: string, ) { - const distFiles = await fs.readdir(resolvePath(targetDir, 'dist')); + const distFiles = await fs.readdir(resolvePath(packageDir, 'dist')); const outputExports = {} as Record>; + const compatibilityWriters = new Array< + (targetDir: string) => Promise + >(); + const entryPoints = readEntryPoints(pkg); for (const entryPoint of entryPoints) { const exp = {} as Record; @@ -199,19 +207,22 @@ async function writeExportsEntryPoints( pkg.types = exp.types; } } else { - const entryPointDir = resolvePath(targetDir, entryPoint.name); - await fs.ensureDir(entryPointDir); - await fs.writeJson( - resolvePath(entryPointDir, PKG_PATH), - { - name: pkg.name, - version: pkg.version, - ...(exp.default ? { main: joinPath('..', exp.default) } : {}), - ...(exp.import ? { module: joinPath('..', exp.import) } : {}), - ...(exp.types ? { types: joinPath('..', exp.types) } : {}), - }, - { encoding: 'utf8', spaces: 2 }, - ); + // This is deferred until after we have created the target directory + compatibilityWriters.push(async targetDir => { + const entryPointDir = resolvePath(targetDir, entryPoint.name); + await fs.ensureDir(entryPointDir); + await fs.writeJson( + resolvePath(entryPointDir, PKG_PATH), + { + name: pkg.name, + version: pkg.version, + ...(exp.default ? { main: joinPath('..', exp.default) } : {}), + ...(exp.import ? { module: joinPath('..', exp.import) } : {}), + ...(exp.types ? { types: joinPath('..', exp.types) } : {}), + }, + { encoding: 'utf8', spaces: 2 }, + ); + }); if (Array.isArray(pkg.files) && !pkg.files.includes(entryPoint.name)) { pkg.files.push(entryPoint.name); } @@ -223,4 +234,11 @@ async function writeExportsEntryPoints( } pkg.exports = outputExports; + + if (compatibilityWriters.length > 0) { + return async (targetDir: string) => { + await Promise.all(compatibilityWriters.map(writer => writer(targetDir))); + }; + } + return undefined; } From b5c1b48d17f8afce96e471017eee8c29cd7202d8 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 23:26:45 +0100 Subject: [PATCH 354/417] cli: trim typesVersions from published packages Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/packager/productionPack.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index 4580b5981e..d78583d955 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -63,6 +63,9 @@ export async function productionPack(options: ProductionPackOptions) { } } + // For published packages we rely on compatibility entry points rather than this + delete pkg.typesVersions; + // We remove the dependencies from package.json of packages that are marked // as bundled, so that yarn doesn't try to install them. if (pkg.bundled) { From 8a3d8ecde05134782b5b9b4bf1c56a64d5495ee3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 23:32:20 +0100 Subject: [PATCH 355/417] cli: make migrate package-exports add ./package.json Signed-off-by: Patrik Oldsberg --- .../src/commands/migrate/packageExports.ts | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/migrate/packageExports.ts b/packages/cli/src/commands/migrate/packageExports.ts index 754a25e32b..9d5c6d6339 100644 --- a/packages/cli/src/commands/migrate/packageExports.ts +++ b/packages/cli/src/commands/migrate/packageExports.ts @@ -30,14 +30,31 @@ export async function command() { await Promise.all( packages.map(async ({ dir, packageJson }) => { - const { exports: exp } = packageJson; - if (!exp || typeof exp !== 'object' || Array.isArray(exp)) { + let { exports: exp } = packageJson; + if (!exp) { return; } + if (Array.isArray(exp)) { + throw new Error('Unexpected array in package.json exports field'); + } let changed = false; let newPackageJson = packageJson; + // If exports is a string we rewrite it to an object to add package.json + if (typeof exp === 'string') { + changed = true; + exp = { '.': exp }; + newPackageJson.exports = exp; + } else if (typeof exp !== 'object') { + return; + } + + if (!exp['./package.json']) { + changed = true; + exp['./package.json'] = './package.json'; + } + const existingTypesVersions = JSON.stringify(packageJson.typesVersions); const typeEntries: Record = {}; From c523edfc8819bbb85885e16abe8a2ffddef99a4a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 17 Jan 2023 23:41:42 +0100 Subject: [PATCH 356/417] migrate all packages to export package.json Signed-off-by: Patrik Oldsberg --- packages/backend-common/package.json | 6 +++++- packages/backend-test-utils/package.json | 6 +++++- packages/catalog-model/package.json | 6 +++++- packages/core-plugin-api/package.json | 6 +++++- packages/test-utils/package.json | 6 +++++- plugins/app-backend/package.json | 6 +++++- plugins/catalog-backend-module-aws/package.json | 6 +++++- plugins/catalog-backend-module-azure/package.json | 6 +++++- plugins/catalog-backend-module-bitbucket-cloud/package.json | 6 +++++- .../catalog-backend-module-bitbucket-server/package.json | 6 +++++- plugins/catalog-backend-module-gerrit/package.json | 6 +++++- plugins/catalog-backend-module-github/package.json | 6 +++++- plugins/catalog-backend-module-gitlab/package.json | 6 +++++- .../package.json | 6 +++++- plugins/catalog-backend-module-msgraph/package.json | 6 +++++- plugins/catalog-backend/package.json | 6 +++++- plugins/catalog-common/package.json | 6 +++++- plugins/catalog-node/package.json | 6 +++++- plugins/catalog-react/package.json | 6 +++++- plugins/events-backend-module-aws-sqs/package.json | 6 +++++- plugins/events-backend-module-azure/package.json | 6 +++++- plugins/events-backend-module-bitbucket-cloud/package.json | 6 +++++- plugins/events-backend-module-gerrit/package.json | 6 +++++- plugins/events-backend-module-github/package.json | 6 +++++- plugins/events-backend-module-gitlab/package.json | 6 +++++- plugins/events-backend/package.json | 6 +++++- plugins/events-node/package.json | 6 +++++- plugins/scaffolder-backend/package.json | 6 +++++- plugins/scaffolder-react/package.json | 6 +++++- plugins/scaffolder/package.json | 6 +++++- plugins/sonarqube-react/package.json | 6 +++++- 31 files changed, 155 insertions(+), 31 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index e778e6830c..71f800dff8 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 6330b161e1..7e14963aab 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -8,12 +8,16 @@ "access": "public" }, "exports": { - ".": "./src/index.ts" + ".": "./src/index.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { "*": [ "src/index.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index b07e2df915..2d569053b1 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index e01c99f384..781ebe37e1 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -7,7 +7,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -16,6 +17,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 4148f62a3f..b278b00c14 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -7,7 +7,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -16,6 +17,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index d52ab37abe..78070cbf14 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index c309ee995e..0273326e36 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index b68015cb87..dd89aec185 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 9f2243b0cd..8fbff7d79b 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index d11b9136e6..1a82807288 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 23d2db3073..33fcc4abcb 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 6ef4fea0c7..a5899ced33 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index a53da3a97f..8d1ec70123 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 8cc1ebbf8e..9479fd88e0 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index e1d0ede5fc..99e5b0da35 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 468cc13b34..47e678c012 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 55680e679c..2c74307f1c 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index d949bfaabb..7d186ad52c 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 0ca4e3c9e4..955e63b425 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 19aec3108a..d68c77bb41 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 540a2c700f..a1314b2db7 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index c377088b62..db85c32fad 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 5fe093893c..35a82b4fc5 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 3145ee9e66..7a7df507b7 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index be5ffc2318..f95995473c 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 4534dac9de..a0d4f9bf12 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -9,7 +9,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -18,6 +19,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 060e450289..ef0cce170e 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 3eda8bd678..9ee87669ff 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 4a4d94debf..6907f8080e 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index b4fb81fb9c..46e8f436fd 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -10,7 +10,8 @@ }, "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts" + "./alpha": "./src/alpha.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { @@ -19,6 +20,9 @@ ], "alpha": [ "src/alpha.ts" + ], + "package.json": [ + "package.json" ] } }, diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index f473d52f16..2f31d37007 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -8,12 +8,16 @@ "access": "public" }, "exports": { - ".": "./src/index.ts" + ".": "./src/index.ts", + "./package.json": "./package.json" }, "typesVersions": { "*": { "*": [ "src/index.ts" + ], + "package.json": [ + "package.json" ] } }, From e47f4994036db489a8e955f6f77ee910a94b7f26 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 00:41:55 +0100 Subject: [PATCH 357/417] cli: ignore package.json entry point Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/packager/productionPack.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index d78583d955..adcab2b90c 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -24,6 +24,7 @@ const PKG_PATH = 'package.json'; const PKG_BACKUP_PATH = 'package.json-prepack'; const SKIPPED_KEYS = ['access', 'registry', 'tag', 'alphaTypes', 'betaTypes']; +const SCRIPT_EXTS = ['.js', '.jsx', '.ts', '.tsx']; interface ProductionPackOptions { packageDir: string; @@ -189,6 +190,9 @@ async function prepareExportsEntryPoints( const entryPoints = readEntryPoints(pkg); for (const entryPoint of entryPoints) { + if (!SCRIPT_EXTS.includes(entryPoint.ext)) { + continue; + } const exp = {} as Record; for (const [key, ext] of Object.entries(EXPORT_MAP)) { const name = `${entryPoint.name}${ext}`; From 3e63951e49067aed8019487ff0c5c6aa80046043 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 00:43:27 +0100 Subject: [PATCH 358/417] prefer subpath over sub-path Signed-off-by: Patrik Oldsberg --- docs/local-dev/cli-build-system.md | 8 ++++---- packages/cli/src/commands/index.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index a784e0eff9..2eb695e3a3 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -650,9 +650,9 @@ The following is an excerpt of a typical setup of an isomorphic library package: "files": ["dist"], ``` -## Sub-path Exports +## Subpath Exports -The Backstage CLI supports implementation of sub-path exports through the `"exports"` field in `package.json`. It might for example look like this: +The Backstage CLI supports implementation of subpath exports through the `"exports"` field in `package.json`. It might for example look like this: ```json "name": "@backstage/plugin-foo", @@ -668,7 +668,7 @@ As with the rest of the Backstage CLI build system, the setup is optimized for l TypeScript support is currently handled though the `typesVersions` field, as there is not yet a module resolution mode that works well with `"exports"`. You can craft the `typesVersions` yourself, but it will also be automatically generated by the `migrate package-exports` command. -To add sub-path exports to an existing package, simply add the desired `"exports"` fields and then run the following command: +To add subpath exports to an existing package, simply add the desired `"exports"` fields and then run the following command: ```bash yarn backstage-cli package migrate package-exports @@ -676,7 +676,7 @@ yarn backstage-cli package migrate package-exports ## Experimental Type Build -> Note: Experimental type builds are deprecated and will be removed in the future. They have been replaced by [sub-path exports](#sub-path-exports). +> Note: Experimental type builds are deprecated and will be removed in the future. They have been replaced by [subpath exports](#subpath-exports). The Backstage CLI has an experimental feature where multiple different type definition files can be generated for different release stages. The release stages are marked in the [TSDoc](https://tsdoc.org/) for each individual export, using either `@public`, `@alpha`, or `@beta`. Rather than just building a single `index.d.ts` file, the build process will instead output `index.d.ts`, `index.beta.d.ts`, and `index.alpha.d.ts`. Each of these files will have exports from more unstable release stages stripped, meaning that `index.d.ts` will omit all exports marked with `@alpha` or `@beta`, while `index.beta.d.ts` will omit all exports marked with `@alpha`. diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 3eb511e06d..ddec5c6a4a 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -193,7 +193,7 @@ export function registerMigrateCommand(program: Command) { command .command('package-exports') - .description('Synchronize package sub-path export definitions') + .description('Synchronize package subpath export definitions') .action( lazy(() => import('./migrate/packageExports').then(m => m.command)), ); From 32a4a05838c523bd0fb55de9341268d6c9ebe17b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 01:02:06 +0100 Subject: [PATCH 359/417] repo-tools: work around /* type imports Signed-off-by: Patrik Oldsberg --- .changeset/curvy-pets-hang.md | 5 +++++ packages/repo-tools/src/commands/type-deps/type-deps.ts | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .changeset/curvy-pets-hang.md diff --git a/.changeset/curvy-pets-hang.md b/.changeset/curvy-pets-hang.md new file mode 100644 index 0000000000..3a2d11ac12 --- /dev/null +++ b/.changeset/curvy-pets-hang.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Tweaked type dependency check to trim wildcard type imports. diff --git a/packages/repo-tools/src/commands/type-deps/type-deps.ts b/packages/repo-tools/src/commands/type-deps/type-deps.ts index 4f8e5e5529..0ad9a5cfc8 100644 --- a/packages/repo-tools/src/commands/type-deps/type-deps.ts +++ b/packages/repo-tools/src/commands/type-deps/type-deps.ts @@ -105,7 +105,10 @@ function checkTypes(pkg: Package) { const errors = []; const typeDeps = []; - for (const dep of deps) { + for (let dep of deps) { + if (dep.endsWith('/*')) { + dep = dep.slice(0, -2); + } try { const typeDep = findTypesPackage(dep, pkg); if (typeDep) { From 928a12a9b3e035c722fa73784507037c21c7bd7a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 01:03:43 +0100 Subject: [PATCH 360/417] changesets: add changeset for alpha exports refactor Signed-off-by: Patrik Oldsberg --- .changeset/rare-grapes-count.md | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .changeset/rare-grapes-count.md diff --git a/.changeset/rare-grapes-count.md b/.changeset/rare-grapes-count.md new file mode 100644 index 0000000000..fdeb653f3c --- /dev/null +++ b/.changeset/rare-grapes-count.md @@ -0,0 +1,45 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-catalog-backend-module-bitbucket-server': patch +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch +'@backstage/plugin-events-backend-module-bitbucket-cloud': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-backend-module-gerrit': patch +'@backstage/plugin-catalog-backend-module-github': patch +'@backstage/plugin-catalog-backend-module-gitlab': patch +'@backstage/plugin-events-backend-module-aws-sqs': patch +'@backstage/plugin-catalog-backend-module-azure': patch +'@backstage/plugin-events-backend-module-gerrit': patch +'@backstage/plugin-events-backend-module-github': patch +'@backstage/plugin-events-backend-module-gitlab': patch +'@backstage/plugin-events-backend-module-azure': patch +'@backstage/plugin-catalog-backend-module-aws': patch +'@backstage/backend-plugin-api': patch +'@backstage/backend-test-utils': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/backend-defaults': patch +'@backstage/backend-app-api': patch +'@backstage/core-plugin-api': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-techdocs-backend': patch +'@backstage/backend-common': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-sonarqube-react': patch +'@backstage/catalog-model': patch +'@backstage/plugin-catalog-common': patch +'@backstage/plugin-events-backend': patch +'@backstage/plugin-jenkins-common': patch +'@backstage/plugin-techdocs-react': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-cost-insights': patch +'@backstage/plugin-catalog-node': patch +'@backstage/test-utils': patch +'@backstage/plugin-app-backend': patch +'@backstage/plugin-events-node': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-sonarqube': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-jenkins': patch +--- + +Internal refactor of `/alpha` exports. From 69f67093c4c632588b82d1764069ad03d7553e76 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 01:24:09 +0100 Subject: [PATCH 361/417] cli: add missing publishConfig types Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/monorepo/PackageGraph.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index 7bca16a6f7..bb203c01a5 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -44,6 +44,14 @@ export interface ExtendedPackageJSON extends PackageJSON { typesVersions?: Record>; files?: string[]; + + publishConfig?: { + access?: 'public' | 'restricted'; + directory?: string; + registry?: string; + alphaTypes?: string; + betaTypes?: string; + }; } export type ExtendedPackage = { From 5b2ddbc812dc1a77a17e21e551be4e112d48212f Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 11:11:45 +0100 Subject: [PATCH 362/417] scaffolder: fix TemplateGroups mock Signed-off-by: Patrik Oldsberg --- .../src/next/TemplateListPage/TemplateGroups.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx index 19a9728f37..6fe2d6beb9 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx @@ -18,7 +18,7 @@ jest.mock('@backstage/plugin-catalog-react', () => ({ useEntityList: jest.fn(), })); -jest.mock('@backstage/plugin-scaffolder-react', () => ({ +jest.mock('@backstage/plugin-scaffolder-react/alpha', () => ({ TemplateGroup: jest.fn(() => null), })); From 258643e6129c436098e88f15f3e55f251a833453 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 11:32:18 +0100 Subject: [PATCH 363/417] repo-tools: ignore non-ts entry points in extractor Signed-off-by: Patrik Oldsberg --- .../src/commands/api-reports/api-extractor.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index c05fd0a01e..6ab712cf5e 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -19,6 +19,7 @@ import { relative as relativePath, basename, join, + extname, } from 'path'; import { execFile } from 'child_process'; import fs from 'fs-extra'; @@ -309,15 +310,19 @@ async function findPackageEntryPoints( ); if (pkg.exports && typeof pkg.exports !== 'string') { - return Object.keys(pkg.exports).map(mount => { + return Object.entries(pkg.exports).flatMap(([mount, path]) => { + const ext = extname(String(path)); + if (!['.ts', '.tsx', '.cts', '.mts'].includes(ext)) { + return []; // Ignore non-TS entry points + } let name = mount; if (name.startsWith('./')) { name = name.slice(2); } if (!name || name === '.') { - return { packageDir, name: 'index' }; + return [{ packageDir, name: 'index' }]; } - return { packageDir, name }; + return [{ packageDir, name }]; }); } From 08d37cf1cc6a8029cbf1632033813884d4bdfec4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 21:42:28 +0100 Subject: [PATCH 364/417] catalog-model: fix alpha API report warnings Signed-off-by: Patrik Oldsberg --- packages/catalog-model/alpha-api-report.md | 5 +---- packages/catalog-model/src/entity/AlphaEntity.ts | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/catalog-model/alpha-api-report.md b/packages/catalog-model/alpha-api-report.md index 639cba1fef..5b962a7403 100644 --- a/packages/catalog-model/alpha-api-report.md +++ b/packages/catalog-model/alpha-api-report.md @@ -3,12 +3,9 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { JsonObject } from '@backstage/types'; +import { Entity } from '@backstage/catalog-model'; import { SerializedError } from '@backstage/errors'; -// Warning: (ae-forgotten-export) The symbol "Entity" needs to be exported by the entry point alpha.d.ts -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/catalog-model" does not have an export "Entity" -// // @alpha export interface AlphaEntity extends Entity { status?: EntityStatus; diff --git a/packages/catalog-model/src/entity/AlphaEntity.ts b/packages/catalog-model/src/entity/AlphaEntity.ts index 57a1954f52..6f5c9d4fa7 100644 --- a/packages/catalog-model/src/entity/AlphaEntity.ts +++ b/packages/catalog-model/src/entity/AlphaEntity.ts @@ -14,11 +14,13 @@ * limitations under the License. */ -import { Entity } from './Entity'; +// TODO(Rugvip): Figure out best way to allow this import +// eslint-disable-next-line import/no-extraneous-dependencies +import { Entity } from '@backstage/catalog-model'; import { EntityStatus } from './EntityStatus'; /** - * A version of the {@link Entity} type that contains unstable alpha fields. + * A version of the `Entity` type that contains unstable alpha fields. * * @remarks * From ea99ce2c37b0f7af5e1ccac73195248f5d88bd39 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 18 Jan 2023 21:47:46 +0100 Subject: [PATCH 365/417] cli: bit of reafactor for clarity in packageExports Signed-off-by: Patrik Oldsberg --- packages/cli/src/commands/migrate/packageExports.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/commands/migrate/packageExports.ts b/packages/cli/src/commands/migrate/packageExports.ts index 9d5c6d6339..51dc5c38bd 100644 --- a/packages/cli/src/commands/migrate/packageExports.ts +++ b/packages/cli/src/commands/migrate/packageExports.ts @@ -30,7 +30,10 @@ export async function command() { await Promise.all( packages.map(async ({ dir, packageJson }) => { - let { exports: exp } = packageJson; + let changed = false; + let newPackageJson = packageJson; + + let { exports: exp } = newPackageJson; if (!exp) { return; } @@ -38,9 +41,6 @@ export async function command() { throw new Error('Unexpected array in package.json exports field'); } - let changed = false; - let newPackageJson = packageJson; - // If exports is a string we rewrite it to an object to add package.json if (typeof exp === 'string') { changed = true; From eb9252186fb5a237eb389df716bc5094e54b9acc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 2 Feb 2023 14:56:09 +0100 Subject: [PATCH 366/417] permission-node,kubernetes-backend: mark public API as public Signed-off-by: Patrik Oldsberg --- .../AwsIamKubernetesAuthTranslator.ts | 4 +- .../AzureIdentityKubernetesAuthTranslator.ts | 2 +- .../GoogleKubernetesAuthTranslator.ts | 2 +- .../GoogleServiceAccountAuthProvider.ts | 2 +- .../KubernetesAuthTranslatorGenerator.ts | 2 +- .../NoopKubernetesAuthTranslator.ts | 2 +- .../OidcKubernetesAuthTranslator.ts | 2 +- .../src/kubernetes-auth-translator/types.ts | 2 +- .../src/service/KubernetesBuilder.ts | 6 +-- .../src/service/KubernetesFanOutHandler.ts | 2 +- .../src/service/KubernetesProxy.ts | 2 +- .../kubernetes-backend/src/service/router.ts | 4 +- plugins/kubernetes-backend/src/types/types.ts | 40 +++++++++---------- .../permission-node/src/integration/util.ts | 6 +-- 14 files changed, 39 insertions(+), 39 deletions(-) diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts index ccb0f28109..b89945902d 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts @@ -20,7 +20,7 @@ import { KubernetesAuthTranslator } from './types'; /** * - * @alpha + * @public */ export type SigningCreds = { accessKeyId: string | undefined; @@ -30,7 +30,7 @@ export type SigningCreds = { /** * - * @alpha + * @public */ export class AwsIamKubernetesAuthTranslator implements KubernetesAuthTranslator diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts index 6b1f2281c4..2633598d6c 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts @@ -27,7 +27,7 @@ const aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope /** * - * @alpha + * @public */ export class AzureIdentityKubernetesAuthTranslator implements KubernetesAuthTranslator diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts index cabf66b40b..e8dae56997 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts @@ -20,7 +20,7 @@ import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; /** * - * @alpha + * @public */ export class GoogleKubernetesAuthTranslator implements KubernetesAuthTranslator diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts index 1eca62b363..cca510ad6c 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts @@ -19,7 +19,7 @@ import * as container from '@google-cloud/container'; /** * - * @alpha + * @public */ export class GoogleServiceAccountAuthTranslator implements KubernetesAuthTranslator diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts index d4eed29653..f54e46efab 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts @@ -25,7 +25,7 @@ import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator'; /** * - * @alpha + * @public */ export class KubernetesAuthTranslatorGenerator { static getKubernetesAuthTranslatorInstance( diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts index 2ef78495a1..32aa141e50 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts @@ -19,7 +19,7 @@ import { ServiceAccountClusterDetails } from '../types/types'; /** * - * @alpha + * @public */ export class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator { async decorateClusterDetailsWithAuth( diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts index e5450b2fe1..cee1ec1e0c 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts @@ -20,7 +20,7 @@ import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; /** * - * @alpha + * @public */ export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator { async decorateClusterDetailsWithAuth( diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/types.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/types.ts index f8417f8468..efbbff8250 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/types.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/types.ts @@ -19,7 +19,7 @@ import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; /** * - * @alpha + * @public */ export interface KubernetesAuthTranslator { decorateClusterDetailsWithAuth( diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 92773ece6d..74ec9eada2 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -43,7 +43,7 @@ import { KubernetesProxy } from './KubernetesProxy'; /** * - * @alpha + * @public */ export interface KubernetesEnvironment { logger: Logger; @@ -54,7 +54,7 @@ export interface KubernetesEnvironment { /** * The return type of the `KubernetesBuilder.build` method * - * @alpha + * @public */ export type KubernetesBuilderReturn = Promise<{ router: express.Router; @@ -68,7 +68,7 @@ export type KubernetesBuilderReturn = Promise<{ /** * - * @alpha + * @public */ export class KubernetesBuilder { private clusterSupplier?: KubernetesClustersSupplier; diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index a738c69bcc..63e46a44e3 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -51,7 +51,7 @@ import { /** * - * @alpha + * @public */ export const DEFAULT_OBJECTS: ObjectToFetch[] = [ { diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts index cb36c647ac..178105ef79 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts @@ -39,7 +39,7 @@ export const HEADER_KUBERNETES_CLUSTER: string = 'X-Kubernetes-Cluster'; /** * A proxy that routes requests to the Kubernetes API. * - * @alpha + * @public */ export class KubernetesProxy { private readonly middlewareForClusterName = new Map(); diff --git a/plugins/kubernetes-backend/src/service/router.ts b/plugins/kubernetes-backend/src/service/router.ts index ab27a75a18..341956553e 100644 --- a/plugins/kubernetes-backend/src/service/router.ts +++ b/plugins/kubernetes-backend/src/service/router.ts @@ -24,7 +24,7 @@ import { CatalogApi } from '@backstage/catalog-client'; /** * - * @alpha + * @public */ export interface RouterOptions { logger: Logger; @@ -47,7 +47,7 @@ export interface RouterOptions { * }).build(); * ``` * - * @alpha + * @public */ export async function createRouter( options: RouterOptions, diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index d76bfc8149..25c7abfd1f 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -28,7 +28,7 @@ import type { /** * - * @alpha + * @public */ export interface ObjectFetchParams { serviceId: string; @@ -46,7 +46,7 @@ export interface ObjectFetchParams { /** * Fetches information from a kubernetes cluster using the cluster details object to target a specific cluster * - * @alpha + * @public */ export interface KubernetesFetcher { fetchObjectsForService( @@ -60,7 +60,7 @@ export interface KubernetesFetcher { /** * - * @alpha + * @public */ export interface FetchResponseWrapper { errors: KubernetesFetchError[]; @@ -69,7 +69,7 @@ export interface FetchResponseWrapper { /** * - * @alpha + * @public */ export interface ObjectToFetch { objectType: KubernetesObjectTypes; @@ -80,7 +80,7 @@ export interface ObjectToFetch { /** * - * @alpha + * @public */ export interface CustomResource extends ObjectToFetch { objectType: 'customresources'; @@ -88,7 +88,7 @@ export interface CustomResource extends ObjectToFetch { /** * - * @alpha + * @public */ export type KubernetesObjectTypes = | 'pods' @@ -107,7 +107,7 @@ export type KubernetesObjectTypes = /** * Used to load cluster details from different sources - * @alpha + * @public */ export interface KubernetesClustersSupplier { /** @@ -120,7 +120,7 @@ export interface KubernetesClustersSupplier { } /** - * @alpha + * @public */ export interface ServiceLocatorRequestContext { objectTypesToFetch: Set; @@ -129,7 +129,7 @@ export interface ServiceLocatorRequestContext { /** * Used to locate which cluster(s) a service is running on - * @alpha + * @public */ export interface KubernetesServiceLocator { getClustersByEntity( @@ -140,13 +140,13 @@ export interface KubernetesServiceLocator { /** * - * @alpha + * @public */ export type ServiceLocatorMethod = 'multiTenant' | 'http'; // TODO implement http /** * - * @alpha + * @public */ export interface ClusterDetails { /** @@ -209,25 +209,25 @@ export interface ClusterDetails { /** * - * @alpha + * @public */ export interface GKEClusterDetails extends ClusterDetails {} /** * - * @alpha + * @public */ export interface AzureClusterDetails extends ClusterDetails {} /** * - * @alpha + * @public */ export interface ServiceAccountClusterDetails extends ClusterDetails {} /** * - * @alpha + * @public */ export interface AWSClusterDetails extends ClusterDetails { assumeRole?: string; @@ -236,7 +236,7 @@ export interface AWSClusterDetails extends ClusterDetails { /** * - * @alpha + * @public */ export interface KubernetesObjectsProviderOptions { logger: Logger; @@ -248,13 +248,13 @@ export interface KubernetesObjectsProviderOptions { /** * - * @alpha + * @public */ export type ObjectsByEntityRequest = KubernetesRequestBody; /** * - * @alpha + * @public */ export interface KubernetesObjectsByEntity { entity: Entity; @@ -263,7 +263,7 @@ export interface KubernetesObjectsByEntity { /** * - * @alpha + * @public */ export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { customResources: CustomResourceMatcher[]; @@ -271,7 +271,7 @@ export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { /** * - * @alpha + * @public */ export interface KubernetesObjectsProvider { getKubernetesObjectsByEntity( diff --git a/plugins/permission-node/src/integration/util.ts b/plugins/permission-node/src/integration/util.ts index e448068e17..9be90e15fc 100644 --- a/plugins/permission-node/src/integration/util.ts +++ b/plugins/permission-node/src/integration/util.ts @@ -33,7 +33,7 @@ export type NoInfer = T extends infer S ? S : never; /** * Utility function used to parse a PermissionCriteria * @param criteria - a PermissionCriteria - * @alpha + * @public * * @returns `true` if the permission criteria is of type allOf, * narrowing down `criteria` to the specific type. @@ -46,7 +46,7 @@ export const isAndCriteria = ( /** * Utility function used to parse a PermissionCriteria of type * @param criteria - a PermissionCriteria - * @alpha + * @public * * @returns `true` if the permission criteria is of type anyOf, * narrowing down `criteria` to the specific type. @@ -59,7 +59,7 @@ export const isOrCriteria = ( /** * Utility function used to parse a PermissionCriteria * @param criteria - a PermissionCriteria - * @alpha + * @public * * @returns `true` if the permission criteria is of type not, * narrowing down `criteria` to the specific type. From 3ab32a709103883c1732745b701e79a082db9d0a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 2 Feb 2023 19:59:27 +0100 Subject: [PATCH 367/417] repo-tools: detect experimental type builds and allow all release stages in index Signed-off-by: Patrik Oldsberg --- .../src/commands/api-reports/api-extractor.ts | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index 6ab712cf5e..fb36d5fe4e 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -300,9 +300,13 @@ function logApiReportInstructions() { console.log(''); } -async function findPackageEntryPoints( - packageDirs: string[], -): Promise> { +async function findPackageEntryPoints(packageDirs: string[]): Promise< + Array<{ + packageDir: string; + name: string; + usesExperimentalTypeBuild?: boolean; + }> +> { return Promise.all( packageDirs.map(async packageDir => { const pkg = await fs.readJson( @@ -326,7 +330,13 @@ async function findPackageEntryPoints( }); } - return { packageDir, name: 'index' }; + return { + packageDir, + name: 'index', + usesExperimentalTypeBuild: pkg.scripts?.build?.includes( + '--experimental-type-build', + ), + }; }), ).then(results => results.flat()); } @@ -372,7 +382,11 @@ export async function runApiExtraction({ } const warnings = new Array(); - for (const { packageDir, name } of packageEntryPoints) { + for (const { + packageDir, + name, + usesExperimentalTypeBuild, + } of packageEntryPoints) { console.log(`## Processing ${packageDir}`); const noBail = Array.isArray(allowWarnings) ? allowWarnings.some(aw => aw === packageDir || minimatch(packageDir, aw)) @@ -505,7 +519,7 @@ export async function runApiExtraction({ // This release tag validation makes sure that the release tag of known entry points match expectations. // The root index entrypoint is only allowed @public exports, while /alpha and /beta only allow @alpha and @beta. - if (validateReleaseTags) { + if (validateReleaseTags && !usesExperimentalTypeBuild) { if (['index', 'alpha', 'beta'].includes(name)) { const report = await fs.readFile( extractorConfig.reportFilePath, From 8ce58b40fb8b71be4222ee42a8470f081b1557a9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 2 Feb 2023 20:31:51 +0100 Subject: [PATCH 368/417] repo-tools: allow public tags in alpha and beta reports Signed-off-by: Patrik Oldsberg --- .../repo-tools/src/commands/api-reports/api-extractor.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index fb36d5fe4e..dcd0631614 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -531,6 +531,11 @@ export async function runApiExtraction({ const line = lines[i]; const match = line.match(/^\/\/ @(alpha|beta|public)/); if (match && match[1] !== expectedTag) { + // Because of limitations in the type script rollup logic we need to allow public exports from the other release stages + // TODO(Rugvip): Try to work around the need for this exception + if (expectedTag !== 'public' && match[1] === 'public') { + continue; + } throw new Error( `Unexpected release tag ${match[1]} in ${ extractorConfig.reportFilePath From 4c08ac06fc30eafaa9ad7ce19e43dedd9151161d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 2 Feb 2023 20:32:59 +0100 Subject: [PATCH 369/417] fix remaining alpha exports Signed-off-by: Patrik Oldsberg --- packages/core-plugin-api/alpha-api-report.md | 3 +- .../src/plugin-options/usePluginOptions.tsx | 2 +- .../alpha-api-report.md | 2 - .../api-report.md | 2 +- .../GithubEntityProviderCatalogModule.ts | 2 +- .../alpha-api-report.md | 9 +-- .../api-report.md | 2 + ...talIngestionEntityProviderCatalogModule.ts | 2 +- .../alpha-api-report.md | 9 +-- ...softGraphOrgEntityProviderCatalogModule.ts | 2 +- plugins/catalog-backend/alpha-api-report.md | 24 ++++--- plugins/catalog-backend/src/alpha.ts | 6 ++ plugins/catalog-node/alpha-api-report.md | 12 +--- plugins/catalog-node/src/extensions.ts | 6 +- .../alpha-api-report.md | 2 - .../AzureDevOpsEventRouterEventsModule.ts | 2 +- .../alpha-api-report.md | 2 - .../BitbucketCloudEventRouterEventsModule.ts | 2 +- .../alpha-api-report.md | 12 ++++ .../api-report.md | 4 -- .../service/GerritEventRouterEventsModule.ts | 2 +- .../alpha-api-report.md | 2 - .../service/GithubEventRouterEventsModule.ts | 2 +- .../alpha-api-report.md | 4 -- .../service/GitlabEventRouterEventsModule.ts | 2 +- .../src/service/GitlabWebhookEventsModule.ts | 2 +- plugins/events-node/alpha-api-report.md | 12 ++-- plugins/events-node/src/extensions.ts | 2 +- plugins/kubernetes-backend/api-report.md | 72 +++++++++---------- plugins/kubernetes/api-report.md | 10 +-- .../src/error-detection/error-detection.ts | 2 +- .../kubernetes/src/error-detection/types.ts | 8 +-- plugins/permission-node/api-report.md | 6 +- plugins/scaffolder/api-report.md | 17 ++--- plugins/sonarqube/api-report.md | 6 +- 35 files changed, 125 insertions(+), 131 deletions(-) create mode 100644 plugins/events-backend-module-gerrit/alpha-api-report.md diff --git a/packages/core-plugin-api/alpha-api-report.md b/packages/core-plugin-api/alpha-api-report.md index b66fee8207..379e186df8 100644 --- a/packages/core-plugin-api/alpha-api-report.md +++ b/packages/core-plugin-api/alpha-api-report.md @@ -3,14 +3,13 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ReactNode } from 'react'; // @alpha export interface PluginOptionsProviderProps { // (undocumented) children: ReactNode; - // Warning: (ae-forgotten-export) The symbol "BackstagePlugin" needs to be exported by the entry point alpha.d.ts - // // (undocumented) plugin?: BackstagePlugin; } diff --git a/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx b/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx index 4fdacc1ace..8b3f7c109c 100644 --- a/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx +++ b/packages/core-plugin-api/src/plugin-options/usePluginOptions.tsx @@ -19,7 +19,7 @@ import { createVersionedValueMap, useVersionedContext, } from '@backstage/version-bridge'; -import { BackstagePlugin } from '../plugin'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; import React, { ReactNode } from 'react'; const contextKey: string = 'plugin-context'; diff --git a/plugins/catalog-backend-module-github/alpha-api-report.md b/plugins/catalog-backend-module-github/alpha-api-report.md index 8522344433..eb13ec4558 100644 --- a/plugins/catalog-backend-module-github/alpha-api-report.md +++ b/plugins/catalog-backend-module-github/alpha-api-report.md @@ -5,8 +5,6 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-catalog-backend-module-github" does not have an export "GithubEntityProvider" -// // @alpha export const githubEntityProviderCatalogModule: () => BackendFeature; diff --git a/plugins/catalog-backend-module-github/api-report.md b/plugins/catalog-backend-module-github/api-report.md index e2b73d267b..0ad377952a 100644 --- a/plugins/catalog-backend-module-github/api-report.md +++ b/plugins/catalog-backend-module-github/api-report.md @@ -7,7 +7,7 @@ import { AnalyzeOptions } from '@backstage/plugin-catalog-backend'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; -import { Entity } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model/*'; import { EntityProvider } from '@backstage/plugin-catalog-backend'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; import { EventParams } from '@backstage/plugin-events-node'; diff --git a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts index fc319534f3..246f700248 100644 --- a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts @@ -23,7 +23,7 @@ import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/ import { GithubEntityProvider } from '../providers/GithubEntityProvider'; /** - * Registers the {@link GithubEntityProvider} with the catalog processing extension point. + * Registers the `GithubEntityProvider` with the catalog processing extension point. * * @alpha */ diff --git a/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md b/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md index f762503b53..ec9c59a4c4 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md +++ b/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md @@ -4,8 +4,8 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -import type { DeferredEntity } from '@backstage/plugin-catalog-backend'; -import type { DurationObjectUnits } from 'luxon'; +import { IncrementalEntityProvider } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; +import { IncrementalEntityProviderOptions } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; // @alpha export const incrementalIngestionEntityProviderCatalogModule: (options: { @@ -15,10 +15,5 @@ export const incrementalIngestionEntityProviderCatalogModule: (options: { }[]; }) => BackendFeature; -// Warnings were encountered during analysis: -// -// src/module/incrementalIngestionEntityProviderCatalogModule.d.ts:9:9 - (ae-forgotten-export) The symbol "IncrementalEntityProvider" needs to be exported by the entry point alpha.d.ts -// src/module/incrementalIngestionEntityProviderCatalogModule.d.ts:10:9 - (ae-forgotten-export) The symbol "IncrementalEntityProviderOptions" needs to be exported by the entry point alpha.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-backend-module-incremental-ingestion/api-report.md b/plugins/catalog-backend-module-incremental-ingestion/api-report.md index 27ea35a34c..167c07f70f 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/api-report.md +++ b/plugins/catalog-backend-module-incremental-ingestion/api-report.md @@ -3,6 +3,8 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +/// + import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; import type { Config } from '@backstage/config'; import type { DeferredEntity } from '@backstage/plugin-catalog-backend'; diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts index 52fcef2cc9..261768c142 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/incrementalIngestionEntityProviderCatalogModule.ts @@ -22,7 +22,7 @@ import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/ import { IncrementalEntityProvider, IncrementalEntityProviderOptions, -} from '../types'; +} from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; import { WrapperProviders } from './WrapperProviders'; /** diff --git a/plugins/catalog-backend-module-msgraph/alpha-api-report.md b/plugins/catalog-backend-module-msgraph/alpha-api-report.md index c0daedc038..ed30b83bc8 100644 --- a/plugins/catalog-backend-module-msgraph/alpha-api-report.md +++ b/plugins/catalog-backend-module-msgraph/alpha-api-report.md @@ -4,22 +4,19 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -import { GroupEntity } from '@backstage/catalog-model'; -import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; -import { UserEntity } from '@backstage/catalog-model'; +import { GroupTransformer } from '@backstage/plugin-catalog-backend-module-msgraph'; +import { OrganizationTransformer } from '@backstage/plugin-catalog-backend-module-msgraph'; +import { UserTransformer } from '@backstage/plugin-catalog-backend-module-msgraph'; // @alpha export const microsoftGraphOrgEntityProviderCatalogModule: () => BackendFeature; // @alpha export interface MicrosoftGraphOrgEntityProviderCatalogModuleOptions { - // Warning: (ae-forgotten-export) The symbol "GroupTransformer" needs to be exported by the entry point alpha.d.ts groupTransformer?: GroupTransformer | Record; - // Warning: (ae-forgotten-export) The symbol "OrganizationTransformer" needs to be exported by the entry point alpha.d.ts organizationTransformer?: | OrganizationTransformer | Record; - // Warning: (ae-forgotten-export) The symbol "UserTransformer" needs to be exported by the entry point alpha.d.ts userTransformer?: UserTransformer | Record; } diff --git a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts index 5cad504829..11be567045 100644 --- a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts +++ b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts @@ -24,7 +24,7 @@ import { GroupTransformer, OrganizationTransformer, UserTransformer, -} from '../microsoftGraph'; +} from '@backstage/plugin-catalog-backend-module-msgraph'; import { MicrosoftGraphOrgEntityProvider } from '../processors'; /** diff --git a/plugins/catalog-backend/alpha-api-report.md b/plugins/catalog-backend/alpha-api-report.md index 6a40829d64..46be9a27df 100644 --- a/plugins/catalog-backend/alpha-api-report.md +++ b/plugins/catalog-backend/alpha-api-report.md @@ -6,7 +6,8 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; import { Conditions } from '@backstage/plugin-permission-node'; -import { Entity } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model/*'; +import { Entity as Entity_2 } from '@backstage/catalog-model'; import { PermissionCondition } from '@backstage/plugin-permission-common'; import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; @@ -71,7 +72,7 @@ export const catalogConditions: Conditions<{ // @alpha export type CatalogPermissionRule< TParams extends PermissionRuleParams = PermissionRuleParams, -> = PermissionRule; +> = PermissionRule; // @alpha export const catalogPlugin: () => BackendFeature; @@ -88,8 +89,19 @@ export const createCatalogConditionalDecision: ( export const createCatalogPermissionRule: < TParams extends PermissionRuleParams = undefined, >( - rule: PermissionRule, -) => PermissionRule; + rule: PermissionRule< + Entity_2, + EntitiesSearchFilter, + 'catalog-entity', + TParams + >, +) => PermissionRule; + +// @public +export type EntitiesSearchFilter = { + key: string; + values?: string[]; +}; // @alpha export const permissionRules: { @@ -146,9 +158,5 @@ export const permissionRules: { >; }; -// Warnings were encountered during analysis: -// -// src/permissions/conditionExports.d.ts:8:5 - (ae-forgotten-export) The symbol "EntitiesSearchFilter" needs to be exported by the entry point alpha.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-backend/src/alpha.ts b/plugins/catalog-backend/src/alpha.ts index 51a6a72923..aa1309aecd 100644 --- a/plugins/catalog-backend/src/alpha.ts +++ b/plugins/catalog-backend/src/alpha.ts @@ -14,5 +14,11 @@ * limitations under the License. */ +// TODO(Rugvip): Re-exported for alpha types as the API report will otherwise +// produce warnings due to the indirect dependency. We be nice to avoid. +import type { EntitiesSearchFilter } from './catalog/types'; + +export type { /** @alpha */ EntitiesSearchFilter }; + export * from './permissions'; export { catalogPlugin } from './service/CatalogPlugin'; diff --git a/plugins/catalog-node/alpha-api-report.md b/plugins/catalog-node/alpha-api-report.md index 1bfb3f3566..ba1bcd47b2 100644 --- a/plugins/catalog-node/alpha-api-report.md +++ b/plugins/catalog-node/alpha-api-report.md @@ -3,26 +3,18 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -/// - import { CatalogApi } from '@backstage/catalog-client'; -import { CompoundEntityRef } from '@backstage/catalog-model'; -import { Entity } from '@backstage/catalog-model'; +import { CatalogProcessor } from '@backstage/plugin-catalog-node'; +import { EntityProvider } from '@backstage/plugin-catalog-node'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; -import { JsonValue } from '@backstage/types'; -import { LocationSpec } from '@backstage/plugin-catalog-common'; import { ServiceRef } from '@backstage/backend-plugin-api'; // @alpha (undocumented) export interface CatalogProcessingExtensionPoint { - // Warning: (ae-forgotten-export) The symbol "EntityProvider" needs to be exported by the entry point alpha.d.ts - // // (undocumented) addEntityProvider( ...providers: Array> ): void; - // Warning: (ae-forgotten-export) The symbol "CatalogProcessor" needs to be exported by the entry point alpha.d.ts - // // (undocumented) addProcessor( ...processors: Array> diff --git a/plugins/catalog-node/src/extensions.ts b/plugins/catalog-node/src/extensions.ts index 8dd9d8579a..0466af36b0 100644 --- a/plugins/catalog-node/src/extensions.ts +++ b/plugins/catalog-node/src/extensions.ts @@ -14,8 +14,10 @@ * limitations under the License. */ import { createExtensionPoint } from '@backstage/backend-plugin-api'; -import { EntityProvider } from './api'; -import { CatalogProcessor } from './api/processor'; +import { + EntityProvider, + CatalogProcessor, +} from '@backstage/plugin-catalog-node'; /** * @alpha diff --git a/plugins/events-backend-module-azure/alpha-api-report.md b/plugins/events-backend-module-azure/alpha-api-report.md index ccae207a64..e3fed2cab0 100644 --- a/plugins/events-backend-module-azure/alpha-api-report.md +++ b/plugins/events-backend-module-azure/alpha-api-report.md @@ -5,8 +5,6 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-azure" does not have an export "AzureDevOpsEventRouter" -// // @alpha export const azureDevOpsEventRouterEventsModule: () => BackendFeature; diff --git a/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts b/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts index 1ceefe5c4e..18851befa4 100644 --- a/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts +++ b/plugins/events-backend-module-azure/src/service/AzureDevOpsEventRouterEventsModule.ts @@ -21,7 +21,7 @@ import { AzureDevOpsEventRouter } from '../router/AzureDevOpsEventRouter'; /** * Module for the events-backend plugin, adding an event router for Azure DevOps. * - * Registers the {@link AzureDevOpsEventRouter}. + * Registers the `AzureDevOpsEventRouter`. * * @alpha */ diff --git a/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md b/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md index 11b60fd12d..f8e550bf98 100644 --- a/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md +++ b/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md @@ -5,8 +5,6 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-bitbucket-cloud" does not have an export "BitbucketCloudEventRouter" -// // @alpha export const bitbucketCloudEventRouterEventsModule: () => BackendFeature; diff --git a/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts b/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts index 1f339a2bd1..9516651aa3 100644 --- a/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts +++ b/plugins/events-backend-module-bitbucket-cloud/src/service/BitbucketCloudEventRouterEventsModule.ts @@ -21,7 +21,7 @@ import { BitbucketCloudEventRouter } from '../router/BitbucketCloudEventRouter'; /** * Module for the events-backend plugin, adding an event router for Bitbucket Cloud. * - * Registers the {@link BitbucketCloudEventRouter}. + * Registers the `BitbucketCloudEventRouter`. * * @alpha */ diff --git a/plugins/events-backend-module-gerrit/alpha-api-report.md b/plugins/events-backend-module-gerrit/alpha-api-report.md new file mode 100644 index 0000000000..f610d518e7 --- /dev/null +++ b/plugins/events-backend-module-gerrit/alpha-api-report.md @@ -0,0 +1,12 @@ +## API Report File for "@backstage/plugin-events-backend-module-gerrit" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; + +// @alpha +export const gerritEventRouterEventsModule: () => BackendFeature; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/events-backend-module-gerrit/api-report.md b/plugins/events-backend-module-gerrit/api-report.md index c8d4a7c9b6..ba3c4dd29f 100644 --- a/plugins/events-backend-module-gerrit/api-report.md +++ b/plugins/events-backend-module-gerrit/api-report.md @@ -3,7 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; import { EventParams } from '@backstage/plugin-events-node'; import { SubTopicEventRouter } from '@backstage/plugin-events-node'; @@ -13,7 +12,4 @@ export class GerritEventRouter extends SubTopicEventRouter { // (undocumented) protected determineSubTopic(params: EventParams): string | undefined; } - -// @alpha -export const gerritEventRouterEventsModule: () => BackendFeature; ``` diff --git a/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts b/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts index 6f8889eb2b..31f5c9b384 100644 --- a/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts +++ b/plugins/events-backend-module-gerrit/src/service/GerritEventRouterEventsModule.ts @@ -21,7 +21,7 @@ import { GerritEventRouter } from '../router/GerritEventRouter'; /** * Module for the events-backend plugin, adding an event router for Gerrit. * - * Registers the {@link GerritEventRouter}. + * Registers the `GerritEventRouter`. * * @alpha */ diff --git a/plugins/events-backend-module-github/alpha-api-report.md b/plugins/events-backend-module-github/alpha-api-report.md index aed740ed0d..cb95928b17 100644 --- a/plugins/events-backend-module-github/alpha-api-report.md +++ b/plugins/events-backend-module-github/alpha-api-report.md @@ -5,8 +5,6 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-github" does not have an export "GithubEventRouter" -// // @alpha export const githubEventRouterEventsModule: () => BackendFeature; diff --git a/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts b/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts index e2e6fab266..56cc571763 100644 --- a/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts +++ b/plugins/events-backend-module-github/src/service/GithubEventRouterEventsModule.ts @@ -21,7 +21,7 @@ import { GithubEventRouter } from '../router/GithubEventRouter'; /** * Module for the events-backend plugin, adding an event router for GitHub. * - * Registers the {@link GithubEventRouter}. + * Registers the `GithubEventRouter`. * * @alpha */ diff --git a/plugins/events-backend-module-gitlab/alpha-api-report.md b/plugins/events-backend-module-gitlab/alpha-api-report.md index d8b1430df9..64727cc844 100644 --- a/plugins/events-backend-module-gitlab/alpha-api-report.md +++ b/plugins/events-backend-module-gitlab/alpha-api-report.md @@ -5,13 +5,9 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-gitlab" does not have an export "GitlabEventRouter" -// // @alpha export const gitlabEventRouterEventsModule: () => BackendFeature; -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-events-backend-module-gitlab" does not have an export "GitlabEventRouter" -// // @alpha export const gitlabWebhookEventsModule: () => BackendFeature; diff --git a/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts b/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts index 45b7f37711..39ccd5cd60 100644 --- a/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts +++ b/plugins/events-backend-module-gitlab/src/service/GitlabEventRouterEventsModule.ts @@ -21,7 +21,7 @@ import { GitlabEventRouter } from '../router/GitlabEventRouter'; /** * Module for the events-backend plugin, adding an event router for GitLab. * - * Registers the {@link GitlabEventRouter}. + * Registers the `GitlabEventRouter`. * * @alpha */ diff --git a/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts b/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts index 2fcee40589..c20e55caa9 100644 --- a/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts +++ b/plugins/events-backend-module-gitlab/src/service/GitlabWebhookEventsModule.ts @@ -26,7 +26,7 @@ import { createGitlabTokenValidator } from '../http/createGitlabTokenValidator'; * registering an HTTP POST ingress with request validator * which verifies the webhook token based on a secret. * - * Registers the {@link GitlabEventRouter}. + * Registers the `GitlabEventRouter`. * * @alpha */ diff --git a/plugins/events-node/alpha-api-report.md b/plugins/events-node/alpha-api-report.md index 161f80ff87..fd30f54d45 100644 --- a/plugins/events-node/alpha-api-report.md +++ b/plugins/events-node/alpha-api-report.md @@ -3,28 +3,24 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { EventBroker } from '@backstage/plugin-events-node'; +import { EventPublisher } from '@backstage/plugin-events-node'; +import { EventSubscriber } from '@backstage/plugin-events-node'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { HttpPostIngressOptions } from '@backstage/plugin-events-node'; // @alpha (undocumented) export interface EventsExtensionPoint { - // Warning: (ae-forgotten-export) The symbol "HttpPostIngressOptions" needs to be exported by the entry point alpha.d.ts - // // (undocumented) addHttpPostIngress(options: HttpPostIngressOptions): void; - // Warning: (ae-forgotten-export) The symbol "EventPublisher" needs to be exported by the entry point alpha.d.ts - // // (undocumented) addPublishers( ...publishers: Array> ): void; - // Warning: (ae-forgotten-export) The symbol "EventSubscriber" needs to be exported by the entry point alpha.d.ts - // // (undocumented) addSubscribers( ...subscribers: Array> ): void; - // Warning: (ae-forgotten-export) The symbol "EventBroker" needs to be exported by the entry point alpha.d.ts - // // (undocumented) setEventBroker(eventBroker: EventBroker): void; } diff --git a/plugins/events-node/src/extensions.ts b/plugins/events-node/src/extensions.ts index 945d86b49c..2e44b381af 100644 --- a/plugins/events-node/src/extensions.ts +++ b/plugins/events-node/src/extensions.ts @@ -20,7 +20,7 @@ import { EventPublisher, EventSubscriber, HttpPostIngressOptions, -} from './api'; +} from '@backstage/plugin-events-node'; /** * @alpha diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 006f980c56..a6a4bcfc58 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -21,7 +21,7 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; import type { RequestHandler } from 'express'; import { TokenCredential } from '@azure/identity'; -// @alpha (undocumented) +// @public (undocumented) export interface AWSClusterDetails extends ClusterDetails { // (undocumented) assumeRole?: string; @@ -29,7 +29,7 @@ export interface AWSClusterDetails extends ClusterDetails { externalId?: string; } -// @alpha (undocumented) +// @public (undocumented) export class AwsIamKubernetesAuthTranslator implements KubernetesAuthTranslator { @@ -54,10 +54,10 @@ export class AwsIamKubernetesAuthTranslator validCredentials(creds: SigningCreds): boolean; } -// @alpha (undocumented) +// @public (undocumented) export interface AzureClusterDetails extends ClusterDetails {} -// @alpha (undocumented) +// @public (undocumented) export class AzureIdentityKubernetesAuthTranslator implements KubernetesAuthTranslator { @@ -68,7 +68,7 @@ export class AzureIdentityKubernetesAuthTranslator ): Promise; } -// @alpha (undocumented) +// @public (undocumented) export interface ClusterDetails { // (undocumented) authProvider: string; @@ -91,25 +91,25 @@ export interface ClusterDetails { url: string; } -// @alpha @deprecated +// @public @deprecated export function createRouter(options: RouterOptions): Promise; -// @alpha (undocumented) +// @public (undocumented) export interface CustomResource extends ObjectToFetch { // (undocumented) objectType: 'customresources'; } -// @alpha (undocumented) +// @public (undocumented) export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { // (undocumented) customResources: CustomResourceMatcher[]; } -// @alpha (undocumented) +// @public (undocumented) export const DEFAULT_OBJECTS: ObjectToFetch[]; -// @alpha (undocumented) +// @public (undocumented) export interface FetchResponseWrapper { // (undocumented) errors: KubernetesFetchError[]; @@ -117,10 +117,10 @@ export interface FetchResponseWrapper { responses: FetchResponse[]; } -// @alpha (undocumented) +// @public (undocumented) export interface GKEClusterDetails extends ClusterDetails {} -// @alpha (undocumented) +// @public (undocumented) export class GoogleKubernetesAuthTranslator implements KubernetesAuthTranslator { @@ -131,7 +131,7 @@ export class GoogleKubernetesAuthTranslator ): Promise; } -// @alpha (undocumented) +// @public (undocumented) export class GoogleServiceAccountAuthTranslator implements KubernetesAuthTranslator { @@ -144,7 +144,7 @@ export class GoogleServiceAccountAuthTranslator // @public export const HEADER_KUBERNETES_CLUSTER: string; -// @alpha (undocumented) +// @public (undocumented) export interface KubernetesAuthTranslator { // (undocumented) decorateClusterDetailsWithAuth( @@ -153,7 +153,7 @@ export interface KubernetesAuthTranslator { ): Promise; } -// @alpha (undocumented) +// @public (undocumented) export class KubernetesAuthTranslatorGenerator { // (undocumented) static getKubernetesAuthTranslatorInstance( @@ -164,7 +164,7 @@ export class KubernetesAuthTranslatorGenerator { ): KubernetesAuthTranslator; } -// @alpha (undocumented) +// @public (undocumented) export class KubernetesBuilder { constructor(env: KubernetesEnvironment); // (undocumented) @@ -247,7 +247,7 @@ export class KubernetesBuilder { setServiceLocator(serviceLocator?: KubernetesServiceLocator): this; } -// @alpha +// @public export type KubernetesBuilderReturn = Promise<{ router: express.Router; clusterSupplier: KubernetesClustersSupplier; @@ -258,12 +258,12 @@ export type KubernetesBuilderReturn = Promise<{ serviceLocator: KubernetesServiceLocator; }>; -// @alpha +// @public export interface KubernetesClustersSupplier { getClusters(): Promise; } -// @alpha (undocumented) +// @public (undocumented) export interface KubernetesEnvironment { // (undocumented) catalogApi: CatalogApi; @@ -273,7 +273,7 @@ export interface KubernetesEnvironment { logger: Logger; } -// @alpha +// @public export interface KubernetesFetcher { // (undocumented) fetchObjectsForService( @@ -286,7 +286,7 @@ export interface KubernetesFetcher { ): Promise; } -// @alpha (undocumented) +// @public (undocumented) export interface KubernetesObjectsByEntity { // (undocumented) auth: KubernetesRequestAuth; @@ -294,7 +294,7 @@ export interface KubernetesObjectsByEntity { entity: Entity; } -// @alpha (undocumented) +// @public (undocumented) export interface KubernetesObjectsProvider { // (undocumented) getCustomResourcesByEntity( @@ -306,7 +306,7 @@ export interface KubernetesObjectsProvider { ): Promise; } -// @alpha (undocumented) +// @public (undocumented) export interface KubernetesObjectsProviderOptions { // (undocumented) customResources: CustomResource[]; @@ -320,7 +320,7 @@ export interface KubernetesObjectsProviderOptions { serviceLocator: KubernetesServiceLocator; } -// @alpha (undocumented) +// @public (undocumented) export type KubernetesObjectTypes = | 'pods' | 'services' @@ -336,14 +336,14 @@ export type KubernetesObjectTypes = | 'statefulsets' | 'daemonsets'; -// @alpha +// @public export class KubernetesProxy { constructor(logger: Logger, clusterSupplier: KubernetesClustersSupplier); // (undocumented) createRequestHandler(): RequestHandler; } -// @alpha +// @public export interface KubernetesServiceLocator { // (undocumented) getClustersByEntity( @@ -354,7 +354,7 @@ export interface KubernetesServiceLocator { }>; } -// @alpha (undocumented) +// @public (undocumented) export class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator { // (undocumented) decorateClusterDetailsWithAuth( @@ -362,7 +362,7 @@ export class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator { ): Promise; } -// @alpha (undocumented) +// @public (undocumented) export interface ObjectFetchParams { // (undocumented) clusterDetails: @@ -382,10 +382,10 @@ export interface ObjectFetchParams { serviceId: string; } -// @alpha (undocumented) +// @public (undocumented) export type ObjectsByEntityRequest = KubernetesRequestBody; -// @alpha (undocumented) +// @public (undocumented) export interface ObjectToFetch { // (undocumented) apiVersion: string; @@ -397,7 +397,7 @@ export interface ObjectToFetch { plural: string; } -// @alpha (undocumented) +// @public (undocumented) export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator { // (undocumented) decorateClusterDetailsWithAuth( @@ -406,7 +406,7 @@ export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator { ): Promise; } -// @alpha (undocumented) +// @public (undocumented) export interface RouterOptions { // (undocumented) catalogApi: CatalogApi; @@ -420,13 +420,13 @@ export interface RouterOptions { logger: Logger; } -// @alpha (undocumented) +// @public (undocumented) export interface ServiceAccountClusterDetails extends ClusterDetails {} -// @alpha (undocumented) +// @public (undocumented) export type ServiceLocatorMethod = 'multiTenant' | 'http'; -// @alpha (undocumented) +// @public (undocumented) export interface ServiceLocatorRequestContext { // (undocumented) customResources: CustomResourceMatcher[]; @@ -434,7 +434,7 @@ export interface ServiceLocatorRequestContext { objectTypesToFetch: Set; } -// @alpha (undocumented) +// @public (undocumented) export type SigningCreds = { accessKeyId: string | undefined; secretAccessKey: string | undefined; diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index 463b4126eb..2cc2674a9e 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -101,7 +101,7 @@ export interface DeploymentResources { replicaSets: V1ReplicaSet[]; } -// @alpha +// @public export interface DetectedError { // (undocumented) cluster: string; @@ -117,10 +117,10 @@ export interface DetectedError { severity: ErrorSeverity; } -// @alpha +// @public export type DetectedErrorsByCluster = Map; -// @alpha +// @public export const detectErrors: ( objects: ObjectsByEntityResponse, ) => DetectedErrorsByCluster; @@ -137,7 +137,7 @@ export type EntityKubernetesContentProps = { refreshIntervalMs?: number; }; -// @alpha +// @public export type ErrorDetectableKind = | 'Pod' | 'Deployment' @@ -161,7 +161,7 @@ export const ErrorReporting: ({ detectedErrors, }: ErrorReportingProps) => JSX.Element; -// @alpha +// @public export type ErrorSeverity = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; // Warning: (ae-forgotten-export) The symbol "FormatClusterLinkOptions" needs to be exported by the entry point index.d.ts diff --git a/plugins/kubernetes/src/error-detection/error-detection.ts b/plugins/kubernetes/src/error-detection/error-detection.ts index 3a9f1571e0..fddd4d838a 100644 --- a/plugins/kubernetes/src/error-detection/error-detection.ts +++ b/plugins/kubernetes/src/error-detection/error-detection.ts @@ -25,7 +25,7 @@ import { detectErrorsInHpa } from './hpas'; * For each cluster try to find errors in each of the object types provided * returning a map of cluster names to errors in that cluster * - * @alpha + * @public */ export const detectErrors = ( objects: ObjectsByEntityResponse, diff --git a/plugins/kubernetes/src/error-detection/types.ts b/plugins/kubernetes/src/error-detection/types.ts index 5e35cef8b6..4bc7ae164d 100644 --- a/plugins/kubernetes/src/error-detection/types.ts +++ b/plugins/kubernetes/src/error-detection/types.ts @@ -24,7 +24,7 @@ import { /** * Severity of the error, where 10 is critical and 0 is very low. * - * @alpha + * @public */ export type ErrorSeverity = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; @@ -33,7 +33,7 @@ export type ErrorDetectable = V1Pod | V1Deployment | V1HorizontalPodAutoscaler; /** * Kubernetes kinds that errors might be reported by the plugin * - * @alpha + * @public */ export type ErrorDetectableKind = | 'Pod' @@ -43,14 +43,14 @@ export type ErrorDetectableKind = /** * A list of errors keyed by Cluster name * - * @alpha + * @public */ export type DetectedErrorsByCluster = Map; /** * Represents an error found on a Kubernetes object * - * @alpha + * @public */ export interface DetectedError { severity: ErrorSeverity; diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index 3f712fe362..569fb5c6ea 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -137,17 +137,17 @@ export const createPermissionRule: < rule: PermissionRule, ) => PermissionRule; -// @alpha +// @public export const isAndCriteria: ( criteria: PermissionCriteria, ) => criteria is AllOfCriteria; -// @alpha +// @public export const isNotCriteria: ( criteria: PermissionCriteria, ) => criteria is NotCriteria; -// @alpha +// @public export const isOrCriteria: ( criteria: PermissionCriteria, ) => criteria is AnyOfCriteria; diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 7030affeea..df1670e718 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -6,7 +6,7 @@ /// import { ApiHolder } from '@backstage/core-plugin-api'; -import { ApiRef } from '@backstage/core-plugin-api'; +import { ApiRef } from '@backstage/core-plugin-api/*'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { createScaffolderFieldExtension as createScaffolderFieldExtension_2 } from '@backstage/plugin-scaffolder-react'; @@ -32,6 +32,7 @@ import { PathParams } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { RouteRef as RouteRef_2 } from '@backstage/core-plugin-api/*'; import { ScaffolderApi as ScaffolderApi_2 } from '@backstage/plugin-scaffolder-react'; import { ScaffolderDryRunOptions as ScaffolderDryRunOptions_2 } from '@backstage/plugin-scaffolder-react'; import { ScaffolderDryRunResponse as ScaffolderDryRunResponse_2 } from '@backstage/plugin-scaffolder-react'; @@ -109,9 +110,9 @@ export type EntityPickerUiOptions = export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< string[], { - helperText?: string | undefined; - kinds?: string[] | undefined; showCounts?: boolean | undefined; + kinds?: string[] | undefined; + helperText?: string | undefined; } >; @@ -119,9 +120,9 @@ export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< export const EntityTagsPickerFieldSchema: FieldSchema< string[], { - helperText?: string | undefined; - kinds?: string[] | undefined; showCounts?: boolean | undefined; + kinds?: string[] | undefined; + helperText?: string | undefined; } >; @@ -259,8 +260,8 @@ export const RepoUrlPickerFieldExtension: FieldExtensionComponent_2< | { azure?: string[] | undefined; github?: string[] | undefined; - bitbucket?: string[] | undefined; gitlab?: string[] | undefined; + bitbucket?: string[] | undefined; gerrit?: string[] | undefined; } | undefined; @@ -285,8 +286,8 @@ export const RepoUrlPickerFieldSchema: FieldSchema< | { azure?: string[] | undefined; github?: string[] | undefined; - bitbucket?: string[] | undefined; gitlab?: string[] | undefined; + bitbucket?: string[] | undefined; gerrit?: string[] | undefined; } | undefined; @@ -315,7 +316,7 @@ export type ReviewStepProps = { }; // @public @deprecated (undocumented) -export const rootRouteRef: RouteRef; +export const rootRouteRef: RouteRef_2; // @public export type RouterProps = { diff --git a/plugins/sonarqube/api-report.md b/plugins/sonarqube/api-report.md index db3f38e31d..cdbe839543 100644 --- a/plugins/sonarqube/api-report.md +++ b/plugins/sonarqube/api-report.md @@ -7,11 +7,11 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model'; -import { FindingSummary } from '@backstage/plugin-sonarqube-react'; +import { Entity } from '@backstage/catalog-model/*'; +import { FindingSummary } from '@backstage/plugin-sonarqube-react/alpha'; import { IdentityApi } from '@backstage/core-plugin-api'; import { InfoCardVariants } from '@backstage/core-components'; -import { SonarQubeApi } from '@backstage/plugin-sonarqube-react'; +import { SonarQubeApi } from '@backstage/plugin-sonarqube-react/alpha'; // @public (undocumented) export type DuplicationRating = { From a117491a92c69ab106aad49200d694c1db61d8a1 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 2 Feb 2023 20:33:52 +0100 Subject: [PATCH 370/417] update cli reports Signed-off-by: Patrik Oldsberg --- packages/cli/cli-report.md | 10 ++++++++++ packages/repo-tools/cli-report.md | 1 + 2 files changed, 11 insertions(+) diff --git a/packages/cli/cli-report.md b/packages/cli/cli-report.md index fa9a2aca8d..bad849d283 100644 --- a/packages/cli/cli-report.md +++ b/packages/cli/cli-report.md @@ -127,11 +127,21 @@ Options: Commands: package-roles package-scripts + package-exports package-lint-configs react-router-deps help [command] ``` +### `backstage-cli migrate package-exports` + +``` +Usage: backstage-cli migrate package-exports [options] + +Options: + -h, --help +``` + ### `backstage-cli migrate package-lint-configs` ``` diff --git a/packages/repo-tools/cli-report.md b/packages/repo-tools/cli-report.md index 3378d20ea7..0e1b2d2a4c 100644 --- a/packages/repo-tools/cli-report.md +++ b/packages/repo-tools/cli-report.md @@ -29,6 +29,7 @@ Options: -a, --allow-warnings --allow-all-warnings -o, --omit-messages + --validate-release-tags -h, --help ``` From cab2437a0b5dff956ababd107f3399fe0bfad820 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 15:44:09 +0100 Subject: [PATCH 371/417] repo-tools: skip doc generation for non-index entrypoints Signed-off-by: Patrik Oldsberg --- packages/repo-tools/src/commands/api-reports/api-extractor.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index dcd0631614..0c23d42437 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -424,7 +424,9 @@ export async function runApiExtraction({ }, docModel: { - enabled: true, + // TODO(Rugvip): This skips docs for non-index entry points. We can try to work around it, but + // most likely it makes sense to wait for API Extractor to natively support exports. + enabled: name === 'index', apiJsonFilePath: resolvePath( outputDir, `${prefix}.api.json`, From 3192c96e82aec00f9b88b4e0f257b426d3e3a48d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 16:50:00 +0100 Subject: [PATCH 372/417] repo-tools: update type-deps to analyze all entry points Signed-off-by: Patrik Oldsberg --- .../src/commands/api-reports/api-extractor.ts | 35 +++++------------ .../src/commands/type-deps/type-deps.ts | 15 ++++--- packages/repo-tools/src/lib/entryPoints.ts | 39 +++++++++++++++++++ 3 files changed, 59 insertions(+), 30 deletions(-) create mode 100644 packages/repo-tools/src/lib/entryPoints.ts diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index 0c23d42437..1fe7602617 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -19,7 +19,6 @@ import { relative as relativePath, basename, join, - extname, } from 'path'; import { execFile } from 'child_process'; import fs from 'fs-extra'; @@ -63,6 +62,7 @@ import { IMarkdownEmitterContext } from '@microsoft/api-documenter/lib/markdown/ import { AstDeclaration } from '@microsoft/api-extractor/lib/analyzer/AstDeclaration'; import { paths as cliPaths } from '../../lib/paths'; import minimatch from 'minimatch'; +import { getPackageExportNames } from '../../lib/entryPoints'; const tmpDir = cliPaths.resolveTargetRoot( './node_modules/.cache/api-extractor', @@ -313,30 +313,15 @@ async function findPackageEntryPoints(packageDirs: string[]): Promise< cliPaths.resolveTargetRoot(packageDir, 'package.json'), ); - if (pkg.exports && typeof pkg.exports !== 'string') { - return Object.entries(pkg.exports).flatMap(([mount, path]) => { - const ext = extname(String(path)); - if (!['.ts', '.tsx', '.cts', '.mts'].includes(ext)) { - return []; // Ignore non-TS entry points - } - let name = mount; - if (name.startsWith('./')) { - name = name.slice(2); - } - if (!name || name === '.') { - return [{ packageDir, name: 'index' }]; - } - return [{ packageDir, name }]; - }); - } - - return { - packageDir, - name: 'index', - usesExperimentalTypeBuild: pkg.scripts?.build?.includes( - '--experimental-type-build', - ), - }; + return ( + getPackageExportNames(pkg)?.map(name => ({ packageDir, name })) ?? { + packageDir, + name: 'index', + usesExperimentalTypeBuild: pkg.scripts?.build?.includes( + '--experimental-type-build', + ), + } + ); }), ).then(results => results.flat()); } diff --git a/packages/repo-tools/src/commands/type-deps/type-deps.ts b/packages/repo-tools/src/commands/type-deps/type-deps.ts index 0ad9a5cfc8..17164cea39 100644 --- a/packages/repo-tools/src/commands/type-deps/type-deps.ts +++ b/packages/repo-tools/src/commands/type-deps/type-deps.ts @@ -20,6 +20,7 @@ import { resolve as resolvePath } from 'path'; // eslint-disable-next-line @backstage/no-undeclared-imports import chalk from 'chalk'; import { getPackages, Package } from '@manypkg/get-packages'; +import { getPackageExportNames } from '../../lib/entryPoints'; export default async () => { const { packages } = await getPackages(resolvePath('.')); @@ -96,11 +97,15 @@ function findAllDeps(declSrc: string) { * missing or incorrect in package.json */ function checkTypes(pkg: Package) { - const typeDecl = fs.readFileSync( - resolvePath(pkg.dir, 'dist/index.d.ts'), - 'utf8', - ); - const allDeps = findAllDeps(typeDecl); + const entryPointNames = getPackageExportNames(pkg.packageJson) ?? ['index']; + + const allDeps = entryPointNames.flatMap(name => { + const typeDecl = fs.readFileSync( + resolvePath(pkg.dir, `dist/${name}.d.ts`), + 'utf8', + ); + return findAllDeps(typeDecl); + }); const deps = Array.from(new Set(allDeps)); const errors = []; diff --git a/packages/repo-tools/src/lib/entryPoints.ts b/packages/repo-tools/src/lib/entryPoints.ts new file mode 100644 index 0000000000..df5633c103 --- /dev/null +++ b/packages/repo-tools/src/lib/entryPoints.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { extname } from 'path'; +import { JsonObject } from '@backstage/types'; + +export function getPackageExportNames(pkg: JsonObject): string[] | undefined { + if (pkg.exports && typeof pkg.exports !== 'string') { + return Object.entries(pkg.exports).flatMap(([mount, path]) => { + const ext = extname(String(path)); + if (!['.ts', '.tsx', '.cts', '.mts'].includes(ext)) { + return []; // Ignore non-TS entry points + } + let name = mount; + if (name.startsWith('./')) { + name = name.slice(2); + } + if (!name || name === '.') { + return ['index']; + } + return [name]; + }); + } + + return undefined; +} From b6674828e7cd85037f3d82efaec48de241a3bb99 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 17:13:05 +0100 Subject: [PATCH 373/417] cli: avoid error when attempting to production pack packages without dist dir Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/packager/productionPack.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index adcab2b90c..3a74b68257 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -181,7 +181,11 @@ async function prepareExportsEntryPoints( pkg: ExtendedPackageJSON, packageDir: string, ) { - const distFiles = await fs.readdir(resolvePath(packageDir, 'dist')); + const distPath = resolvePath(packageDir, 'dist'); + if (!(await fs.pathExists(distPath))) { + return undefined; + } + const distFiles = await fs.readdir(distPath); const outputExports = {} as Record>; const compatibilityWriters = new Array< From efbd99efd75ee757cb8aebcf4c7dd1af4e82d7f4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 17:26:47 +0100 Subject: [PATCH 374/417] remove index entry from typesVersions Signed-off-by: Patrik Oldsberg --- packages/backend-common/package.json | 3 --- packages/backend-test-utils/package.json | 3 --- packages/catalog-model/package.json | 3 --- .../cli/src/commands/migrate/packageExports.ts | 6 +++++- packages/core-plugin-api/package.json | 3 --- packages/test-utils/package.json | 3 --- plugins/app-backend/package.json | 3 --- plugins/catalog-backend-module-aws/package.json | 3 --- plugins/catalog-backend-module-azure/package.json | 3 --- .../package.json | 3 --- .../package.json | 3 --- plugins/catalog-backend-module-gerrit/package.json | 3 --- .../catalog-backend-module-github/api-report.md | 2 +- plugins/catalog-backend-module-github/package.json | 3 --- plugins/catalog-backend-module-gitlab/package.json | 3 --- .../package.json | 3 --- .../catalog-backend-module-msgraph/package.json | 3 --- plugins/catalog-backend/alpha-api-report.md | 14 ++++---------- plugins/catalog-backend/package.json | 3 --- plugins/catalog-common/package.json | 3 --- plugins/catalog-node/package.json | 3 --- plugins/catalog-react/package.json | 3 --- plugins/events-backend-module-aws-sqs/package.json | 3 --- plugins/events-backend-module-azure/package.json | 3 --- .../package.json | 3 --- plugins/events-backend-module-gerrit/package.json | 3 --- plugins/events-backend-module-github/package.json | 3 --- plugins/events-backend-module-gitlab/package.json | 3 --- plugins/events-backend/package.json | 3 --- plugins/events-node/package.json | 3 --- plugins/scaffolder-backend/package.json | 3 --- plugins/scaffolder-react/package.json | 3 --- plugins/scaffolder/api-report.md | 5 ++--- plugins/scaffolder/package.json | 3 --- plugins/sonarqube-react/package.json | 3 --- plugins/sonarqube/api-report.md | 2 +- 36 files changed, 13 insertions(+), 109 deletions(-) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 71f800dff8..7973ae6111 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 7e14963aab..7bcb680dfe 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -13,9 +13,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "package.json": [ "package.json" ] diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 2d569053b1..b391ad79e4 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/packages/cli/src/commands/migrate/packageExports.ts b/packages/cli/src/commands/migrate/packageExports.ts index 51dc5c38bd..ff01f939f9 100644 --- a/packages/cli/src/commands/migrate/packageExports.ts +++ b/packages/cli/src/commands/migrate/packageExports.ts @@ -59,7 +59,11 @@ export async function command() { const typeEntries: Record = {}; for (const [path, value] of Object.entries(exp)) { - const newPath = path === '.' ? '*' : trimRelative(path); + // Main entry point does not need to be listed + if (path === '.') { + continue; + } + const newPath = trimRelative(path); if (typeof value === 'string') { typeEntries[newPath] = [trimRelative(value)]; diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 781ebe37e1..d34d13dbe1 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -12,9 +12,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index b278b00c14..192d58fd14 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -12,9 +12,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 78070cbf14..ae2c61311c 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 0273326e36..61cf55d546 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index dd89aec185..ecaf9fb9cc 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 8fbff7d79b..5d6c80a0cb 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 1a82807288..811dfe9f10 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 33fcc4abcb..95978c2502 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-github/api-report.md b/plugins/catalog-backend-module-github/api-report.md index 0ad377952a..e2b73d267b 100644 --- a/plugins/catalog-backend-module-github/api-report.md +++ b/plugins/catalog-backend-module-github/api-report.md @@ -7,7 +7,7 @@ import { AnalyzeOptions } from '@backstage/plugin-catalog-backend'; import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; -import { Entity } from '@backstage/catalog-model/*'; +import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-backend'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; import { EventParams } from '@backstage/plugin-events-node'; diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index a5899ced33..ccf1be3b2a 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 8d1ec70123..cbd07944d9 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 9479fd88e0..5f49cb8905 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 99e5b0da35..1cc3855d77 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-backend/alpha-api-report.md b/plugins/catalog-backend/alpha-api-report.md index 46be9a27df..df2fa3d2e9 100644 --- a/plugins/catalog-backend/alpha-api-report.md +++ b/plugins/catalog-backend/alpha-api-report.md @@ -6,8 +6,7 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; import { Conditions } from '@backstage/plugin-permission-node'; -import { Entity } from '@backstage/catalog-model/*'; -import { Entity as Entity_2 } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; import { PermissionCondition } from '@backstage/plugin-permission-common'; import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; @@ -72,7 +71,7 @@ export const catalogConditions: Conditions<{ // @alpha export type CatalogPermissionRule< TParams extends PermissionRuleParams = PermissionRuleParams, -> = PermissionRule; +> = PermissionRule; // @alpha export const catalogPlugin: () => BackendFeature; @@ -89,13 +88,8 @@ export const createCatalogConditionalDecision: ( export const createCatalogPermissionRule: < TParams extends PermissionRuleParams = undefined, >( - rule: PermissionRule< - Entity_2, - EntitiesSearchFilter, - 'catalog-entity', - TParams - >, -) => PermissionRule; + rule: PermissionRule, +) => PermissionRule; // @public export type EntitiesSearchFilter = { diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 47e678c012..17e9c9aa7c 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 2c74307f1c..27b31d15ea 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 7d186ad52c..6c888f342e 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 955e63b425..e8f796a725 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index d68c77bb41..2e45015bce 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index a1314b2db7..a3acd37263 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index db85c32fad..ae006b1bce 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 35a82b4fc5..a7aadf06dc 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 7a7df507b7..966b7b3592 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index f95995473c..4e5e53771d 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index a0d4f9bf12..d779869e14 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -14,9 +14,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index ef0cce170e..368e567930 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 9ee87669ff..121a5c8ed0 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 6907f8080e..14d25136e0 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index df1670e718..43cc657a03 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -6,7 +6,7 @@ /// import { ApiHolder } from '@backstage/core-plugin-api'; -import { ApiRef } from '@backstage/core-plugin-api/*'; +import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; import { createScaffolderFieldExtension as createScaffolderFieldExtension_2 } from '@backstage/plugin-scaffolder-react'; @@ -32,7 +32,6 @@ import { PathParams } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; -import { RouteRef as RouteRef_2 } from '@backstage/core-plugin-api/*'; import { ScaffolderApi as ScaffolderApi_2 } from '@backstage/plugin-scaffolder-react'; import { ScaffolderDryRunOptions as ScaffolderDryRunOptions_2 } from '@backstage/plugin-scaffolder-react'; import { ScaffolderDryRunResponse as ScaffolderDryRunResponse_2 } from '@backstage/plugin-scaffolder-react'; @@ -316,7 +315,7 @@ export type ReviewStepProps = { }; // @public @deprecated (undocumented) -export const rootRouteRef: RouteRef_2; +export const rootRouteRef: RouteRef; // @public export type RouterProps = { diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 46e8f436fd..15893b7ccb 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -15,9 +15,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "alpha": [ "src/alpha.ts" ], diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 2f31d37007..80177d9e24 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -13,9 +13,6 @@ }, "typesVersions": { "*": { - "*": [ - "src/index.ts" - ], "package.json": [ "package.json" ] diff --git a/plugins/sonarqube/api-report.md b/plugins/sonarqube/api-report.md index cdbe839543..baf796b34c 100644 --- a/plugins/sonarqube/api-report.md +++ b/plugins/sonarqube/api-report.md @@ -7,7 +7,7 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model/*'; +import { Entity } from '@backstage/catalog-model'; import { FindingSummary } from '@backstage/plugin-sonarqube-react/alpha'; import { IdentityApi } from '@backstage/core-plugin-api'; import { InfoCardVariants } from '@backstage/core-components'; From d443f9ebba6b496c90b7fc446d11f5f02c175d22 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sat, 4 Feb 2023 17:59:02 +0100 Subject: [PATCH 375/417] cli: always make package.json available in exports in published packages Signed-off-by: Patrik Oldsberg --- packages/cli/src/lib/packager/productionPack.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/lib/packager/productionPack.ts b/packages/cli/src/lib/packager/productionPack.ts index 3a74b68257..b91112216a 100644 --- a/packages/cli/src/lib/packager/productionPack.ts +++ b/packages/cli/src/lib/packager/productionPack.ts @@ -128,7 +128,7 @@ export async function revertProductionPack(packageDir: string) { // Remove any extra entrypoint backwards compatibility directories const entryPoints = readEntryPoints(pkg); for (const entryPoint of entryPoints) { - if (entryPoint.mount !== '.') { + if (entryPoint.mount !== '.' && SCRIPT_EXTS.includes(entryPoint.ext)) { await fs.remove(resolvePath(packageDir, entryPoint.name)); } } @@ -244,7 +244,11 @@ async function prepareExportsEntryPoints( } } - pkg.exports = outputExports; + if (pkg.exports) { + pkg.exports = outputExports; + // We treat package.json as a fixed export that is always available in the published package + pkg.exports['./package.json'] = './package.json'; + } if (compatibilityWriters.length > 0) { return async (targetDir: string) => { From 58814d6d4cd6d63462a75d3389fe5f78406e09ac Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 15 Feb 2023 16:45:49 +0100 Subject: [PATCH 376/417] fix stray imports Signed-off-by: Patrik Oldsberg --- packages/backend-defaults/src/CreateBackend.test.ts | 2 +- .../BitbucketCloudEntityProviderCatalogModule.test.ts | 5 +---- plugins/sonarqube/api-report.md | 4 ++-- plugins/sonarqube/dev/index.tsx | 2 +- plugins/sonarqube/src/api/SonarQubeClient.test.ts | 2 +- plugins/sonarqube/src/api/SonarQubeClient.ts | 2 +- plugins/sonarqube/src/api/types.ts | 2 +- .../sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx | 2 +- .../SonarQubeContentPage/SonarQubeContentPage.test.tsx | 2 -- plugins/sonarqube/src/plugin.ts | 2 +- plugins/todo-backend/src/service/TodoReaderService.ts | 2 +- 11 files changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts index cc6c93c0eb..8d56cd0986 100644 --- a/packages/backend-defaults/src/CreateBackend.test.ts +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -21,7 +21,7 @@ import { createServiceRef, createSharedEnvironment, } from '@backstage/backend-plugin-api'; -import { mockServices } from '@backstage/backend-test-utils/alpha'; +import { mockServices } from '@backstage/backend-test-utils'; import { createBackend } from './CreateBackend'; const fooServiceRef = createServiceRef({ id: 'foo', scope: 'root' }); diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts index 13ad5dbf22..630c18b134 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.test.ts @@ -19,10 +19,7 @@ import { PluginTaskScheduler, TaskScheduleDefinition, } from '@backstage/backend-tasks'; -import { - startTestBackend, - mockServices, -} from '@backstage/backend-test-utils/alpha'; +import { startTestBackend, mockServices } from '@backstage/backend-test-utils'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { Duration } from 'luxon'; diff --git a/plugins/sonarqube/api-report.md b/plugins/sonarqube/api-report.md index baf796b34c..db3f38e31d 100644 --- a/plugins/sonarqube/api-report.md +++ b/plugins/sonarqube/api-report.md @@ -8,10 +8,10 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; -import { FindingSummary } from '@backstage/plugin-sonarqube-react/alpha'; +import { FindingSummary } from '@backstage/plugin-sonarqube-react'; import { IdentityApi } from '@backstage/core-plugin-api'; import { InfoCardVariants } from '@backstage/core-components'; -import { SonarQubeApi } from '@backstage/plugin-sonarqube-react/alpha'; +import { SonarQubeApi } from '@backstage/plugin-sonarqube-react'; // @public (undocumented) export type DuplicationRating = { diff --git a/plugins/sonarqube/dev/index.tsx b/plugins/sonarqube/dev/index.tsx index 98c48c56fc..8d38c7314a 100644 --- a/plugins/sonarqube/dev/index.tsx +++ b/plugins/sonarqube/dev/index.tsx @@ -24,7 +24,7 @@ import { FindingSummary, SonarQubeApi, sonarQubeApiRef, -} from '@backstage/plugin-sonarqube-react/alpha'; +} from '@backstage/plugin-sonarqube-react'; import { SONARQUBE_PROJECT_KEY_ANNOTATION } from '@backstage/plugin-sonarqube-react'; const entity = (name?: string) => diff --git a/plugins/sonarqube/src/api/SonarQubeClient.test.ts b/plugins/sonarqube/src/api/SonarQubeClient.test.ts index 441263afc8..592f08457f 100644 --- a/plugins/sonarqube/src/api/SonarQubeClient.test.ts +++ b/plugins/sonarqube/src/api/SonarQubeClient.test.ts @@ -21,7 +21,7 @@ import { SonarQubeClient } from './index'; import { InstanceUrlWrapper, FindingsWrapper } from './types'; import { UrlPatternDiscovery } from '@backstage/core-app-api'; import { IdentityApi } from '@backstage/core-plugin-api'; -import { FindingSummary } from '@backstage/plugin-sonarqube-react/alpha'; +import { FindingSummary } from '@backstage/plugin-sonarqube-react'; const server = setupServer(); diff --git a/plugins/sonarqube/src/api/SonarQubeClient.ts b/plugins/sonarqube/src/api/SonarQubeClient.ts index 94d7a96243..14c7936e92 100644 --- a/plugins/sonarqube/src/api/SonarQubeClient.ts +++ b/plugins/sonarqube/src/api/SonarQubeClient.ts @@ -19,7 +19,7 @@ import { FindingSummary, Metrics, SonarQubeApi, -} from '@backstage/plugin-sonarqube-react/alpha'; +} from '@backstage/plugin-sonarqube-react'; import { InstanceUrlWrapper, FindingsWrapper } from './types'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; diff --git a/plugins/sonarqube/src/api/types.ts b/plugins/sonarqube/src/api/types.ts index f3ad690261..29b7e7ca54 100644 --- a/plugins/sonarqube/src/api/types.ts +++ b/plugins/sonarqube/src/api/types.ts @@ -17,7 +17,7 @@ import { MetricKey as NonDeprecatedMetricKey, SonarUrlProcessorFunc as NonDeprecatedSonarUrlProcessorFunc, -} from '@backstage/plugin-sonarqube-react/alpha'; +} from '@backstage/plugin-sonarqube-react'; export interface InstanceUrlWrapper { instanceUrl: string; diff --git a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx index 3965c03b69..932641e48d 100644 --- a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx +++ b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx @@ -18,7 +18,7 @@ import { useEntity } from '@backstage/plugin-catalog-react'; import { sonarQubeApiRef, useProjectInfo, -} from '@backstage/plugin-sonarqube-react/alpha'; +} from '@backstage/plugin-sonarqube-react'; import { SONARQUBE_PROJECT_KEY_ANNOTATION } from '@backstage/plugin-sonarqube-react'; import { Chip, Grid } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; diff --git a/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx b/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx index 91e85f9f25..0bf5f04640 100644 --- a/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx +++ b/plugins/sonarqube/src/components/SonarQubeContentPage/SonarQubeContentPage.test.tsx @@ -20,8 +20,6 @@ import React from 'react'; import { SonarQubeApi, sonarQubeApiRef, -} from '@backstage/plugin-sonarqube-react/alpha'; -import { isSonarQubeAvailable, SONARQUBE_PROJECT_KEY_ANNOTATION, } from '@backstage/plugin-sonarqube-react'; diff --git a/plugins/sonarqube/src/plugin.ts b/plugins/sonarqube/src/plugin.ts index 8da690abbf..c66d8c4e96 100644 --- a/plugins/sonarqube/src/plugin.ts +++ b/plugins/sonarqube/src/plugin.ts @@ -22,7 +22,7 @@ import { discoveryApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { sonarQubeApiRef } from '@backstage/plugin-sonarqube-react/alpha'; +import { sonarQubeApiRef } from '@backstage/plugin-sonarqube-react'; /** @public */ export const sonarQubePlugin = createPlugin({ diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index c5fa0aa70b..6ce38709f1 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -25,7 +25,7 @@ import { createServiceRef, ServiceRef, } from '@backstage/backend-plugin-api'; -import { catalogServiceRef } from '@backstage/plugin-catalog-node'; +import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; import { TodoReader, todoReaderServiceRef } from '../lib'; import { ListTodosRequest, ListTodosResponse, TodoService } from './types'; From 9913f61e7a40fe598c6efffc46ab04524c12a2d6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 21 Feb 2023 14:56:26 +0100 Subject: [PATCH 377/417] todo-backend: mark public API as public Signed-off-by: Patrik Oldsberg --- plugins/todo-backend/api-report.md | 4 ++-- plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts | 2 +- plugins/todo-backend/src/plugin.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index dabe2fbfd4..6db1e012e9 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -90,7 +90,7 @@ export type TodoParserResult = { lineNumber: number; }; -// @alpha +// @public export const todoPlugin: () => BackendFeature; // @public (undocumented) @@ -118,7 +118,7 @@ export type TodoReaderServiceOptions = { defaultPageSize?: number; }; -// @alpha (undocumented) +// @public (undocumented) export const todoReaderServiceRef: ServiceRef; // @public (undocumented) diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts index 2804da98cc..276d176efb 100644 --- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts +++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts @@ -174,7 +174,7 @@ export class TodoScmReader implements TodoReader { } /** - * @alpha + * @public */ export const todoReaderServiceRef = createServiceRef({ id: 'todo.todoReader', diff --git a/plugins/todo-backend/src/plugin.ts b/plugins/todo-backend/src/plugin.ts index cbb581f336..b9a73a84ee 100644 --- a/plugins/todo-backend/src/plugin.ts +++ b/plugins/todo-backend/src/plugin.ts @@ -24,7 +24,7 @@ import { createRouter } from './service/router'; /** * The Todos plugin is responsible for aggregating todo comments within source. - * @alpha + * @public */ export const todoPlugin = createBackendPlugin({ pluginId: 'todo-backend', From aa5ed47b3999faea75fc128d1ec5ce200fbbaea4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 21 Feb 2023 15:04:15 +0100 Subject: [PATCH 378/417] scaffolder-react: fix API report warning Signed-off-by: Patrik Oldsberg --- plugins/scaffolder-react/alpha-api-report.md | 5 +---- .../components/TemplateOutputs/DefaultTemplateOutputs.tsx | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index 75d2e4fd79..ad44cd3707 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -22,6 +22,7 @@ import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RJSFSchema } from '@rjsf/utils'; +import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { SetStateAction } from 'react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; @@ -217,9 +218,5 @@ export type WorkflowProps = { | 'layouts' >; -// Warnings were encountered during analysis: -// -// src/next/components/TemplateOutputs/DefaultTemplateOutputs.d.ts:9:5 - (ae-forgotten-export) The symbol "ScaffolderTaskOutput" needs to be exported by the entry point alpha.d.ts - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx index 5fbd3a5142..4d908461b0 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { Box, Paper } from '@material-ui/core'; import { LinkOutputs } from './LinkOutputs'; -import { ScaffolderTaskOutput } from '../../../api'; +import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; /** * The DefaultOutputs renderer for the scaffolder task output From 99b3eff86e53db8f5b2705d8d596c09e1b136043 Mon Sep 17 00:00:00 2001 From: Jonathan Mezach Date: Tue, 21 Feb 2023 15:10:25 +0100 Subject: [PATCH 379/417] Remove private tag from package.json Signed-off-by: Jonathan Mezach --- plugins/octopus-deploy/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 047f325316..3a8e3213ea 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -4,7 +4,6 @@ "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", - "private": true, "publishConfig": { "access": "public", "main": "dist/index.esm.js", From 8f980890b51b899eac5d6747a2c0fb2f30c4abaf Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 15:26:17 +0100 Subject: [PATCH 380/417] chore: make valid mdx when transpiling Signed-off-by: blam --- packages/test-utils/src/testUtils/TestApiProvider.tsx | 4 ++-- .../git-release-manager/src/helpers/tagParts/getTagParts.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 35fa302415..f38433ace9 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -100,7 +100,7 @@ export class TestApiRegistry implements ApiHolder { * [identityApiRef, mockIdentityApi as unknown as IdentityApi] * ])} * > - * {...} + * // ... * * ) * ``` @@ -110,7 +110,7 @@ export class TestApiRegistry implements ApiHolder { * ```tsx * renderInTestApp( * - * {...} + * // ... * * ) * ``` diff --git a/plugins/git-release-manager/src/helpers/tagParts/getTagParts.ts b/plugins/git-release-manager/src/helpers/tagParts/getTagParts.ts index ba8412b2b4..3c500eb923 100644 --- a/plugins/git-release-manager/src/helpers/tagParts/getTagParts.ts +++ b/plugins/git-release-manager/src/helpers/tagParts/getTagParts.ts @@ -19,7 +19,7 @@ import { getSemverTagParts } from './getSemverTagParts'; import { Project } from '../../contexts/ProjectContext'; /** - * Tag parts are the individual parts of a version, e.g. .. + * Tag parts are the individual parts of a version, e.g. [major].[minor].[patch] * are the parts of a semantic version * * @public From bf2f2fa90ae51a54a1d9f06cea9face0471c228b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 21 Feb 2023 15:28:22 +0100 Subject: [PATCH 381/417] repo-tools: add missing types dep Signed-off-by: Patrik Oldsberg --- packages/repo-tools/package.json | 1 + packages/repo-tools/src/lib/entryPoints.ts | 2 +- yarn.lock | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 5a5683dff9..0fc5cc3554 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -45,6 +45,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", + "@backstage/types": "workspace:^", "@types/is-glob": "^4.0.2", "@types/mock-fs": "^4.13.0", "mock-fs": "^5.1.0" diff --git a/packages/repo-tools/src/lib/entryPoints.ts b/packages/repo-tools/src/lib/entryPoints.ts index df5633c103..4a412d410b 100644 --- a/packages/repo-tools/src/lib/entryPoints.ts +++ b/packages/repo-tools/src/lib/entryPoints.ts @@ -15,7 +15,7 @@ */ import { extname } from 'path'; -import { JsonObject } from '@backstage/types'; +import type { JsonObject } from '@backstage/types'; export function getPackageExportNames(pkg: JsonObject): string[] | undefined { if (pkg.exports && typeof pkg.exports !== 'string') { diff --git a/yarn.lock b/yarn.lock index aa8558da37..0438503db3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8618,6 +8618,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/types": "workspace:^" "@manypkg/get-packages": ^1.1.3 "@microsoft/api-documenter": ^7.19.27 "@microsoft/api-extractor": ^7.33.7 From 662af7fe5a48ed25eb04feb0a2af6e43fcdb63eb Mon Sep 17 00:00:00 2001 From: Binita Nayak <45393478+binitan@users.noreply.github.com> Date: Tue, 21 Feb 2023 16:17:18 +0100 Subject: [PATCH 382/417] updated SPOC updated SPOC Signed-off-by: Binita Nayak <45393478+binitan@users.noreply.github.com> --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 38e67adfee..f518a00338 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -159,7 +159,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Doctolib](https://doctolib.engineering/) | [@djiit](https://github.com/djiit) | Rails modularization effort awareness, tech organization discoverability. Improving the daily workflows and collaboration processes of our engineers. | | [Twilio](https://www.twilio.com) | [Kyle Smith](https://github.com/knksmith57) | Developer portal, universal software catalog, and centralized taxonomy platform. | | [OVHcloud](https://www.ovhcloud.com/fr/) | [Jean-Philippe Blary](https://github.com/blaryjp), [Arnaud Bauer](mailto:arnaud.bauer@ovhcloud.com), [Flavien Chantelot](https://github.com/Dorn-) | We're providing Backstage to our collaborators to ease their daily jobs, and let them extends it using plugins. | -| [Procter & Gamble](https://us.pg.com/) | [Binita Nayak](https://github.com/binitan), [Josh Rose](https://github.com/joshuarose), [RJ Winkler](https://github.com/rjwink) | P&G leverages Backstage to build internal developer portal to ensure developers' happiness. This developer portal shall act as single source of information needed by development teams to seamlessly create, find and maintain their software components/resources/documentation. | +| [Procter & Gamble](https://us.pg.com/) | [Binita Nayak](https://github.com/binitan), | P&G leverages Backstage to build internal developer portal to ensure developers' happiness. This developer portal shall act as single source of information needed by development teams to seamlessly create, find and maintain their software components/resources/documentation. | | [SANS Institute](https://www.sans.org) | [Christopher Klewin](mailto:cklewin@sans.org) | Developer portal for centralized visibility, reporting, and tooling across multiple organizations. | | [Okay](https://www.okayhq.com/) | [Tomas Barreto](mailto:tomas@okayhq.com) | Service catalog, developer portal, and technical documentation | | [Kaluza](https://www.kaluza.com) | [James Condron](mailto:james.condron@kaluza.com) | To provide an automated golden path to developers, with a focus on discovery and documentation | From b4627f23b2800958ec51a10c7b248e57dcef5e21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 21 Feb 2023 15:40:30 +0000 Subject: [PATCH 383/417] Version Packages (next) --- .changeset/create-app-1676993958.md | 5 + .changeset/pre.json | 44 +- docs/releases/v1.12.0-next.0-changelog.md | 2364 +++++++++++++++++ package.json | 2 +- packages/app-defaults/CHANGELOG.md | 11 + packages/app-defaults/package.json | 2 +- packages/app/CHANGELOG.md | 69 + packages/app/package.json | 2 +- packages/backend-app-api/CHANGELOG.md | 17 + packages/backend-app-api/package.json | 2 +- packages/backend-common/CHANGELOG.md | 16 + packages/backend-common/package.json | 2 +- packages/backend-defaults/CHANGELOG.md | 9 + packages/backend-defaults/package.json | 2 +- packages/backend-next/CHANGELOG.md | 11 + packages/backend-next/package.json | 2 +- packages/backend-plugin-api/CHANGELOG.md | 12 + packages/backend-plugin-api/package.json | 2 +- packages/backend-tasks/CHANGELOG.md | 11 + packages/backend-tasks/package.json | 2 +- packages/backend-test-utils/CHANGELOG.md | 13 + packages/backend-test-utils/package.json | 2 +- packages/backend/CHANGELOG.md | 51 + packages/backend/package.json | 2 +- packages/catalog-client/CHANGELOG.md | 12 + packages/catalog-client/package.json | 2 +- packages/catalog-model/CHANGELOG.md | 10 + packages/catalog-model/package.json | 2 +- packages/cli/CHANGELOG.md | 16 + packages/cli/package.json | 2 +- packages/core-app-api/CHANGELOG.md | 10 + packages/core-app-api/package.json | 2 +- packages/core-components/CHANGELOG.md | 11 + packages/core-components/package.json | 2 +- packages/core-plugin-api/CHANGELOG.md | 10 + packages/core-plugin-api/package.json | 2 +- packages/create-app/CHANGELOG.md | 8 + packages/create-app/package.json | 2 +- packages/dev-utils/CHANGELOG.md | 15 + packages/dev-utils/package.json | 2 +- packages/e2e-test/CHANGELOG.md | 9 + packages/e2e-test/package.json | 2 +- packages/eslint-plugin/CHANGELOG.md | 6 + packages/eslint-plugin/package.json | 2 +- packages/integration-react/CHANGELOG.md | 11 + packages/integration-react/package.json | 2 +- packages/repo-tools/CHANGELOG.md | 10 + packages/repo-tools/package.json | 2 +- .../techdocs-cli-embedded-app/CHANGELOG.md | 19 + .../techdocs-cli-embedded-app/package.json | 2 +- packages/techdocs-cli/CHANGELOG.md | 11 + packages/techdocs-cli/package.json | 2 +- packages/test-utils/CHANGELOG.md | 14 + packages/test-utils/package.json | 2 +- plugins/adr-backend/CHANGELOG.md | 15 + plugins/adr-backend/package.json | 2 +- plugins/adr-common/CHANGELOG.md | 9 + plugins/adr-common/package.json | 2 +- plugins/adr/CHANGELOG.md | 15 + plugins/adr/package.json | 2 +- plugins/airbrake-backend/CHANGELOG.md | 8 + plugins/airbrake-backend/package.json | 2 +- plugins/airbrake/CHANGELOG.md | 13 + plugins/airbrake/package.json | 2 +- plugins/allure/CHANGELOG.md | 11 + plugins/allure/package.json | 2 +- plugins/analytics-module-ga/CHANGELOG.md | 10 + plugins/analytics-module-ga/package.json | 2 +- plugins/apache-airflow/CHANGELOG.md | 8 + plugins/apache-airflow/package.json | 2 +- plugins/api-docs/CHANGELOG.md | 13 + plugins/api-docs/package.json | 2 +- plugins/apollo-explorer/CHANGELOG.md | 9 + plugins/apollo-explorer/package.json | 2 +- plugins/app-backend/CHANGELOG.md | 12 + plugins/app-backend/package.json | 2 +- plugins/auth-backend/CHANGELOG.md | 14 + plugins/auth-backend/package.json | 2 +- plugins/auth-node/CHANGELOG.md | 9 + plugins/auth-node/package.json | 2 +- plugins/azure-devops-backend/CHANGELOG.md | 9 + plugins/azure-devops-backend/package.json | 2 +- plugins/azure-devops/CHANGELOG.md | 13 + plugins/azure-devops/package.json | 2 +- plugins/azure-sites-backend/CHANGELOG.md | 9 + plugins/azure-sites-backend/package.json | 2 +- plugins/azure-sites/CHANGELOG.md | 12 + plugins/azure-sites/package.json | 2 +- plugins/badges-backend/CHANGELOG.md | 11 + plugins/badges-backend/package.json | 2 +- plugins/badges/CHANGELOG.md | 12 + plugins/badges/package.json | 2 +- plugins/bazaar-backend/CHANGELOG.md | 11 + plugins/bazaar-backend/package.json | 2 +- plugins/bazaar/CHANGELOG.md | 15 + plugins/bazaar/package.json | 2 +- plugins/bitrise/CHANGELOG.md | 11 + plugins/bitrise/package.json | 2 +- .../catalog-backend-module-aws/CHANGELOG.md | 20 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 17 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 19 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 14 + .../package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 20 + .../package.json | 2 +- .../CHANGELOG.md | 17 + .../package.json | 2 +- .../CHANGELOG.md | 19 + .../package.json | 2 +- .../catalog-backend-module-ldap/CHANGELOG.md | 12 + .../catalog-backend-module-ldap/package.json | 2 +- .../CHANGELOG.md | 16 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- plugins/catalog-backend/CHANGELOG.md | 28 + plugins/catalog-backend/package.json | 2 +- plugins/catalog-common/CHANGELOG.md | 10 + plugins/catalog-common/package.json | 2 +- plugins/catalog-customized/CHANGELOG.md | 8 + plugins/catalog-customized/package.json | 2 +- plugins/catalog-graph/CHANGELOG.md | 12 + plugins/catalog-graph/package.json | 2 +- plugins/catalog-graphql/CHANGELOG.md | 9 + plugins/catalog-graphql/package.json | 2 +- plugins/catalog-import/CHANGELOG.md | 16 + plugins/catalog-import/package.json | 2 +- plugins/catalog-node/CHANGELOG.md | 13 + plugins/catalog-node/package.json | 2 +- plugins/catalog-react/CHANGELOG.md | 23 + plugins/catalog-react/package.json | 2 +- plugins/catalog/CHANGELOG.md | 23 + plugins/catalog/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/cicd-statistics/CHANGELOG.md | 9 + plugins/cicd-statistics/package.json | 2 +- plugins/circleci/CHANGELOG.md | 11 + plugins/circleci/package.json | 2 +- plugins/cloudbuild/CHANGELOG.md | 11 + plugins/cloudbuild/package.json | 2 +- plugins/code-climate/CHANGELOG.md | 11 + plugins/code-climate/package.json | 2 +- plugins/code-coverage-backend/CHANGELOG.md | 12 + plugins/code-coverage-backend/package.json | 2 +- plugins/code-coverage/CHANGELOG.md | 13 + plugins/code-coverage/package.json | 2 +- plugins/codescene/CHANGELOG.md | 11 + plugins/codescene/package.json | 2 +- plugins/config-schema/CHANGELOG.md | 12 + plugins/config-schema/package.json | 2 +- plugins/cost-insights/CHANGELOG.md | 14 + plugins/cost-insights/package.json | 2 +- plugins/dynatrace/CHANGELOG.md | 11 + plugins/dynatrace/package.json | 2 +- plugins/entity-feedback-backend/CHANGELOG.md | 12 + plugins/entity-feedback-backend/package.json | 2 +- plugins/entity-feedback/CHANGELOG.md | 13 + plugins/entity-feedback/package.json | 2 +- plugins/entity-validation/CHANGELOG.md | 14 + plugins/entity-validation/package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../events-backend-module-azure/CHANGELOG.md | 9 + .../events-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../events-backend-module-gerrit/CHANGELOG.md | 9 + .../events-backend-module-gerrit/package.json | 2 +- .../events-backend-module-github/CHANGELOG.md | 10 + .../events-backend-module-github/package.json | 2 +- .../events-backend-module-gitlab/CHANGELOG.md | 10 + .../events-backend-module-gitlab/package.json | 2 +- .../events-backend-test-utils/CHANGELOG.md | 7 + .../events-backend-test-utils/package.json | 2 +- plugins/events-backend/CHANGELOG.md | 11 + plugins/events-backend/package.json | 2 +- plugins/events-node/CHANGELOG.md | 8 + plugins/events-node/package.json | 2 +- .../example-todo-list-backend/CHANGELOG.md | 11 + .../example-todo-list-backend/package.json | 2 +- plugins/example-todo-list/CHANGELOG.md | 9 + plugins/example-todo-list/package.json | 2 +- plugins/explore-backend/CHANGELOG.md | 10 + plugins/explore-backend/package.json | 2 +- plugins/explore-react/CHANGELOG.md | 8 + plugins/explore-react/package.json | 2 +- plugins/explore/CHANGELOG.md | 17 + plugins/explore/package.json | 2 +- plugins/firehydrant/CHANGELOG.md | 10 + plugins/firehydrant/package.json | 2 +- plugins/fossa/CHANGELOG.md | 12 + plugins/fossa/package.json | 2 +- plugins/gcalendar/CHANGELOG.md | 10 + plugins/gcalendar/package.json | 2 +- plugins/gcp-projects/CHANGELOG.md | 9 + plugins/gcp-projects/package.json | 2 +- plugins/git-release-manager/CHANGELOG.md | 10 + plugins/git-release-manager/package.json | 2 +- plugins/github-actions/CHANGELOG.md | 12 + plugins/github-actions/package.json | 2 +- plugins/github-deployments/CHANGELOG.md | 14 + plugins/github-deployments/package.json | 2 +- plugins/github-issues/CHANGELOG.md | 13 + plugins/github-issues/package.json | 2 +- .../github-pull-requests-board/CHANGELOG.md | 12 + .../github-pull-requests-board/package.json | 2 +- plugins/gitops-profiles/CHANGELOG.md | 9 + plugins/gitops-profiles/package.json | 2 +- plugins/gocd/CHANGELOG.md | 12 + plugins/gocd/package.json | 2 +- plugins/graphiql/CHANGELOG.md | 9 + plugins/graphiql/package.json | 2 +- plugins/graphql-backend/CHANGELOG.md | 9 + plugins/graphql-backend/package.json | 2 +- plugins/graphql-voyager/CHANGELOG.md | 9 + plugins/graphql-voyager/package.json | 2 +- plugins/home/CHANGELOG.md | 12 + plugins/home/package.json | 2 +- plugins/ilert/CHANGELOG.md | 12 + plugins/ilert/package.json | 2 +- plugins/jenkins-backend/CHANGELOG.md | 14 + plugins/jenkins-backend/package.json | 2 +- plugins/jenkins-common/CHANGELOG.md | 9 + plugins/jenkins-common/package.json | 2 +- plugins/jenkins/CHANGELOG.md | 14 + plugins/jenkins/package.json | 2 +- plugins/kafka-backend/CHANGELOG.md | 11 + plugins/kafka-backend/package.json | 2 +- plugins/kafka/CHANGELOG.md | 12 + plugins/kafka/package.json | 2 +- plugins/kubernetes-backend/CHANGELOG.md | 13 + plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes-common/CHANGELOG.md | 7 + plugins/kubernetes-common/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 13 + plugins/kubernetes/package.json | 2 +- plugins/lighthouse-backend/CHANGELOG.md | 13 + plugins/lighthouse-backend/package.json | 2 +- plugins/lighthouse/CHANGELOG.md | 13 + plugins/lighthouse/package.json | 2 +- plugins/linguist-backend/CHANGELOG.md | 20 + plugins/linguist-backend/package.json | 2 +- plugins/linguist/CHANGELOG.md | 13 + plugins/linguist/package.json | 2 +- plugins/microsoft-calendar/CHANGELOG.md | 10 + plugins/microsoft-calendar/package.json | 2 +- plugins/newrelic-dashboard/CHANGELOG.md | 11 + plugins/newrelic-dashboard/package.json | 2 +- plugins/newrelic/CHANGELOG.md | 9 + plugins/newrelic/package.json | 2 +- plugins/octopus-deploy/CHANGELOG.md | 16 + plugins/octopus-deploy/package.json | 2 +- plugins/org-react/CHANGELOG.md | 12 + plugins/org-react/package.json | 2 +- plugins/org/CHANGELOG.md | 12 + plugins/org/package.json | 2 +- plugins/pagerduty/CHANGELOG.md | 12 + plugins/pagerduty/package.json | 2 +- plugins/periskop-backend/CHANGELOG.md | 9 + plugins/periskop-backend/package.json | 2 +- plugins/periskop/CHANGELOG.md | 12 + plugins/periskop/package.json | 2 +- plugins/permission-backend/CHANGELOG.md | 12 + plugins/permission-backend/package.json | 2 +- plugins/permission-node/CHANGELOG.md | 11 + plugins/permission-node/package.json | 2 +- plugins/permission-react/CHANGELOG.md | 9 + plugins/permission-react/package.json | 2 +- plugins/playlist-backend/CHANGELOG.md | 15 + plugins/playlist-backend/package.json | 2 +- plugins/playlist/CHANGELOG.md | 18 + plugins/playlist/package.json | 2 +- plugins/proxy-backend/CHANGELOG.md | 22 + plugins/proxy-backend/package.json | 2 +- plugins/rollbar-backend/CHANGELOG.md | 8 + plugins/rollbar-backend/package.json | 2 +- plugins/rollbar/CHANGELOG.md | 11 + plugins/rollbar/package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 13 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/scaffolder-backend/CHANGELOG.md | 22 + plugins/scaffolder-backend/package.json | 2 +- plugins/scaffolder-common/CHANGELOG.md | 8 + plugins/scaffolder-common/package.json | 2 +- plugins/scaffolder-node/CHANGELOG.md | 10 + plugins/scaffolder-node/package.json | 2 +- plugins/scaffolder-react/CHANGELOG.md | 20 + plugins/scaffolder-react/package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 22 + plugins/scaffolder/package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- plugins/search-backend-module-pg/CHANGELOG.md | 10 + plugins/search-backend-module-pg/package.json | 2 +- plugins/search-backend-node/CHANGELOG.md | 12 + plugins/search-backend-node/package.json | 2 +- plugins/search-backend/CHANGELOG.md | 15 + plugins/search-backend/package.json | 2 +- plugins/search-react/CHANGELOG.md | 12 + plugins/search-react/package.json | 2 +- plugins/search/CHANGELOG.md | 17 + plugins/search/package.json | 2 +- plugins/sentry/CHANGELOG.md | 11 + plugins/sentry/package.json | 2 +- plugins/shortcuts/CHANGELOG.md | 10 + plugins/shortcuts/package.json | 2 +- plugins/sonarqube-backend/CHANGELOG.md | 9 + plugins/sonarqube-backend/package.json | 2 +- plugins/sonarqube-react/CHANGELOG.md | 10 + plugins/sonarqube-react/package.json | 2 +- plugins/sonarqube/CHANGELOG.md | 15 + plugins/sonarqube/package.json | 2 +- plugins/splunk-on-call/CHANGELOG.md | 11 + plugins/splunk-on-call/package.json | 2 +- plugins/stack-overflow-backend/CHANGELOG.md | 9 + plugins/stack-overflow-backend/package.json | 2 +- plugins/stack-overflow/CHANGELOG.md | 13 + plugins/stack-overflow/package.json | 2 +- plugins/stackstorm/CHANGELOG.md | 15 + plugins/stackstorm/package.json | 2 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- plugins/tech-insights-backend/CHANGELOG.md | 16 + plugins/tech-insights-backend/package.json | 2 +- plugins/tech-insights-node/CHANGELOG.md | 11 + plugins/tech-insights-node/package.json | 2 +- plugins/tech-insights/CHANGELOG.md | 14 + plugins/tech-insights/package.json | 2 +- plugins/tech-radar/CHANGELOG.md | 9 + plugins/tech-radar/package.json | 2 +- .../techdocs-addons-test-utils/CHANGELOG.md | 17 + .../techdocs-addons-test-utils/package.json | 2 +- plugins/techdocs-backend/CHANGELOG.md | 17 + plugins/techdocs-backend/package.json | 2 +- .../CHANGELOG.md | 12 + .../package.json | 2 +- plugins/techdocs-node/CHANGELOG.md | 13 + plugins/techdocs-node/package.json | 2 +- plugins/techdocs-react/CHANGELOG.md | 12 + plugins/techdocs-react/package.json | 2 +- plugins/techdocs/CHANGELOG.md | 23 + plugins/techdocs/package.json | 2 +- plugins/todo-backend/CHANGELOG.md | 15 + plugins/todo-backend/package.json | 2 +- plugins/todo/CHANGELOG.md | 12 + plugins/todo/package.json | 2 +- plugins/user-settings-backend/CHANGELOG.md | 12 + plugins/user-settings-backend/package.json | 2 +- plugins/user-settings/CHANGELOG.md | 13 + plugins/user-settings/package.json | 2 +- plugins/vault-backend/CHANGELOG.md | 11 + plugins/vault-backend/package.json | 2 +- plugins/vault/CHANGELOG.md | 12 + plugins/vault/package.json | 2 +- plugins/xcmetrics/CHANGELOG.md | 10 + plugins/xcmetrics/package.json | 2 +- yarn.lock | 230 +- 371 files changed, 5175 insertions(+), 201 deletions(-) create mode 100644 .changeset/create-app-1676993958.md create mode 100644 docs/releases/v1.12.0-next.0-changelog.md create mode 100644 plugins/octopus-deploy/CHANGELOG.md create mode 100644 plugins/stackstorm/CHANGELOG.md diff --git a/.changeset/create-app-1676993958.md b/.changeset/create-app-1676993958.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1676993958.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/pre.json b/.changeset/pre.json index fa7ab06d08..d3d0c1d42d 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -208,7 +208,47 @@ "@backstage/plugin-user-settings-backend": "0.1.6", "@backstage/plugin-vault": "0.1.9", "@backstage/plugin-vault-backend": "0.2.8", - "@backstage/plugin-xcmetrics": "0.2.35" + "@backstage/plugin-xcmetrics": "0.2.35", + "@backstage/plugin-octopus-deploy": "0.0.0", + "@backstage/plugin-stackstorm": "0.0.0" }, - "changesets": [] + "changesets": [ + "breezy-bees-care", + "bright-kids-raise", + "create-app-1676993958", + "curvy-pets-hang", + "eight-radios-bake", + "eighty-geese-return", + "four-lizards-grin", + "gentle-pears-clean", + "grumpy-bikes-begin", + "happy-boxes-arrive", + "honest-nails-bake", + "long-nails-pump", + "new-jobs-deny", + "nice-planets-wave", + "ninety-turtles-wait", + "odd-fireants-bathe", + "old-foxes-shave", + "perfect-mayflies-greet", + "polite-chicken-do", + "polite-falcons-jump", + "quick-schools-dress", + "quick-tables-listen", + "rare-buses-swim", + "rare-grapes-count", + "rare-pandas-hope", + "silly-suits-run", + "six-melons-rhyme", + "slimy-lobsters-kneel", + "slow-insects-cheat", + "slow-suits-grab", + "spotty-bees-tell", + "spotty-wasps-complain", + "swift-bags-wave", + "ten-tigers-marry", + "thin-candles-wait", + "twenty-jeans-speak", + "yellow-bananas-yawn" + ] } diff --git a/docs/releases/v1.12.0-next.0-changelog.md b/docs/releases/v1.12.0-next.0-changelog.md new file mode 100644 index 0000000000..b7f71b53e6 --- /dev/null +++ b/docs/releases/v1.12.0-next.0-changelog.md @@ -0,0 +1,2364 @@ +# Release v1.12.0-next.0 + +## @backstage/catalog-client@1.4.0-next.0 + +### Minor Changes + +- 8c030b1826: Add `queryEntities` method to `CatalogApi`. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-catalog@1.9.0-next.0 + +### Minor Changes + +- 3f75b7607c: Add ability to pass icon as function to have ability to customize it by search item + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/plugin-catalog-backend@1.8.0-next.0 + +### Minor Changes + +- 7f4ea3d360: Add /entities/by-query endpoint returning paginated entities. + + The endpoint supports cursor base pagination and server side sorting of the entities + +### Patch Changes + +- ac8929f2f3: Fix export of `defaultCatalogCollatorEntityTransformer`. +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-react@1.4.0-next.0 + +### Minor Changes + +- 0a5b73b292: Add possibility to re-use EntityPicker for filters with multiple select. + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.11-next.0 + +## @backstage/plugin-linguist-backend@0.2.0-next.0 + +### Minor Changes + +- 4a1c318853: **BREAKING** The linguist-backend `createRouter` now requires that the `tokenManger` is passed to the router. + +### Patch Changes + +- 2ea5782162: Fixed bug in LinguistBackendApi that caused initial batch of entities to be skipped. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-linguist-common@0.1.0 + +## @backstage/plugin-octopus-deploy@0.1.0-next.0 + +### Minor Changes + +- b7fff1171f: Initial version + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-stackstorm@0.1.0-next.0 + +### Minor Changes + +- f3a15259e9: Add StackStorm plugin to Backstage which is interfacing with StackStorm API. It allows users to view workflow executions, packs and actions. For installation and configuration instructions please view [README.md](https://github.com/backstage/backstage/tree/master/plugins/stackstorm/README.md) + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-techdocs@1.6.0-next.0 + +### Minor Changes + +- 3f75b7607c: Add ability to pass icon as function to have ability to customize it by search item + +### Patch Changes + +- f320c299c6: The HTML tag attributes in the documentation content inserted to shadow DOM is preserved to improve accessibility +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/app-defaults@1.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-permission-react@0.4.11-next.0 + +## @backstage/backend-app-api@0.4.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-node@0.7.6-next.0 + +## @backstage/backend-common@0.18.3-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-app-api@0.4.1-next.0 + - @backstage/backend-dev-utils@0.1.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/backend-defaults@0.1.8-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-app-api@0.4.1-next.0 + +## @backstage/backend-plugin-api@0.4.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/backend-tasks@0.4.4-next.0 + +### Patch Changes + +- f0685193ef: Added the adapted query to mysql and sqlite3 databases to not returning warning on logs +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-test-utils@0.1.35-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-app-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + +## @backstage/catalog-model@1.2.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/cli@0.22.4-next.0 + +### Patch Changes + +- b4cd145b57: Added a new `migrate package-exports` command that synchronizes package exports fields in all `package.json`s. +- 8bf24946c6: Adjust express dependencies to be the same as the rest of the project +- 17271841de: Updated frontend plugin template to use some more recent features +- Updated dependencies + - @backstage/eslint-plugin@0.1.2-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + +## @backstage/core-app-api@1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + +## @backstage/core-components@0.12.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/version-bridge@1.0.3 + +## @backstage/core-plugin-api@1.4.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + +## @backstage/create-app@0.4.38-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/dev-utils@1.0.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/app-defaults@1.2.1-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + +## @backstage/eslint-plugin@0.1.2-next.0 + +### Patch Changes + +- a061c466d6: Fixing a bug that we should check internal dependencies too + +## @backstage/integration-react@1.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + +## @backstage/repo-tools@0.1.3-next.0 + +### Patch Changes + +- 32a4a05838: Tweaked type dependency check to trim wildcard type imports. +- 6ba8faf22a: The API report generation process is now able to detect and generate reports for additional entry points declared in the package `"exports"` field. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + +## @techdocs/cli@1.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.5.1-next.0 + +## @backstage/test-utils@1.2.6-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.11-next.0 + +## @backstage/plugin-adr@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-adr-common@0.2.7-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/plugin-adr-backend@0.3.1-next.0 + +### Patch Changes + +- 8bf24946c6: Adjust express dependencies to be the same as the rest of the project +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.7-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-adr-common@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-airbrake@0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/dev-utils@1.0.13-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-airbrake-backend@0.2.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-allure@0.1.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-analytics-module-ga@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-apache-airflow@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + +## @backstage/plugin-api-docs@0.9.1-next.0 + +### Patch Changes + +- 095e755d9b: Add ApiDefinitionDialog component for fast access to the API definition in ProvidedApiCards and ConsumedApiCards. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-apollo-explorer@0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-app-backend@0.3.43-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-backend@0.18.1-next.0 + +### Patch Changes + +- 529de8c421: Added authentication provider for Azure Easy Authentication. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + +## @backstage/plugin-auth-node@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-azure-devops@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-devops-backend@0.3.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-azure-sites-backend@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-badges-backend@0.1.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bazaar@0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/cli@0.22.4-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-bazaar-backend@0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + +## @backstage/plugin-bitrise@0.1.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-catalog-backend-module-aws@0.1.17-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- bf611cf019: Fix missing `dependencies` in `package.json` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-kubernetes-common@0.6.1-next.0 + +## @backstage/plugin-catalog-backend-module-azure@0.1.14-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.10-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.8-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.11-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-github@0.2.6-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.14-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.2.2-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- bf611cf019: Fix missing `dependencies` in `package.json` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-defaults@0.1.8-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.2-next.0 + +### Patch Changes + +- a4ebd51352: Revert using `baseUrl` for MS Graph provider as it breaks token retrieval +- 928a12a9b3: Internal refactor of `/alpha` exports. +- 2c234a8932: properly support custom graph api URL +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-common@1.0.12-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-graph@0.2.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-catalog-graphql@0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-import@0.9.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + +## @backstage/plugin-catalog-node@1.3.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-cicd-statistics@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-cicd-statistics@0.1.18-next.0 + +## @backstage/plugin-circleci@0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-cloudbuild@0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-code-climate@0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-code-coverage@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-code-coverage-backend@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-codescene@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-config-schema@0.1.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + +## @backstage/plugin-cost-insights@0.12.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-dynatrace@3.0.0-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-entity-feedback@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-entity-feedback-common@0.1.0 + +## @backstage/plugin-entity-feedback-backend@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-entity-feedback-common@0.1.0 + +## @backstage/plugin-entity-validation@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-events-backend@0.2.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-aws-sqs@0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-events-backend-module-azure@0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + +## @backstage/plugin-events-backend-module-gerrit@0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + +## @backstage/plugin-events-backend-module-github@0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-gitlab@0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-test-utils@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.4-next.0 + +## @backstage/plugin-events-node@0.2.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + +## @backstage/plugin-explore@0.4.1-next.0 + +### Patch Changes + +- 3f75b7607c: Add ability to pass icon as function to have ability to customize it by search item +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.27-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/plugin-explore-backend@0.0.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-explore-react@0.0.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-explore-common@0.0.1 + +## @backstage/plugin-firehydrant@0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-fossa@0.2.48-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-gcalendar@0.3.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-gcp-projects@0.3.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-git-release-manager@0.3.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + +## @backstage/plugin-github-actions@0.5.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + +## @backstage/plugin-github-deployments@0.1.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-github-issues@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + +## @backstage/plugin-github-pull-requests-board@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + +## @backstage/plugin-gitops-profiles@0.3.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-gocd@0.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-graphiql@0.2.48-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-graphql-backend@0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.19-next.0 + +## @backstage/plugin-graphql-voyager@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-home@0.4.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-ilert@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-jenkins@0.7.15-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-jenkins-common@0.1.14-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-jenkins-backend@0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-jenkins-common@0.1.14-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-jenkins-common@0.1.14-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-kafka@0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-kafka-backend@0.2.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-kubernetes@0.7.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-kubernetes-common@0.6.1-next.0 + +## @backstage/plugin-kubernetes-backend@0.9.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-kubernetes-common@0.6.1-next.0 + +## @backstage/plugin-kubernetes-common@0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + +## @backstage/plugin-lighthouse@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-lighthouse-common@0.1.0 + +## @backstage/plugin-lighthouse-backend@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-lighthouse-common@0.1.0 + +## @backstage/plugin-linguist@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-linguist-common@0.1.0 + +## @backstage/plugin-microsoft-calendar@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-newrelic@0.3.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-newrelic-dashboard@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-org@0.6.6-next.0 + +### Patch Changes + +- 36bccb5252: Fix small UI-glitch in MemberListCard +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-org-react@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-pagerduty@0.5.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-periskop@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-periskop-backend@0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-permission-backend@0.5.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + +## @backstage/plugin-permission-node@0.7.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-permission-react@0.4.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-playlist@0.1.7-next.0 + +### Patch Changes + +- 122a37a880: Internal update to work with newer versions of react-router +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.11-next.0 + - @backstage/plugin-playlist-common@0.1.4 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/plugin-playlist-backend@0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-proxy-backend@0.2.37-next.0 + +### Patch Changes + +- 3e3eea4bc7: The proxy-backend plugin now supports reviving request bodies that have previously been consumed by an express middleware (e.g. `express.json()`). This is done by setting `reviveConsumedRequestBodies: true` on the proxy `RouterOptions`. In order to preserve the current behavior, the proxy will **not** revive request bodies by default. + + The following is an example of a proxy `createRouter` invocation that revives request bodies: + + ```diff + const router = await createRouter({ + config, + logger, + discovery, + + reviveConsumedRequestBodies: true, + }); + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-rollbar@0.4.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-rollbar-backend@0.1.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + +## @backstage/plugin-scaffolder@1.11.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-scaffolder-react@1.1.1-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-react@0.4.11-next.0 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + +## @backstage/plugin-scaffolder-backend@1.11.1-next.0 + +### Patch Changes + +- c6c78b4acb: throw error from catalog:fetch scaffolder action when entity is null and optional is false +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + +## @backstage/plugin-scaffolder-common@1.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-node@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + +## @backstage/plugin-scaffolder-react@1.1.1-next.0 + +### Patch Changes + +- c8d78b9ae9: fix bug with `hasErrors` returning false when dealing with empty objects +- 928a12a9b3: Internal refactor of `/alpha` exports. +- cc418d652a: scaffolder/next: Added the ability to get the fields definition in the schema in the validation function +- d4100d0ec4: Fix alignment bug for owners on `TemplateCard` +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + +## @backstage/plugin-search@1.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/plugin-search-backend@1.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-pg@0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-node@1.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-react@1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-sentry@0.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-shortcuts@0.3.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + +## @backstage/plugin-sonarqube@0.6.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- 8ae65a0bc1: Moved imports from `/alpha` to main public exports. +- d3d624e8e8: Show a more appropriate icon if there are no code smells and/or vulnerabilities. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-sonarqube-react@0.1.4-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-sonarqube-backend@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-sonarqube-react@0.1.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- 8ae65a0bc1: Moved imports from `/alpha` to main public exports. +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + +## @backstage/plugin-splunk-on-call@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-stack-overflow@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-home@0.4.32-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/plugin-stack-overflow-backend@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-tech-insights@0.3.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-insights-backend@0.5.9-next.0 + +### Patch Changes + +- f244b58916: Add DB index to improve latency of latest fact query +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.1-next.0 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.1-next.0 + +## @backstage/plugin-tech-insights-node@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + +## @backstage/plugin-tech-radar@0.6.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.11-next.0 + +### Patch Changes + +- 2b00d8a225: Fix bug/problem with test helper +- Updated dependencies + - @backstage/plugin-techdocs@1.6.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-search-react@1.5.1-next.0 + +## @backstage/plugin-techdocs-backend@1.5.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.5.1-next.0 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + +## @backstage/plugin-techdocs-node@1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-techdocs-react@1.1.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/version-bridge@1.0.3 + +## @backstage/plugin-todo@0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-todo-backend@0.1.40-next.0 + +### Patch Changes + +- 4120513412: todo-backend is now exposed as a plugin which uses the new plugin system +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-user-settings@0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + +## @backstage/plugin-user-settings-backend@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + +## @backstage/plugin-vault@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## @backstage/plugin-vault-backend@0.2.10-next.0 + +### Patch Changes + +- 66b3a3956b: Ignore the `eslint` error +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-xcmetrics@0.2.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + +## example-app@0.2.81-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.1-next.0 + - @backstage/cli@0.22.4-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/plugin-techdocs@1.6.0-next.0 + - @backstage/plugin-api-docs@0.9.1-next.0 + - @backstage/plugin-org@0.6.6-next.0 + - @backstage/plugin-stackstorm@0.1.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/plugin-cost-insights@0.12.5-next.0 + - @backstage/plugin-scaffolder@1.11.1-next.0 + - @backstage/plugin-jenkins@0.7.15-next.0 + - @backstage/plugin-playlist@0.1.7-next.0 + - @backstage/plugin-explore@0.4.1-next.0 + - @backstage/plugin-catalog-graph@0.2.28-next.0 + - @backstage/plugin-catalog-import@0.9.6-next.0 + - @backstage/app-defaults@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-airbrake@0.3.16-next.0 + - @backstage/plugin-apache-airflow@0.2.9-next.0 + - @backstage/plugin-azure-devops@0.2.7-next.0 + - @backstage/plugin-azure-sites@0.1.5-next.0 + - @backstage/plugin-badges@0.2.40-next.0 + - @backstage/plugin-circleci@0.3.16-next.0 + - @backstage/plugin-cloudbuild@0.3.16-next.0 + - @backstage/plugin-code-coverage@0.2.9-next.0 + - @backstage/plugin-dynatrace@3.0.0-next.0 + - @backstage/plugin-entity-feedback@0.1.1-next.0 + - @backstage/plugin-gcalendar@0.3.12-next.0 + - @backstage/plugin-gcp-projects@0.3.35-next.0 + - @backstage/plugin-github-actions@0.5.16-next.0 + - @backstage/plugin-gocd@0.1.22-next.0 + - @backstage/plugin-graphiql@0.2.48-next.0 + - @backstage/plugin-home@0.4.32-next.0 + - @backstage/plugin-kafka@0.3.16-next.0 + - @backstage/plugin-kubernetes@0.7.9-next.0 + - @backstage/plugin-lighthouse@0.4.1-next.0 + - @backstage/plugin-linguist@0.1.1-next.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-microsoft-calendar@0.1.1-next.0 + - @backstage/plugin-newrelic@0.3.34-next.0 + - @backstage/plugin-newrelic-dashboard@0.2.9-next.0 + - @backstage/plugin-pagerduty@0.5.9-next.0 + - @backstage/plugin-permission-react@0.4.11-next.0 + - @backstage/plugin-rollbar@0.4.16-next.0 + - @backstage/plugin-search@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + - @backstage/plugin-sentry@0.5.1-next.0 + - @backstage/plugin-shortcuts@0.3.8-next.0 + - @backstage/plugin-stack-overflow@0.1.12-next.0 + - @backstage/plugin-tech-insights@0.3.8-next.0 + - @backstage/plugin-tech-radar@0.6.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.11-next.0 + - @backstage/plugin-todo@0.2.18-next.0 + - @backstage/plugin-user-settings@0.7.1-next.0 + - @internal/plugin-catalog-customized@0.0.8-next.0 + +## example-backend@0.2.81-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-todo-backend@0.1.40-next.0 + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/plugin-tech-insights-backend@0.5.9-next.0 + - @backstage/plugin-linguist-backend@0.2.0-next.0 + - @backstage/plugin-adr-backend@0.3.1-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/plugin-techdocs-backend@1.5.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-events-backend@0.2.4-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-app-backend@0.3.43-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/plugin-proxy-backend@0.2.37-next.0 + - @backstage/plugin-auth-backend@0.18.1-next.0 + - @backstage/plugin-badges-backend@0.1.37-next.0 + - @backstage/plugin-code-coverage-backend@0.2.9-next.0 + - @backstage/plugin-entity-feedback-backend@0.1.1-next.0 + - @backstage/plugin-jenkins-backend@0.1.33-next.0 + - @backstage/plugin-kubernetes-backend@0.9.4-next.0 + - @backstage/plugin-lighthouse-backend@0.1.1-next.0 + - @backstage/plugin-playlist-backend@0.2.6-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.11-next.0 + - example-app@0.2.81-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-azure-devops-backend@0.3.22-next.0 + - @backstage/plugin-azure-sites-backend@0.1.5-next.0 + - @backstage/plugin-explore-backend@0.0.5-next.0 + - @backstage/plugin-graphql-backend@0.1.33-next.0 + - @backstage/plugin-kafka-backend@0.2.36-next.0 + - @backstage/plugin-permission-backend@0.5.18-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-rollbar-backend@0.1.40-next.0 + - @backstage/plugin-search-backend@1.2.4-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.4-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.4-next.0 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.27-next.0 + - @backstage/plugin-tech-insights-node@0.4.1-next.0 + +## example-backend-next@0.0.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-todo-backend@0.1.40-next.0 + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-defaults@0.1.8-next.0 + - @backstage/plugin-app-backend@0.3.43-next.0 + +## e2e-test@0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.4.38-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + +## techdocs-cli-embedded-app@0.2.80-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.4-next.0 + - @backstage/plugin-techdocs@1.6.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/app-defaults@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + +## @internal/plugin-catalog-customized@0.0.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + +## @internal/plugin-todo-list@1.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + +## @internal/plugin-todo-list-backend@1.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 diff --git a/package.json b/package.json index c06d353501..9a60fb9d4a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.11.0", + "version": "1.12.0-next.0", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index f22e4fce1a..fe9c1ac9ba 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/app-defaults +## 1.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-permission-react@0.4.11-next.0 + ## 1.2.0 ### Minor Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index b1a30fdfc6..b9116c21ae 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.2.0", + "version": "1.2.1-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index aae6d02535..78633bc1d9 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,74 @@ # example-app +## 0.2.81-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.1-next.0 + - @backstage/cli@0.22.4-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/plugin-techdocs@1.6.0-next.0 + - @backstage/plugin-api-docs@0.9.1-next.0 + - @backstage/plugin-org@0.6.6-next.0 + - @backstage/plugin-stackstorm@0.1.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/plugin-cost-insights@0.12.5-next.0 + - @backstage/plugin-scaffolder@1.11.1-next.0 + - @backstage/plugin-jenkins@0.7.15-next.0 + - @backstage/plugin-playlist@0.1.7-next.0 + - @backstage/plugin-explore@0.4.1-next.0 + - @backstage/plugin-catalog-graph@0.2.28-next.0 + - @backstage/plugin-catalog-import@0.9.6-next.0 + - @backstage/app-defaults@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-airbrake@0.3.16-next.0 + - @backstage/plugin-apache-airflow@0.2.9-next.0 + - @backstage/plugin-azure-devops@0.2.7-next.0 + - @backstage/plugin-azure-sites@0.1.5-next.0 + - @backstage/plugin-badges@0.2.40-next.0 + - @backstage/plugin-circleci@0.3.16-next.0 + - @backstage/plugin-cloudbuild@0.3.16-next.0 + - @backstage/plugin-code-coverage@0.2.9-next.0 + - @backstage/plugin-dynatrace@3.0.0-next.0 + - @backstage/plugin-entity-feedback@0.1.1-next.0 + - @backstage/plugin-gcalendar@0.3.12-next.0 + - @backstage/plugin-gcp-projects@0.3.35-next.0 + - @backstage/plugin-github-actions@0.5.16-next.0 + - @backstage/plugin-gocd@0.1.22-next.0 + - @backstage/plugin-graphiql@0.2.48-next.0 + - @backstage/plugin-home@0.4.32-next.0 + - @backstage/plugin-kafka@0.3.16-next.0 + - @backstage/plugin-kubernetes@0.7.9-next.0 + - @backstage/plugin-lighthouse@0.4.1-next.0 + - @backstage/plugin-linguist@0.1.1-next.0 + - @backstage/plugin-linguist-common@0.1.0 + - @backstage/plugin-microsoft-calendar@0.1.1-next.0 + - @backstage/plugin-newrelic@0.3.34-next.0 + - @backstage/plugin-newrelic-dashboard@0.2.9-next.0 + - @backstage/plugin-pagerduty@0.5.9-next.0 + - @backstage/plugin-permission-react@0.4.11-next.0 + - @backstage/plugin-rollbar@0.4.16-next.0 + - @backstage/plugin-search@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + - @backstage/plugin-sentry@0.5.1-next.0 + - @backstage/plugin-shortcuts@0.3.8-next.0 + - @backstage/plugin-stack-overflow@0.1.12-next.0 + - @backstage/plugin-tech-insights@0.3.8-next.0 + - @backstage/plugin-tech-radar@0.6.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.11-next.0 + - @backstage/plugin-todo@0.2.18-next.0 + - @backstage/plugin-user-settings@0.7.1-next.0 + - @internal/plugin-catalog-customized@0.0.8-next.0 + ## 0.2.80 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 822416ba09..7aba203895 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.80", + "version": "0.2.81-next.0", "private": true, "backstage": { "role": "frontend" diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 2d5eb8251c..af7828daac 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/backend-app-api +## 0.4.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-node@0.7.6-next.0 + ## 0.4.0 ### Minor Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 9c105fb474..099466aef7 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.4.0", + "version": "0.4.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 14e9d60ba2..dc07ac0614 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/backend-common +## 0.18.3-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-app-api@0.4.1-next.0 + - @backstage/backend-dev-utils@0.1.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.18.2 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 7973ae6111..4738a1bc97 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.18.2", + "version": "0.18.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index d55ff77a24..e56a19d04a 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-defaults +## 0.1.8-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-app-api@0.4.1-next.0 + ## 0.1.7 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 1e700e2021..cc10118bb8 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.1.7", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 69cfdac43e..2c40502783 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,16 @@ # example-backend-next +## 0.0.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-todo-backend@0.1.40-next.0 + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-defaults@0.1.8-next.0 + - @backstage/plugin-app-backend@0.3.43-next.0 + ## 0.0.8 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index a76d7e1dd3..21ba3550b4 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.8", + "version": "0.0.9-next.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 7afc24bb74..4dc19db6fc 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-plugin-api +## 0.4.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + ## 0.4.0 ### Minor Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 30ea47c520..06acbce628 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.4.0", + "version": "0.4.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 3b5a2473c8..e70ff6146d 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-tasks +## 0.4.4-next.0 + +### Patch Changes + +- f0685193ef: Added the adapted query to mysql and sqlite3 databases to not returning warning on logs +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.4.3 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 3c7c8ed452..42d0f35374 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.4.3", + "version": "0.4.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index b4a81da494..8129bb3c0a 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/backend-test-utils +## 0.1.35-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-app-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + ## 0.1.34 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 7bcb680dfe..59b6fd057d 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.34", + "version": "0.1.35-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index dd77d99f65..a9551d3c47 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,56 @@ # example-backend +## 0.2.81-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-todo-backend@0.1.40-next.0 + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/plugin-tech-insights-backend@0.5.9-next.0 + - @backstage/plugin-linguist-backend@0.2.0-next.0 + - @backstage/plugin-adr-backend@0.3.1-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/plugin-techdocs-backend@1.5.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-events-backend@0.2.4-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-app-backend@0.3.43-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/plugin-proxy-backend@0.2.37-next.0 + - @backstage/plugin-auth-backend@0.18.1-next.0 + - @backstage/plugin-badges-backend@0.1.37-next.0 + - @backstage/plugin-code-coverage-backend@0.2.9-next.0 + - @backstage/plugin-entity-feedback-backend@0.1.1-next.0 + - @backstage/plugin-jenkins-backend@0.1.33-next.0 + - @backstage/plugin-kubernetes-backend@0.9.4-next.0 + - @backstage/plugin-lighthouse-backend@0.1.1-next.0 + - @backstage/plugin-playlist-backend@0.2.6-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.11-next.0 + - example-app@0.2.81-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-azure-devops-backend@0.3.22-next.0 + - @backstage/plugin-azure-sites-backend@0.1.5-next.0 + - @backstage/plugin-explore-backend@0.0.5-next.0 + - @backstage/plugin-graphql-backend@0.1.33-next.0 + - @backstage/plugin-kafka-backend@0.2.36-next.0 + - @backstage/plugin-permission-backend@0.5.18-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-rollbar-backend@0.1.40-next.0 + - @backstage/plugin-search-backend@1.2.4-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.4-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.4-next.0 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.27-next.0 + - @backstage/plugin-tech-insights-node@0.4.1-next.0 + ## 0.2.80 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 87efe3c0c5..2e742b365d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.80", + "version": "0.2.81-next.0", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 557129f2f2..99b07f3c5c 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/catalog-client +## 1.4.0-next.0 + +### Minor Changes + +- 8c030b1826: Add `queryEntities` method to `CatalogApi`. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/errors@1.1.4 + ## 1.3.1 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 98257bc190..4915bfa636 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.3.1", + "version": "1.4.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 0eed8c8dbf..8d6659c20b 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/catalog-model +## 1.2.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 1.2.0 ### Minor Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index b391ad79e4..c75984643b 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "1.2.0", + "version": "1.2.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 08ffac4595..c42f76c774 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/cli +## 0.22.4-next.0 + +### Patch Changes + +- b4cd145b57: Added a new `migrate package-exports` command that synchronizes package exports fields in all `package.json`s. +- 8bf24946c6: Adjust express dependencies to be the same as the rest of the project +- 17271841de: Updated frontend plugin template to use some more recent features +- Updated dependencies + - @backstage/eslint-plugin@0.1.2-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + ## 0.22.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 9eaef81bec..64311a767d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.22.2", + "version": "0.22.4-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index df1cdc318e..4575040798 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-app-api +## 1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + ## 1.5.0 ### Minor Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 7233564efc..f9a17bd88c 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.5.0", + "version": "1.5.1-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index ee214290ea..5ad035fbfd 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/core-components +## 0.12.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/version-bridge@1.0.3 + ## 0.12.4 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index e10ab0ba69..736b7a415b 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.12.4", + "version": "0.12.5-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index 464915bf18..e2da5bc048 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-plugin-api +## 1.4.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + ## 1.4.0 ### Minor Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index d34d13dbe1..561b08f3e5 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "1.4.0", + "version": "1.4.1-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 3bdda403aa..149c474022 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/create-app +## 0.4.38-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.11 + ## 0.4.37 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 52c7dcb3fe..6ca80a519c 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.4.37", + "version": "0.4.38-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 80550d82ca..ae7c5a3282 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/dev-utils +## 1.0.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/app-defaults@1.2.1-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + ## 1.0.12 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index d179aa3c8c..2680401145 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.12", + "version": "1.0.13-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index d872d34664..c3345a5815 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,14 @@ # e2e-test +## 0.2.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.4.38-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + ## 0.2.0 ### Minor Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 718f8fd079..969c68feb3 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,7 +1,7 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.2.0", + "version": "0.2.1-next.0", "private": true, "backstage": { "role": "cli" diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index bc8c2742da..7e5a3efbae 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/eslint-plugin +## 0.1.2-next.0 + +### Patch Changes + +- a061c466d6: Fixing a bug that we should check internal dependencies too + ## 0.1.0 ### Minor Changes diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 8dedd24b1a..fcc038cdbf 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/eslint-plugin", "description": "Backstage ESLint plugin", - "version": "0.1.0", + "version": "0.1.2-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 45f6f0a543..700b410bf6 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/integration-react +## 1.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + ## 1.1.10 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index d8aabc9f92..f074245dcb 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "1.1.10", + "version": "1.1.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 9cf5780cbe..d4d300f450 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/repo-tools +## 0.1.3-next.0 + +### Patch Changes + +- 32a4a05838: Tweaked type dependency check to trim wildcard type imports. +- 6ba8faf22a: The API report generation process is now able to detect and generate reports for additional entry points declared in the package `"exports"` field. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + ## 0.1.2 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 0fc5cc3554..2ceeeb0dd8 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.1.2", + "version": "0.1.3-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index fe2d1f6b4a..e3b49ff2f2 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,24 @@ # techdocs-cli-embedded-app +## 0.2.80-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.4-next.0 + - @backstage/plugin-techdocs@1.6.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/app-defaults@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + ## 0.2.79 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index fe7d6a427c..2d8c47c1f0 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.79", + "version": "0.2.80-next.0", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index a2da4ff5fa..1e995b5f23 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @techdocs/cli +## 1.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.5.1-next.0 + ## 1.3.2 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 016404b12f..0a3bbed06f 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.3.2", + "version": "1.3.3-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 9a8cf6f264..2a2ff57694 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/test-utils +## 1.2.6-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.11-next.0 + ## 1.2.5 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 192d58fd14..925f42b49b 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.2.5", + "version": "1.2.6-next.0", "publishConfig": { "access": "public" }, diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index e52d3f91e7..9bd8a9576a 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-adr-backend +## 0.3.1-next.0 + +### Patch Changes + +- 8bf24946c6: Adjust express dependencies to be the same as the rest of the project +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.7-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 0.3.0 ### Minor Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index b6b62fbc93..34231c549c 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.3.0", + "version": "0.3.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index e19d73fe73..b04b7a0c64 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + ## 0.2.6 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index d7a57fc7d1..b2557c5407 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.6", + "version": "0.2.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index 72c3625a4d..c22c566b6c 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-adr +## 0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-adr-common@0.2.7-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 0.4.0 ### Minor Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 2ed701baf4..c5c99c6e24 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.4.0", + "version": "0.4.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index 70e2e16713..821f2df769 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-airbrake-backend +## 0.2.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + ## 0.2.15 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 7a6248c391..faa401da7b 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.2.15", + "version": "0.2.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index f5c5d98f35..493a4ecd34 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-airbrake +## 0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/dev-utils@1.0.13-next.0 + - @backstage/theme@0.2.17 + ## 0.3.15 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 86713347c0..1430fc0546 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.15", + "version": "0.3.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index f1e5663dea..d3629f0406 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-allure +## 0.1.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.31 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 3eae30212a..017fe5908c 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.31", + "version": "0.1.32-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 3527c8ab4b..02bed18551 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga +## 0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.26 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 0db33867a4..71b71887b4 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.26", + "version": "0.1.27-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index f40885d51b..50ceff31ac 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-apache-airflow +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + ## 0.2.8 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 504f3d5478..42a1177aea 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.8", + "version": "0.2.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 64af7b93e5..8f6878bb97 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-api-docs +## 0.9.1-next.0 + +### Patch Changes + +- 095e755d9b: Add ApiDefinitionDialog component for fast access to the API definition in ProvidedApiCards and ConsumedApiCards. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.9.0 ### Minor Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 1d2902117c..49f70c038b 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.9.0", + "version": "0.9.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index 1e84c3361a..b3d1d90f53 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-apollo-explorer +## 0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.8 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 7e53f25627..3f6b8202a8 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.8", + "version": "0.1.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 9c0438f33a..ef9392a626 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-app-backend +## 0.3.43-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + ## 0.3.42 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index ae2c61311c..5f9856d322 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.42", + "version": "0.3.43-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 6525ae6e92..5e2b975fc1 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-auth-backend +## 0.18.1-next.0 + +### Patch Changes + +- 529de8c421: Added authentication provider for Azure Easy Authentication. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + ## 0.18.0 ### Minor Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index dee7f6e442..523568cc2c 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.18.0", + "version": "0.18.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 585358669f..9f0609bd7a 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-node +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.11 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index df1f8e52d5..97539fadcb 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.2.11", + "version": "0.2.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 632fcc078c..2f28ddd584 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-devops-backend +## 0.3.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.3.21 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 5880e8ac2c..e75adc2344 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.21", + "version": "0.3.22-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index e5a43b7104..3df7331474 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-azure-devops +## 0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.2.6 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 0000ab8584..ca01418465 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.2.6", + "version": "0.2.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index 9faccb8d31..32fba35d47 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-azure-sites-backend +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index 2d87d3c4b5..760765303a 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 6f2417817e..e755c154ce 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-azure-sites +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 47d56fc062..aa2d92ffab 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 4e19efafc0..c71299528e 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-badges-backend +## 0.1.37-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.36 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 6c30cbf210..af9ff60372 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.1.36", + "version": "0.1.37-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 16e60ca6df..c92817a9e3 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-badges +## 0.2.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.2.39 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 85812681ab..54de1216d2 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.39", + "version": "0.2.40-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index f007563f54..1ae72cadfb 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bazaar-backend +## 0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + ## 0.2.5 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index d0c0fce53d..e8ea2a19f7 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.2.5", + "version": "0.2.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 8518052168..49a5570245 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-bazaar +## 0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/cli@0.22.4-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.2.4 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 9164bd3824..ae3703cbbc 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.4", + "version": "0.2.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 8aaea19613..2c74da08aa 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bitrise +## 0.1.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.42 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 1bf2252d3e..cb7eeae705 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.42", + "version": "0.1.43-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index c70a80f693..085b505782 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.1.17-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- bf611cf019: Fix missing `dependencies` in `package.json` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-kubernetes-common@0.6.1-next.0 + ## 0.1.15 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 61cf55d546..ea75932dc8 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.1.15", + "version": "0.1.17-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 88b1d869fa..3dbd990f57 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.14-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.13 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index ecaf9fb9cc..a327679807 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.13", + "version": "0.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 909153d497..c506ddc588 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.10-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + ## 0.1.9 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 5d6c80a0cb..55f5d710f9 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.9", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index cdf0373e0f..938f731df3 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.8-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.7 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 811dfe9f10..2de59cdc33 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.7", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index f0d584f5bc..d082563115 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + ## 0.2.9 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 596a87f5b9..d01e1e7d30 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.9", + "version": "0.2.10-next.0", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 5e6e186e1c..80a5989141 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.11-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.10 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 95978c2502..e9c9572b5f 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.10", + "version": "0.1.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index ba092566b1..e4b14ca727 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-catalog-backend-module-github +## 0.2.6-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.2.5 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index ccf1be3b2a..b30b211c92 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.2.5", + "version": "0.2.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index b444742f89..67bb23d79e 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.1.14-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.13 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index cbd07944d9..d73b6666e5 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.1.13", + "version": "0.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 11d2015a02..88ae72e1a8 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.2.2-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- bf611cf019: Fix missing `dependencies` in `package.json` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-defaults@0.1.8-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + ## 0.2.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 5f49cb8905..326f4d7bec 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.2.0", + "version": "0.2.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 007cb3b219..e2c358d1a4 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.5.9 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index bf436978a9..dfca9332c0 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.9", + "version": "0.5.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 41dd527462..c7c64da5a0 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.2-next.0 + +### Patch Changes + +- a4ebd51352: Revert using `baseUrl` for MS Graph provider as it breaks token retrieval +- 928a12a9b3: Internal refactor of `/alpha` exports. +- 2c234a8932: properly support custom graph api URL +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + ## 0.5.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 1cc3855d77..7ccc8f4fd9 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.5.0", + "version": "0.5.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 5e488c7f56..a1d43e6954 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.1.8 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index b9d9332257..3407eeb0e6 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.8", + "version": "0.1.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 1b9eb1c703..0b55db0239 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-backend +## 1.8.0-next.0 + +### Minor Changes + +- 7f4ea3d360: Add /entities/by-query endpoint returning paginated entities. + + The endpoint supports cursor base pagination and server side sorting of the entities + +### Patch Changes + +- ac8929f2f3: Fix export of `defaultCatalogCollatorEntityTransformer`. +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 1.7.2 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 17e9c9aa7c..c9b3b93857 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "1.7.2", + "version": "1.8.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index eb6ba1149a..753af21e7e 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-common +## 1.0.12-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.0.11 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 27b31d15ea..033ee10f3d 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "1.0.11", + "version": "1.0.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index ec7502f51f..dbcbd10520 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,13 @@ # @internal/plugin-catalog-customized +## 0.0.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + ## 0.0.7 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index 01921d1255..3cacddf58a 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.7", + "version": "0.0.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 791d8118b3..ec21c0aa66 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-graph +## 0.2.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.2.27 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index fb37af29ed..0e093a3ab1 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.27", + "version": "0.2.28-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 5483c379e0..ede51b17fb 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-graphql +## 0.3.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.3.18 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 4cfa1dbcc9..0a6cff187c 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-graphql", "description": "An experimental Backstage catalog GraphQL module", - "version": "0.3.18", + "version": "0.3.19-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 1e5c09567f..cf6e3068cc 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-import +## 0.9.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + ## 0.9.5 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index b185ce799e..e07725bedb 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.9.5", + "version": "0.9.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 47e3e2a519..6f4098a158 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-node +## 1.3.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 1.3.3 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 6c888f342e..4f122ec465 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.3.3", + "version": "1.3.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index aed8750ede..db92d850ed 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog-react +## 1.4.0-next.0 + +### Minor Changes + +- 0a5b73b292: Add possibility to re-use EntityPicker for filters with multiple select. + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.11-next.0 + ## 1.3.0 ### Minor Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index e8f796a725..7a707240ca 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "1.3.0", + "version": "1.4.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 58ef9dcce9..5a4fee935a 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog +## 1.9.0-next.0 + +### Minor Changes + +- 3f75b7607c: Add ability to pass icon as function to have ability to customize it by search item + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 1.8.0 ### Minor Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 01ce6dadf0..212f4044b4 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "1.8.0", + "version": "1.9.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 77305d54cb..bd49967ff4 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-cicd-statistics@0.1.18-next.0 + ## 0.1.11 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index ee39fa0b39..7db1fa63f5 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.11", + "version": "0.1.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index d80c9b2f7a..e60210b30b 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 55495ee940..79469a7ce8 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", - "version": "0.1.17", + "version": "0.1.18-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 7de7dae49a..43d0b72410 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-circleci +## 0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.3.15 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 64785a896d..0167f9ff98 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.3.15", + "version": "0.3.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index e7e9c99da1..7939ee1ad4 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cloudbuild +## 0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.3.15 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 4e519c5274..d888dc6a7b 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.3.15", + "version": "0.3.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index f3efbc42de..5d4e998846 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-code-climate +## 0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.15 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index ef1b5f5e76..d353b2443f 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.15", + "version": "0.1.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 7bdf96fd44..e6606e3eea 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-code-coverage-backend +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.2.8 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 18603858e4..24309c128e 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.2.8", + "version": "0.2.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 9973cabe3e..36c7617431 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-code-coverage +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.2.8 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 3d94e6314b..2dd0041002 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.2.8", + "version": "0.2.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index 8129121f2f..e8ab4d63cf 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-codescene +## 0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.1.10 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 062f01c9c5..d44f3f3fa6 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.10", + "version": "0.1.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 73875b4087..5a52322ec0 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-config-schema +## 0.1.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + ## 0.1.38 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 1602caee2d..2c0fb2ae7c 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.38", + "version": "0.1.39-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index ba24253414..e94efa2602 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-cost-insights +## 0.12.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-cost-insights-common@0.1.1 + ## 0.12.4 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index d443637dc5..c20d42928b 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.12.4", + "version": "0.12.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index c84b3b7355..1daec214f0 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-dynatrace +## 3.0.0-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 2.0.0 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index bca0d276e3..cca4d9254f 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "2.0.0", + "version": "3.0.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-backend/CHANGELOG.md b/plugins/entity-feedback-backend/CHANGELOG.md index 58e66fb696..86f7debc5c 100644 --- a/plugins/entity-feedback-backend/CHANGELOG.md +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-entity-feedback-backend +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-entity-feedback-common@0.1.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 487d5f5d5e..c7b5146267 100644 --- a/plugins/entity-feedback-backend/package.json +++ b/plugins/entity-feedback-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback-backend", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback/CHANGELOG.md b/plugins/entity-feedback/CHANGELOG.md index 795156f019..4fc3561a07 100644 --- a/plugins/entity-feedback/CHANGELOG.md +++ b/plugins/entity-feedback/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-entity-feedback +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-entity-feedback-common@0.1.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 6d71b04cc2..3602d08c2f 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md index 95fe6c8436..6b80724f92 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-entity-validation +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.1.0 ### Minor Changes diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index e9a47cc1e2..a6697d0722 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-validation", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 60c67be93f..af976da894 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.1.4 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 2e45015bce..53901e5038 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index 7a2d2c5b0f..54c0f53713 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index a3acd37263..bdfa37d36f 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 545df05bdc..2310a2eb44 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index ae006b1bce..0b1c5d08a7 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index c900e0e68f..f74060b9bd 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index a7aadf06dc..ec9f9358ab 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index 0505662c26..ff885d1dbf 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-events-backend-module-github +## 0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + ## 0.1.4 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 966b7b3592..ac7599b11f 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index e12e1d1130..f3b2ac8594 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + ## 0.1.4 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 4e5e53771d..09c924394b 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index 7591176488..2394b67a48 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.4-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index e1c86062c6..2a4f45aa73 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-backend-test-utils", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 891d8eff1b..0e04c52691 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-events-backend +## 0.2.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/plugin-events-node@0.2.4-next.0 + - @backstage/config@1.0.6 + ## 0.2.3 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index d779869e14..fa3594528c 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.2.3", + "version": "0.2.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index ef59fc29ed..3c999d18d6 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-events-node +## 0.2.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + ## 0.2.3 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 368e567930..5d6327980e 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-node", "description": "The plugin-events-node module for @backstage/plugin-events-backend", - "version": "0.2.3", + "version": "0.2.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index b517b8a64f..e0356edf92 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @internal/plugin-todo-list-backend +## 1.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + ## 1.0.10 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 3821e36e7d..4dad898939 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.10", + "version": "1.0.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index 602844625c..715a9bfc12 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,14 @@ # @internal/plugin-todo-list +## 1.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 1.0.10 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 8839346812..961fe4ef08 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.10", + "version": "1.0.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index db9365c6a7..42a632ec7f 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-explore-backend +## 0.0.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + ## 0.0.4 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index ec26467a8e..00b2f18bbc 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-backend", - "version": "0.0.4", + "version": "0.0.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index 08181713f0..cb3adf2f5d 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-explore-react +## 0.0.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-explore-common@0.0.1 + ## 0.0.26 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index afc01aca33..3d674c9506 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore-react", "description": "A frontend library for Backstage plugins that want to interact with the explore plugin", - "version": "0.0.26", + "version": "0.0.27-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index ad2e9aa19e..501f4dd10c 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-explore +## 0.4.1-next.0 + +### Patch Changes + +- 3f75b7607c: Add ability to pass icon as function to have ability to customize it by search item +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.27-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 0.4.0 ### Minor Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index f114076d3c..1a4da26abb 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.4.0", + "version": "0.4.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 05a126ab2c..a83b8aa486 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-firehydrant +## 0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.32 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index b847ddcd43..a1bd316856 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.1.32", + "version": "0.1.33-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 92779b8525..d7d62cc9fa 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-fossa +## 0.2.48-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.2.47 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 90fcdd92fc..655aab51ed 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.47", + "version": "0.2.48-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 17b06fbf57..3878c11515 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-gcalendar +## 0.3.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.3.11 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 42c9e11b43..1121849277 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.11", + "version": "0.3.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 4bacbec2e5..8b625586f9 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gcp-projects +## 0.3.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.3.34 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 65af5ae819..ff8fd9d57e 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.34", + "version": "0.3.35-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index b12495e3ca..5180d95013 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-git-release-manager +## 0.3.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + ## 0.3.28 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 2d0fc51bc6..b208099a62 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.28", + "version": "0.3.29-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 95776f2b02..03eaff830e 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-actions +## 0.5.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + ## 0.5.15 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 9aabcbeda5..e3bc9a9764 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.5.15", + "version": "0.5.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index c941fe04cd..d073a5eed9 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-deployments +## 0.1.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + ## 0.1.46 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 25bb21df67..1cfaafe758 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.46", + "version": "0.1.47-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index df2886dac7..9e4e64b628 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-github-issues +## 0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + ## 0.2.4 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index adfb395d5f..d3544d2dbe 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.2.4", + "version": "0.2.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 66fc1300c8..ec4da0406e 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.17 + ## 0.1.9 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 6d00f621ac..0500193a8f 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.9", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 4fb6dec523..b6ef8bfede 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gitops-profiles +## 0.3.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.3.33 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index cda5452d9a..c6798383d6 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.33", + "version": "0.3.34-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index b06622a53e..2d576fa79b 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gocd +## 0.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.1.21 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 0e2f78e8d2..08c4d6991c 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.21", + "version": "0.1.22-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index d0f32d2729..0ee2c37177 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphiql +## 0.2.48-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.2.47 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 33e9605aa6..1d825744d8 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.47", + "version": "0.2.48-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 9ef3ca16c6..3497d58b44 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-backend +## 0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.19-next.0 + ## 0.1.32 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index ba1388a790..34fb0d6c04 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-backend", "description": "An experimental Backstage backend plugin for GraphQL", - "version": "0.1.32", + "version": "0.1.33-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md index 3eccc7f27b..678cec72b2 100644 --- a/plugins/graphql-voyager/CHANGELOG.md +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-voyager +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.0 ### Minor Changes diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index f4e36f3046..599bc1ce3c 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 5ac8a7912e..c28cc9159a 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-home +## 0.4.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.4.31 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index f3f545c1fd..28b17e89d2 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.31", + "version": "0.4.32-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index f74dc502ea..18025f037b 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-ilert +## 0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.2.4 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 7572a5725a..474f55845e 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.2.4", + "version": "0.2.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index 9d8732ef50..e9405af8a1 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-jenkins-backend +## 0.1.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-jenkins-common@0.1.14-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.32 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 314ef28b0b..11ae1d4799 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.1.32", + "version": "0.1.33-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index ec4a80c12c..dd692185f2 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-jenkins-common +## 0.1.14-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.13 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index 003a2e84b4..b745c50fa2 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.13", + "version": "0.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 2e38c955cf..58dfae66d4 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-jenkins +## 0.7.15-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-jenkins-common@0.1.14-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.7.14 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index aa7a7114f7..a756afba3c 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.7.14", + "version": "0.7.15-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index e7b1512157..89e8babe2e 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-kafka-backend +## 0.2.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.35 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 4bef8db597..33f5b667c6 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.35", + "version": "0.2.36-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index d0544308b5..8f0afda96d 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kafka +## 0.3.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.3.15 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 22790c3510..f829b4568d 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.3.15", + "version": "0.3.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index da155ef28e..26ad74cc1e 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes-backend +## 0.9.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-kubernetes-common@0.6.1-next.0 + ## 0.9.3 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 09736e9e8e..06c8df39f6 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.9.3", + "version": "0.9.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index a6212ee381..281d2a83af 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-kubernetes-common +## 0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + ## 0.6.0 ### Minor Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index c6da37cf2e..30c2e9befd 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-common", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", - "version": "0.6.0", + "version": "0.6.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index f6588349d3..a6f5a90e65 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes +## 0.7.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-kubernetes-common@0.6.1-next.0 + ## 0.7.8 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 8f8ccfd8e3..0538b099cb 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.7.8", + "version": "0.7.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md index 30b8acba19..a7a8b26203 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-lighthouse-backend +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-lighthouse-common@0.1.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index df787e1bfe..0af3f7f5fb 100644 --- a/plugins/lighthouse-backend/package.json +++ b/plugins/lighthouse-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-backend", "description": "Backend functionalities for lighthouse", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 040009bc2d..e2a035dabf 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-lighthouse +## 0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-lighthouse-common@0.1.0 + ## 0.4.0 ### Minor Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 8887a54bb2..3c9fe20494 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.4.0", + "version": "0.4.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist-backend/CHANGELOG.md b/plugins/linguist-backend/CHANGELOG.md index d703944d89..102c42c4cc 100644 --- a/plugins/linguist-backend/CHANGELOG.md +++ b/plugins/linguist-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-linguist-backend +## 0.2.0-next.0 + +### Minor Changes + +- 4a1c318853: **BREAKING** The linguist-backend `createRouter` now requires that the `tokenManger` is passed to the router. + +### Patch Changes + +- 2ea5782162: Fixed bug in LinguistBackendApi that caused initial batch of entities to be skipped. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-linguist-common@0.1.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index f5035d0f90..568730bc85 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist-backend", - "version": "0.1.0", + "version": "0.2.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist/CHANGELOG.md b/plugins/linguist/CHANGELOG.md index 13771bd259..ee28cf7354 100644 --- a/plugins/linguist/CHANGELOG.md +++ b/plugins/linguist/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-linguist +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-linguist-common@0.1.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index 1d33f5260d..61bb4b19a6 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/microsoft-calendar/CHANGELOG.md b/plugins/microsoft-calendar/CHANGELOG.md index c8437bc2fb..c9e1da8fb1 100644 --- a/plugins/microsoft-calendar/CHANGELOG.md +++ b/plugins/microsoft-calendar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-microsoft-calendar +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.1.0 ### Minor Changes diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 848169c527..c4b445c97b 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-microsoft-calendar", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 6963241558..c3de323d2d 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-newrelic-dashboard +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + ## 0.2.8 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index a93eb0ff59..462352b69e 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.2.8", + "version": "0.2.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index bac9a51946..ba75aface5 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-newrelic +## 0.3.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.3.33 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 2d4c48966a..32ee89f6aa 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.33", + "version": "0.3.34-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/octopus-deploy/CHANGELOG.md b/plugins/octopus-deploy/CHANGELOG.md new file mode 100644 index 0000000000..15be227555 --- /dev/null +++ b/plugins/octopus-deploy/CHANGELOG.md @@ -0,0 +1,16 @@ +# @backstage/plugin-octopus-deploy + +## 0.1.0-next.0 + +### Minor Changes + +- b7fff1171f: Initial version + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 3a8e3213ea..f62166478d 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-octopus-deploy", - "version": "0.0.0", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 59137d4ce7..54fd9629ce 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-org-react +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.1.4 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 19a8ea024f..8b51cd3d91 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.4", + "version": "0.1.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 3190de3335..2fd85644ff 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-org +## 0.6.6-next.0 + +### Patch Changes + +- 36bccb5252: Fix small UI-glitch in MemberListCard +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.6.5 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 4d63db8ea5..cbf97e95d4 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.6.5", + "version": "0.6.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 6a64484355..a69e2da666 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-pagerduty +## 0.5.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.5.8 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 44a9dc384c..3514bd2b75 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.5.8", + "version": "0.5.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index 68847c839e..55769cb201 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-periskop-backend +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + ## 0.1.13 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index f66a630185..ca7e096505 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.1.13", + "version": "0.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 76c75f9dae..1a700f5aa0 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-periskop +## 0.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.1.13 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 4445623ff4..2c1f98eb56 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.13", + "version": "0.1.14-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 53189129b0..87be1e49e1 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-backend +## 0.5.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + ## 0.5.17 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 06006dcbe6..bd3342e142 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.17", + "version": "0.5.18-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index b9c1d0f5d1..8d2789e615 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-node +## 0.7.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + ## 0.7.5 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index fbe7a8a41f..440b6f411b 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-node", "description": "Common permission and authorization utilities for backend plugins", - "version": "0.7.5", + "version": "0.7.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index cd3421bc44..914552da32 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-permission-react +## 0.4.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-permission-common@0.7.3 + ## 0.4.10 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index eeb98df610..dcf45270f4 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.10", + "version": "0.4.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index fe1154b081..9dcf4493ea 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-playlist-backend +## 0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-playlist-common@0.1.4 + ## 0.2.5 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 408629dffa..908362893a 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.2.5", + "version": "0.2.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index 368d66ee8d..e6d1a1d809 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-playlist +## 0.1.7-next.0 + +### Patch Changes + +- 122a37a880: Internal update to work with newer versions of react-router +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.11-next.0 + - @backstage/plugin-playlist-common@0.1.4 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 0.1.6 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 9b2ad57646..d30e6fb4b1 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.6", + "version": "0.1.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 96f2e16120..2f5c46445a 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-proxy-backend +## 0.2.37-next.0 + +### Patch Changes + +- 3e3eea4bc7: The proxy-backend plugin now supports reviving request bodies that have previously been consumed by an express middleware (e.g. `express.json()`). This is done by setting `reviveConsumedRequestBodies: true` on the proxy `RouterOptions`. In order to preserve the current behavior, the proxy will **not** revive request bodies by default. + + The following is an example of a proxy `createRouter` invocation that revives request bodies: + + ```diff + const router = await createRouter({ + config, + logger, + discovery, + + reviveConsumedRequestBodies: true, + }); + ``` + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + ## 0.2.36 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 21435d5e9c..7fa3f35e45 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.36", + "version": "0.2.37-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index dcb0805ac1..41a5df307f 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar-backend +## 0.1.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + ## 0.1.39 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index a574100983..28a0f1bf3b 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.39", + "version": "0.1.40-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index be98587ec1..77235a2c74 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-rollbar +## 0.4.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.4.15 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index e74c9a63ba..36b31e9338 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.4.15", + "version": "0.4.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 5537c72931..ed849b36f1 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + ## 0.2.17 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 84d43e0441..29a79640d2 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.2.17", + "version": "0.2.18-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 78d709b904..65cc7fa77d 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend@1.11.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + ## 0.4.10 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 3183508f92..2ae2a6dd3f 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.4.10", + "version": "0.4.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index f017eaf9e2..059b43bd90 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 35be906c44..8c1e2f5742 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.1.2", + "version": "0.1.3-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index e0d4e39c8b..c099722329 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + ## 0.2.15 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index b4ed76f0a3..6b609d8b39 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.2.15", + "version": "0.2.16-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index f68c91e237..2d31ac43c1 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-scaffolder-backend +## 1.11.1-next.0 + +### Patch Changes + +- c6c78b4acb: throw error from catalog:fetch scaffolder action when entity is null and optional is false +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-backend@1.8.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + - @backstage/plugin-scaffolder-node@0.1.1-next.0 + ## 1.11.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 121a5c8ed0..872759815b 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "1.11.0", + "version": "1.11.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index b37be62f2e..c9c785d777 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-scaffolder-common +## 1.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/types@1.0.2 + ## 1.2.5 ### Patch Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index cce88a450d..4e78d531e3 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "1.2.5", + "version": "1.2.6-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index 8d9d666ac1..5bc9d498b6 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-node +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index d4741a009b..642a59b801 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-node", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", - "version": "0.1.0", + "version": "0.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index dada3d4353..24ccc34e4e 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-react +## 1.1.1-next.0 + +### Patch Changes + +- c8d78b9ae9: fix bug with `hasErrors` returning false when dealing with empty objects +- 928a12a9b3: Internal refactor of `/alpha` exports. +- cc418d652a: scaffolder/next: Added the ability to get the fields definition in the schema in the validation function +- d4100d0ec4: Fix alignment bug for owners on `TemplateCard` +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + ## 1.1.0 ### Minor Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 14d25136e0..2d3e10ed9f 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.1.0", + "version": "1.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index d4aaf89ddc..2c12e00c10 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-scaffolder +## 1.11.1-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/plugin-scaffolder-react@1.1.1-next.0 + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-react@0.4.11-next.0 + - @backstage/plugin-scaffolder-common@1.2.6-next.0 + ## 1.11.0 ### Minor Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 15893b7ccb..c1e257b398 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "1.11.0", + "version": "1.11.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index bda1843d96..1a73eecf55 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 714bfa3096..d8e1ee7021 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "1.1.3", + "version": "1.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 90ea0c1a62..abfc6e5060 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 0.5.3 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index f1eef09082..f944cf7c59 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.5.3", + "version": "0.5.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index a434f2a8b1..eedafe3497 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search-backend-node +## 1.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index addca1b93c..f8ec1c00b0 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "1.1.3", + "version": "1.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 48df127d2d..3bd3b84554 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-search-backend +## 1.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.6-next.0 + - @backstage/plugin-search-backend-node@1.1.4-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 1.2.3 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index c4c85253e5..4eb8187a2a 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend", "description": "The Backstage backend plugin that provides your backstage app with search", - "version": "1.2.3", + "version": "1.2.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 8b75fde4db..52ac478207 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-search-react +## 1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.5.0 ### Minor Changes diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 589e28db79..fd8242b552 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.5.0", + "version": "1.5.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index cc0d10f5a5..974fcc4a5d 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-search +## 1.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 1.1.0 ### Minor Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index ddec50d70e..1e1552172f 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "1.1.0", + "version": "1.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 0a9e0a031a..1f23a87326 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sentry +## 0.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.5.0 ### Minor Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 5a9d3e5965..d68eb06ea9 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.5.0", + "version": "0.5.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 601d12293a..ed4df4535b 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-shortcuts +## 0.3.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + ## 0.3.7 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 31b984907a..64af56efbd 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.3.7", + "version": "0.3.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index 7c5b8cfa86..2543e6ca49 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-sonarqube-backend +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.7 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 80a85d955b..3934abe862 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.1.7", + "version": "0.1.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-react/CHANGELOG.md b/plugins/sonarqube-react/CHANGELOG.md index 87257ccda8..7372052227 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-sonarqube-react +## 0.1.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- 8ae65a0bc1: Moved imports from `/alpha` to main public exports. +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 80177d9e24..9a567040cb 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-react", - "version": "0.1.2", + "version": "0.1.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 04dec88ca9..7235835af6 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-sonarqube +## 0.6.5-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- 8ae65a0bc1: Moved imports from `/alpha` to main public exports. +- d3d624e8e8: Show a more appropriate icon if there are no code smells and/or vulnerabilities. +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-sonarqube-react@0.1.4-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.6.3 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index ce0a288d59..be3135f790 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.6.3", + "version": "0.6.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index e731d7fa24..abf9a2cca9 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-splunk-on-call +## 0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.4.4 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 4403d0a640..cd098d238f 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.4.4", + "version": "0.4.5-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 70a15d0417..d10de5de42 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-stack-overflow-backend +## 0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + ## 0.1.11 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index f4845de7a4..6698afc182 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.1.11", + "version": "0.1.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index f24e998a58..91ea342e8a 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-stack-overflow +## 0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-home@0.4.32-next.0 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 0.1.11 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 777e128aaa..2997d331f3 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.11", + "version": "0.1.12-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stackstorm/CHANGELOG.md b/plugins/stackstorm/CHANGELOG.md new file mode 100644 index 0000000000..c6718679a3 --- /dev/null +++ b/plugins/stackstorm/CHANGELOG.md @@ -0,0 +1,15 @@ +# @backstage/plugin-stackstorm + +## 0.1.0-next.0 + +### Minor Changes + +- f3a15259e9: Add StackStorm plugin to Backstage which is interfacing with StackStorm API. It allows users to view workflow executions, packs and actions. For installation and configuration instructions please view [README.md](https://github.com/backstage/backstage/tree/master/plugins/stackstorm/README.md) + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index c5b266782e..767abf5118 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-stackstorm", "description": "A Backstage plugin that integrates towards StackStorm", - "version": "0.0.0", + "version": "0.1.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index f529b48646..d97c864580 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.1-next.0 + ## 0.1.26 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index 6f43c730cf..062829135e 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend-module-jsonfc", - "version": "0.1.26", + "version": "0.1.27-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 115b6f505e..262e5a6d0a 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-tech-insights-backend +## 0.5.9-next.0 + +### Patch Changes + +- f244b58916: Add DB index to improve latency of latest fact query +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + - @backstage/plugin-tech-insights-node@0.4.1-next.0 + ## 0.5.8 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index d260229957..98152f39ac 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend", - "version": "0.5.8", + "version": "0.5.9-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 953ee74dbc..84694fc518 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-insights-node +## 0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + ## 0.4.0 ### Minor Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 08aedf87b3..e6a06bd615 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-node", - "version": "0.4.0", + "version": "0.4.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index b013b06868..1703832055 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-tech-insights +## 0.3.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10 + ## 0.3.7 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 7e4d8d9ab1..57def61d19 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.3.7", + "version": "0.3.8-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index 946583c945..0ac00e3cfe 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-tech-radar +## 0.6.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/theme@0.2.17 + ## 0.6.1 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index f69657776f..4686d329ef 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.6.1", + "version": "0.6.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index c4e4dc0571..7f8b72744e 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.11-next.0 + +### Patch Changes + +- 2b00d8a225: Fix bug/problem with test helper +- Updated dependencies + - @backstage/plugin-techdocs@1.6.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/test-utils@1.2.6-next.0 + - @backstage/plugin-catalog@1.9.0-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 1.0.10 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index c783fb53d7..673aafa93c 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.10", + "version": "1.0.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 3f846de942..4ba0a36a48 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-techdocs-backend +## 1.5.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-common@1.0.12-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.5.1-next.0 + ## 1.5.3 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index caf751423d..bcba399086 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "1.5.3", + "version": "1.5.4-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 7147a35221..abe7bc542f 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + ## 1.0.10 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 8b682095b9..233e933e89 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.0.10", + "version": "1.0.11-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 1d57db1599..4c14489d5a 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-techdocs-node +## 1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + ## 1.5.0 ### Minor Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 8e2d1998c8..4f458c4fff 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.5.0", + "version": "1.5.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 287693865f..fdaba0ebe4 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs-react +## 1.1.4-next.0 + +### Patch Changes + +- 928a12a9b3: Internal refactor of `/alpha` exports. +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/version-bridge@1.0.3 + ## 1.1.3 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 7f7fd06bec..1b184136b3 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.1.3", + "version": "1.1.4-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 2ed0c4fa79..01a028f605 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-techdocs +## 1.6.0-next.0 + +### Minor Changes + +- 3f75b7607c: Add ability to pass icon as function to have ability to customize it by search item + +### Patch Changes + +- f320c299c6: The HTML tag attributes in the documentation content inserted to shadow DOM is preserved to improve accessibility +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-techdocs-react@1.1.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.11-next.0 + - @backstage/theme@0.2.17 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-search-react@1.5.1-next.0 + ## 1.5.0 ### Minor Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 42f6103b04..308987f757 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "1.5.0", + "version": "1.6.0-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 42b6b6f37e..39a9a56a70 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-todo-backend +## 0.1.40-next.0 + +### Patch Changes + +- 4120513412: todo-backend is now exposed as a plugin which uses the new plugin system +- Updated dependencies + - @backstage/catalog-client@1.4.0-next.0 + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/plugin-catalog-node@1.3.4-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.39 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index e3e15e4f06..a0a1db2e0e 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.1.39", + "version": "0.1.40-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 558e0ca6bc..35c607ba30 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo +## 0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.2.17 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index cc988b3f45..979ee1dacc 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.2.17", + "version": "0.2.18-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 64becea637..4a6c211adb 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-user-settings-backend +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.1-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.12-next.0 + ## 0.1.6 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 4461bfea8c..61ef65c231 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings-backend", "description": "The Backstage backend plugin to manage user settings", - "version": "0.1.6", + "version": "0.1.7-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 66cd543061..784956b16d 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-user-settings +## 0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-app-api@1.5.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + - @backstage/types@1.0.2 + ## 0.7.0 ### Minor Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 4c5780257e..85614aa8db 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.7.0", + "version": "0.7.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 946e776371..4f57faf78e 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-vault-backend +## 0.2.10-next.0 + +### Patch Changes + +- 66b3a3956b: Ignore the `eslint` error +- Updated dependencies + - @backstage/backend-tasks@0.4.4-next.0 + - @backstage/backend-common@0.18.3-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.8 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 08e6553e6a..fc6fab1b41 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.2.8", + "version": "0.2.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index 2bc324e0a5..3b79e99c42 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-vault +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.4.0-next.0 + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/catalog-model@1.2.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.1.9 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 934333f21b..163f9a649d 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.9", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index df67db6b94..7a727aa92a 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-xcmetrics +## 0.2.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.4.1-next.0 + - @backstage/core-components@0.12.5-next.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.17 + ## 0.2.35 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index a2e8c226b3..15be9d2579 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.35", + "version": "0.2.36-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/yarn.lock b/yarn.lock index d20206d507..55dcfb3a67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3591,6 +3591,17 @@ __metadata: languageName: unknown linkType: soft +"@backstage/catalog-client@npm:^1.3.1": + version: 1.3.1 + resolution: "@backstage/catalog-client@npm:1.3.1" + dependencies: + "@backstage/catalog-model": ^1.2.0 + "@backstage/errors": ^1.1.4 + cross-fetch: ^3.1.5 + checksum: e2e0050d93f509fbaed40d89228ce9af7c9f32372c721d5faea29ef312e488cbfc1426959f39d61790d41406fbd6bc895bed2c3427bbdf6cab6a412f449c2efe + languageName: node + linkType: hard + "@backstage/catalog-client@workspace:^, @backstage/catalog-client@workspace:packages/catalog-client": version: 0.0.0-use.local resolution: "@backstage/catalog-client@workspace:packages/catalog-client" @@ -3603,7 +3614,22 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-model@^1.1.3, @backstage/catalog-model@^1.1.5, @backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@npm:^1.1.3, @backstage/catalog-model@npm:^1.1.5, @backstage/catalog-model@npm:^1.2.0": + version: 1.2.0 + resolution: "@backstage/catalog-model@npm:1.2.0" + dependencies: + "@backstage/config": ^1.0.6 + "@backstage/errors": ^1.1.4 + "@backstage/types": ^1.0.2 + ajv: ^8.10.0 + json-schema: ^0.4.0 + lodash: ^4.17.21 + uuid: ^8.0.0 + checksum: d4e07e91e501b4ecbc9d0b754518277dd2ed93f22f801740cc539dbcbd905ba8111b1651d20fb725e44d7cd99a96faec6fd56cd51fdf8e1d7f39a6e177f31efa + languageName: node + linkType: hard + +"@backstage/catalog-model@workspace:^, @backstage/catalog-model@workspace:packages/catalog-model": version: 0.0.0-use.local resolution: "@backstage/catalog-model@workspace:packages/catalog-model" dependencies: @@ -3818,7 +3844,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config@^1.0.4, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": +"@backstage/config@^1.0.4, @backstage/config@^1.0.6, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": version: 0.0.0-use.local resolution: "@backstage/config@workspace:packages/config" dependencies: @@ -3864,7 +3890,57 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-components@^0.12.0, @backstage/core-components@^0.12.3, @backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": +"@backstage/core-components@npm:^0.12.0, @backstage/core-components@npm:^0.12.3, @backstage/core-components@npm:^0.12.4": + version: 0.12.4 + resolution: "@backstage/core-components@npm:0.12.4" + dependencies: + "@backstage/config": ^1.0.6 + "@backstage/core-plugin-api": ^1.4.0 + "@backstage/errors": ^1.1.4 + "@backstage/theme": ^0.2.17 + "@backstage/version-bridge": ^1.0.3 + "@material-table/core": ^3.1.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + "@react-hookz/web": ^20.0.0 + "@types/react-sparklines": ^1.7.0 + "@types/react-text-truncate": ^0.14.0 + ansi-regex: ^6.0.1 + classnames: ^2.2.6 + d3-selection: ^3.0.0 + d3-shape: ^3.0.0 + d3-zoom: ^3.0.0 + dagre: ^0.8.5 + history: ^5.0.0 + immer: ^9.0.1 + lodash: ^4.17.21 + pluralize: ^8.0.0 + prop-types: ^15.7.2 + qs: ^6.9.4 + rc-progress: 3.4.1 + react-helmet: 6.1.0 + react-hook-form: ^7.12.2 + react-markdown: ^8.0.0 + react-sparklines: ^1.7.0 + react-syntax-highlighter: ^15.4.5 + react-text-truncate: ^0.19.0 + react-use: ^17.3.2 + react-virtualized-auto-sizer: ^1.0.6 + react-window: ^1.8.6 + remark-gfm: ^3.0.1 + zen-observable: ^0.10.0 + zod: ~3.18.0 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-dom: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 476160ad54a399e7393bb70fc34fc01b69519431606797fdecc974d5e826315527d8ab71af5dd4d1c8d88bfe797aa37e781fd5fd31d8293c19982704e4f7cfdc + languageName: node + linkType: hard + +"@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" dependencies: @@ -3935,7 +4011,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-plugin-api@^1.1.0, @backstage/core-plugin-api@^1.3.0, @backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": +"@backstage/core-plugin-api@npm:^1.1.0, @backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.4.0": + version: 1.4.0 + resolution: "@backstage/core-plugin-api@npm:1.4.0" + dependencies: + "@backstage/config": ^1.0.6 + "@backstage/types": ^1.0.2 + "@backstage/version-bridge": ^1.0.3 + history: ^5.0.0 + prop-types: ^15.7.2 + zen-observable: ^0.10.0 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 046d0fcb52b3110d6a926eeaf766486c753c2eeca70f7897f4ded45e0cf7da8591ec7df337433427bc50de7193e7a6d875356a027a8d1733fa07d87509e561a1 + languageName: node + linkType: hard + +"@backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": version: 0.0.0-use.local resolution: "@backstage/core-plugin-api@workspace:packages/core-plugin-api" dependencies: @@ -4020,7 +4114,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": +"@backstage/errors@^1.1.4, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": version: 0.0.0-use.local resolution: "@backstage/errors@workspace:packages/errors" dependencies: @@ -4061,7 +4155,26 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@^1.1.9, @backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/integration-react@npm:^1.1.9": + version: 1.1.10 + resolution: "@backstage/integration-react@npm:1.1.10" + dependencies: + "@backstage/config": ^1.0.6 + "@backstage/core-components": ^0.12.4 + "@backstage/core-plugin-api": ^1.4.0 + "@backstage/integration": ^1.4.2 + "@backstage/theme": ^0.2.17 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + checksum: 248e11c74fed7fb6d5fcc9cf7f7d7baffe94a6a4091aff60afc46c797b08a63486baaffe32812c237e29e3cb295d429b1cd740ca704b43b7dc4704a910184716 + languageName: node + linkType: hard + +"@backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": version: 0.0.0-use.local resolution: "@backstage/integration-react@workspace:packages/integration-react" dependencies: @@ -4088,7 +4201,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": +"@backstage/integration@^1.4.2, @backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" dependencies: @@ -5147,7 +5260,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@^1.0.8, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": +"@backstage/plugin-catalog-common@npm:^1.0.11, @backstage/plugin-catalog-common@npm:^1.0.8": + version: 1.0.11 + resolution: "@backstage/plugin-catalog-common@npm:1.0.11" + dependencies: + "@backstage/catalog-model": ^1.2.0 + "@backstage/plugin-permission-common": ^0.7.3 + "@backstage/plugin-search-common": ^1.2.1 + checksum: e0e37a96b4d97230c590fc4f1e17f252167a3cbbc79533c7e29a26d3480e82435c57ae6f7952aaf694bd8dc22245410c9fd29853249b1b73ed3a009dd49bce6b + languageName: node + linkType: hard + +"@backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-common@workspace:plugins/catalog-common" dependencies: @@ -5275,7 +5399,42 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@^1.2.1, @backstage/plugin-catalog-react@^1.2.4, @backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": +"@backstage/plugin-catalog-react@npm:^1.2.1, @backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.3.0": + version: 1.3.0 + resolution: "@backstage/plugin-catalog-react@npm:1.3.0" + dependencies: + "@backstage/catalog-client": ^1.3.1 + "@backstage/catalog-model": ^1.2.0 + "@backstage/core-components": ^0.12.4 + "@backstage/core-plugin-api": ^1.4.0 + "@backstage/errors": ^1.1.4 + "@backstage/integration": ^1.4.2 + "@backstage/plugin-catalog-common": ^1.0.11 + "@backstage/plugin-permission-common": ^0.7.3 + "@backstage/plugin-permission-react": ^0.4.10 + "@backstage/theme": ^0.2.17 + "@backstage/types": ^1.0.2 + "@backstage/version-bridge": ^1.0.3 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + classnames: ^2.2.6 + jwt-decode: ^3.1.0 + lodash: ^4.17.21 + material-ui-popup-state: ^1.9.3 + qs: ^6.9.4 + react-use: ^17.2.4 + yaml: ^2.0.0 + zen-observable: ^0.10.0 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 03cd5a270154c0cde63bd33104d11ba5811690205c697441f207606d961935f5c45ad2a8e17f591c5ac8b294601c1855852bac35ccb30125e2ab6df13daf82d2 + languageName: node + linkType: hard + +"@backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-react@workspace:plugins/catalog-react" dependencies: @@ -6461,7 +6620,30 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-home@^0.4.30, @backstage/plugin-home@workspace:^, @backstage/plugin-home@workspace:plugins/home": +"@backstage/plugin-home@npm:^0.4.30": + version: 0.4.31 + resolution: "@backstage/plugin-home@npm:0.4.31" + dependencies: + "@backstage/catalog-model": ^1.2.0 + "@backstage/config": ^1.0.6 + "@backstage/core-components": ^0.12.4 + "@backstage/core-plugin-api": ^1.4.0 + "@backstage/plugin-catalog-react": ^1.3.0 + "@backstage/theme": ^0.2.17 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + lodash: ^4.17.21 + react-use: ^17.2.4 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 2ba5d377713540a4f9ab7083bc1595361678b59c80d57f26f2fe0bd660ec77926a6bfdeb52a2c6179e809e5186360333ae1bb41f51e741c4bdb7fc3edfda60c3 + languageName: node + linkType: hard + +"@backstage/plugin-home@workspace:^, @backstage/plugin-home@workspace:plugins/home": version: 0.0.0-use.local resolution: "@backstage/plugin-home@workspace:plugins/home" dependencies: @@ -7155,7 +7337,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": +"@backstage/plugin-permission-common@^0.7.3, @backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-common@workspace:plugins/permission-common" dependencies: @@ -7192,6 +7374,24 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-permission-react@npm:^0.4.10": + version: 0.4.10 + resolution: "@backstage/plugin-permission-react@npm:0.4.10" + dependencies: + "@backstage/config": ^1.0.6 + "@backstage/core-plugin-api": ^1.4.0 + "@backstage/plugin-permission-common": ^0.7.3 + cross-fetch: ^3.1.5 + react-use: ^17.2.4 + swr: ^2.0.0 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: f7a82648a31a8fe9873492abdbcc524549205e3fd11fe144ab225e6263ce2b2e46abd642e6c370d692d424c51e7c55b9259d8178500f9bfbfc9267d09596843c + languageName: node + linkType: hard + "@backstage/plugin-permission-react@workspace:^, @backstage/plugin-permission-react@workspace:plugins/permission-react": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-react@workspace:plugins/permission-react" @@ -7747,7 +7947,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": +"@backstage/plugin-search-common@^1.2.1, @backstage/plugin-search-common@workspace:^, @backstage/plugin-search-common@workspace:plugins/search-common": version: 0.0.0-use.local resolution: "@backstage/plugin-search-common@workspace:plugins/search-common" dependencies: @@ -8703,7 +8903,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.2.16, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": +"@backstage/theme@^0.2.16, @backstage/theme@^0.2.17, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": version: 0.0.0-use.local resolution: "@backstage/theme@workspace:packages/theme" dependencies: @@ -8712,7 +8912,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/types@^1.0.1, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": +"@backstage/types@^1.0.1, @backstage/types@^1.0.2, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@backstage/types@workspace:packages/types" dependencies: @@ -8723,7 +8923,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/version-bridge@^1.0.2, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": +"@backstage/version-bridge@^1.0.2, @backstage/version-bridge@^1.0.3, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": version: 0.0.0-use.local resolution: "@backstage/version-bridge@workspace:packages/version-bridge" dependencies: From 8426450aa260f0c0ee8014503792b312abc4becb Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 17:58:26 +0100 Subject: [PATCH 384/417] chore: microsite build speed improvements Signed-off-by: blam --- microsite-next/docusaurus.config.js | 19 ++- microsite-next/package.json | 4 +- .../bannerSection/bannerSectionGrid.tsx | 3 - microsite-next/yarn.lock | 121 ++++++++++++++++++ 4 files changed, 141 insertions(+), 6 deletions(-) diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index a5dbd144da..4b44604ab5 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -47,8 +47,6 @@ module.exports = { /** @type {import('@docusaurus/preset-classic').Options} */ { docs: { - showLastUpdateAuthor: true, - showLastUpdateTime: true, editUrl: 'https://github.com/backstage/backstage/edit/master/docs/', path: '../docs', sidebarPath: 'sidebars.json', @@ -65,6 +63,23 @@ module.exports = { }, ], ], + webpack: { + jsLoader: isServer => ({ + loader: require.resolve('swc-loader'), + options: { + jsc: { + parser: { + syntax: 'typescript', + tsx: true, + }, + target: 'es2017', + }, + module: { + type: isServer ? 'commonjs' : 'es6', + }, + }, + }), + }, plugins: [ 'docusaurus-plugin-sass', () => ({ diff --git a/microsite-next/package.json b/microsite-next/package.json index f56ed6ae39..c223e87584 100644 --- a/microsite-next/package.json +++ b/microsite-next/package.json @@ -31,10 +31,12 @@ "dependencies": { "@docusaurus/core": "2.3.1", "@docusaurus/preset-classic": "2.3.1", + "@swc/core": "^1.3.36", "clsx": "^1.1.1", "docusaurus-plugin-sass": "^0.2.3", "react": "^17.0.2", "react-dom": "^17.0.2", - "sass": "^1.57.1" + "sass": "^1.57.1", + "swc-loader": "^0.2.3" } } diff --git a/microsite-next/src/components/bannerSection/bannerSectionGrid.tsx b/microsite-next/src/components/bannerSection/bannerSectionGrid.tsx index 639cc0a97c..dc9853d1fe 100644 --- a/microsite-next/src/components/bannerSection/bannerSectionGrid.tsx +++ b/microsite-next/src/components/bannerSection/bannerSectionGrid.tsx @@ -6,7 +6,6 @@ import bannerGridStyles from './bannerSectionGrid.module.scss'; export type IBannerSectionColumnsProps = PropsWithChildren<{ header?: ReactNode; className?: string; - // children: ReactNode | ReactNode[]; }>; export const BannerSectionGrid = ({ @@ -14,8 +13,6 @@ export const BannerSectionGrid = ({ children, className, }: IBannerSectionColumnsProps) => { - console.log('Header: ', header); - return (

    {header &&
    {header}
    } diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 81d5c07f6f..98d0e36c7a 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -2603,6 +2603,115 @@ __metadata: languageName: node linkType: hard +"@swc/core-darwin-arm64@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-darwin-arm64@npm:1.3.36" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@swc/core-darwin-x64@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-darwin-x64@npm:1.3.36" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@swc/core-linux-arm-gnueabihf@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.36" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@swc/core-linux-arm64-gnu@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.36" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@swc/core-linux-arm64-musl@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.36" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@swc/core-linux-x64-gnu@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.36" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@swc/core-linux-x64-musl@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-x64-musl@npm:1.3.36" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@swc/core-win32-arm64-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.36" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@swc/core-win32-ia32-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.36" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@swc/core-win32-x64-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.36" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@swc/core@npm:^1.3.36": + version: 1.3.36 + resolution: "@swc/core@npm:1.3.36" + dependencies: + "@swc/core-darwin-arm64": 1.3.36 + "@swc/core-darwin-x64": 1.3.36 + "@swc/core-linux-arm-gnueabihf": 1.3.36 + "@swc/core-linux-arm64-gnu": 1.3.36 + "@swc/core-linux-arm64-musl": 1.3.36 + "@swc/core-linux-x64-gnu": 1.3.36 + "@swc/core-linux-x64-musl": 1.3.36 + "@swc/core-win32-arm64-msvc": 1.3.36 + "@swc/core-win32-ia32-msvc": 1.3.36 + "@swc/core-win32-x64-msvc": 1.3.36 + dependenciesMeta: + "@swc/core-darwin-arm64": + optional: true + "@swc/core-darwin-x64": + optional: true + "@swc/core-linux-arm-gnueabihf": + optional: true + "@swc/core-linux-arm64-gnu": + optional: true + "@swc/core-linux-arm64-musl": + optional: true + "@swc/core-linux-x64-gnu": + optional: true + "@swc/core-linux-x64-musl": + optional: true + "@swc/core-win32-arm64-msvc": + optional: true + "@swc/core-win32-ia32-msvc": + optional: true + "@swc/core-win32-x64-msvc": + optional: true + checksum: 36e96e86d1ab8fd84eb51e7264a7ae781ee7e507d36b9ccc028d7f31a2ccf2949f074656e34139c970196774d24d55a54c3aa5c53d04eb6e3569c71cbfed0c0d + languageName: node + linkType: hard + "@szmarczak/http-timer@npm:^1.1.2": version: 1.1.2 resolution: "@szmarczak/http-timer@npm:1.1.2" @@ -3601,6 +3710,7 @@ __metadata: "@docusaurus/module-type-aliases": 2.3.1 "@docusaurus/preset-classic": 2.3.1 "@spotify/prettier-config": ^14.0.0 + "@swc/core": ^1.3.36 "@tsconfig/docusaurus": ^1.0.6 "@types/webpack-env": ^1.18.0 clsx: ^1.1.1 @@ -3611,6 +3721,7 @@ __metadata: react-dom: ^17.0.2 replace: ^1.2.2 sass: ^1.57.1 + swc-loader: ^0.2.3 typescript: ^4.9.4 yaml-loader: ^0.8.0 languageName: unknown @@ -9998,6 +10109,16 @@ __metadata: languageName: node linkType: hard +"swc-loader@npm:^0.2.3": + version: 0.2.3 + resolution: "swc-loader@npm:0.2.3" + peerDependencies: + "@swc/core": ^1.2.147 + webpack: ">=2" + checksum: 010d84d399525c0185d36d62c86c55ae017e7a90046bc8a39be4b7e07526924037868049f6037bc966da98151cb2600934b96a66279b742d3c413a718b427251 + languageName: node + linkType: hard + "tapable@npm:^1.0.0": version: 1.1.3 resolution: "tapable@npm:1.1.3" From c3bf22a2455ae35b29d225f11bfe9d8be6d15d3f Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 18:00:09 +0100 Subject: [PATCH 385/417] chore: add the concurrency Signed-off-by: blam --- .github/workflows/deploy_microsite.yml | 1 + .github/workflows/verify_microsite-next.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 61a0cd5b0f..1b0f7753bd 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -15,6 +15,7 @@ jobs: env: CI: true NODE_OPTIONS: --max-old-space-size=4096 + DOCUSAURUS_SSR_CONCURRENCY: 5 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/verify_microsite-next.yml b/.github/workflows/verify_microsite-next.yml index ea0cbae0be..fc42ec4225 100644 --- a/.github/workflows/verify_microsite-next.yml +++ b/.github/workflows/verify_microsite-next.yml @@ -17,6 +17,7 @@ jobs: env: CI: true NODE_OPTIONS: --max-old-space-size=4096 + DOCUSAURUS_SSR_CONCURRENCY: 5 steps: - uses: actions/checkout@v3 From 19985912e78f62729d6cbdbd10b8cf667b9cd7b3 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 20:00:02 +0100 Subject: [PATCH 386/417] chore: make sure to build the api-docs Signed-off-by: blam --- .github/workflows/verify_microsite-next.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/verify_microsite-next.yml b/.github/workflows/verify_microsite-next.yml index fc42ec4225..6c9edf2031 100644 --- a/.github/workflows/verify_microsite-next.yml +++ b/.github/workflows/verify_microsite-next.yml @@ -29,10 +29,16 @@ jobs: # Skip caching of microsite dependencies, it keeps the global cache size # smaller, which make Windows builds a lot faster for the rest of the project. + - name: top-level install + run: yarn install --immutable + - name: yarn install run: yarn install --immutable working-directory: microsite-next + - name: build API reference + run: yarn build:api-docs + - name: verify yarn dependency duplicates run: node scripts/verify-lockfile-duplicates.js From 47d246691ac11ca2da2c27687173f89344c3b9d0 Mon Sep 17 00:00:00 2001 From: Mark David Avery Date: Thu, 16 Feb 2023 20:40:13 -0800 Subject: [PATCH 387/417] fix(plugin-entity-validation): using location for the value rather than default location Fixes #16406 Signed-off-by: Mark David Avery --- .changeset/khaki-poems-run.md | 5 +++++ plugins/entity-validation/dev/index.tsx | 9 +++++++++ .../EntityValidationPage.tsx | 19 +++++++------------ 3 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 .changeset/khaki-poems-run.md diff --git a/.changeset/khaki-poems-run.md b/.changeset/khaki-poems-run.md new file mode 100644 index 0000000000..74db902c02 --- /dev/null +++ b/.changeset/khaki-poems-run.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-entity-validation': patch +--- + +Fixed bug in EntityVaidation plugin where string in text box was unable to be updated. diff --git a/plugins/entity-validation/dev/index.tsx b/plugins/entity-validation/dev/index.tsx index 1e1dfa760c..42f4b152ed 100644 --- a/plugins/entity-validation/dev/index.tsx +++ b/plugins/entity-validation/dev/index.tsx @@ -16,9 +16,18 @@ import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; import { entityValidationPlugin, EntityValidationPage } from '../src/plugin'; +import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; createDevApp() .registerPlugin(entityValidationPlugin) + .registerApi({ + api: catalogApiRef, + deps: {}, + factory: () => + ({ + getEntities: () => ({}), + } as CatalogApi), + }) .addPage({ element: , title: 'Root Page', diff --git a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx index dc86af8763..52628e6ad2 100644 --- a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx +++ b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React, { useState } from 'react'; -import { Button, Content, Header, Page } from '@backstage/core-components'; +import { Content, Header, LinkButton, Page } from '@backstage/core-components'; import { EntityTextArea } from '../EntityTextArea'; import { Grid, TextField } from '@material-ui/core'; import { CatalogProcessorResult } from '../../types'; @@ -47,7 +47,7 @@ export const EntityValidationPage = (props: { const [catalogYaml, setCatalogYaml] = useState(defaultYaml); const [yamlFiles, setYamlFiles] = useState(); - const [locationUrl, setLocationUrl] = useState(''); + const [locationUrl, setLocationUrl] = useState(defaultLocation); const parseYaml = () => { const parsedFiles = [ @@ -66,15 +66,15 @@ export const EntityValidationPage = (props: { subtitle="Tool to validate catalog-info.yaml files" /> - + setLocationUrl(e.target.value)} @@ -83,14 +83,9 @@ export const EntityValidationPage = (props: { - + From cfa7f8c5175c7c00c711936f96a39f16eb3deffe Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 21 Feb 2023 23:11:33 +0100 Subject: [PATCH 388/417] chore: add comment and fix Signed-off-by: blam --- packages/test-utils/src/testUtils/TestApiProvider.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index f38433ace9..c212b94bea 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -91,6 +91,10 @@ export class TestApiRegistry implements ApiHolder { * It lets you provide any number of API implementations, without necessarily * having to fully implement each of the APIs. * + * @remarks + * todo: remove this remark tag and ship in the api-reference. There's some odd formatting going on when this is made into a markdown doc, that there's no line break between + * the emmited

    for To the following

    so what happens is that when parsing in docusaurus, it thinks that the code block is mdx rather than a code + * snippet. Just ommiting this from the report for now until we can work out how to fix laterr. * A migration from `ApiRegistry` and `ApiProvider` might look like this, from: * * ```tsx @@ -100,7 +104,7 @@ export class TestApiRegistry implements ApiHolder { * [identityApiRef, mockIdentityApi as unknown as IdentityApi] * ])} * > - * // ... + * ... * * ) * ``` @@ -110,7 +114,7 @@ export class TestApiRegistry implements ApiHolder { * ```tsx * renderInTestApp( * - * // ... + * ... * * ) * ``` From 9888031078c2fb9548463138bd6c0804dc081fe2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 00:34:43 +0000 Subject: [PATCH 389/417] fix(deps): update dependency @swc/core to v1.3.36 Signed-off-by: Renovate Bot --- storybook/yarn.lock | 86 ++++++++++++++++++++++----------------------- yarn.lock | 86 ++++++++++++++++++++++----------------------- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 9bcd4ed45c..5584e16296 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2966,90 +2966,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-darwin-arm64@npm:1.3.35" +"@swc/core-darwin-arm64@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-darwin-arm64@npm:1.3.36" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-darwin-x64@npm:1.3.35" +"@swc/core-darwin-x64@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-darwin-x64@npm:1.3.36" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.35" +"@swc/core-linux-arm-gnueabihf@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.36" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.35" +"@swc/core-linux-arm64-gnu@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.36" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.35" +"@swc/core-linux-arm64-musl@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.36" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.35" +"@swc/core-linux-x64-gnu@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.36" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-x64-musl@npm:1.3.35" +"@swc/core-linux-x64-musl@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-x64-musl@npm:1.3.36" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.35" +"@swc/core-win32-arm64-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.36" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.35" +"@swc/core-win32-ia32-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.36" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.35" +"@swc/core-win32-x64-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.36" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.35 - resolution: "@swc/core@npm:1.3.35" + version: 1.3.36 + resolution: "@swc/core@npm:1.3.36" dependencies: - "@swc/core-darwin-arm64": 1.3.35 - "@swc/core-darwin-x64": 1.3.35 - "@swc/core-linux-arm-gnueabihf": 1.3.35 - "@swc/core-linux-arm64-gnu": 1.3.35 - "@swc/core-linux-arm64-musl": 1.3.35 - "@swc/core-linux-x64-gnu": 1.3.35 - "@swc/core-linux-x64-musl": 1.3.35 - "@swc/core-win32-arm64-msvc": 1.3.35 - "@swc/core-win32-ia32-msvc": 1.3.35 - "@swc/core-win32-x64-msvc": 1.3.35 + "@swc/core-darwin-arm64": 1.3.36 + "@swc/core-darwin-x64": 1.3.36 + "@swc/core-linux-arm-gnueabihf": 1.3.36 + "@swc/core-linux-arm64-gnu": 1.3.36 + "@swc/core-linux-arm64-musl": 1.3.36 + "@swc/core-linux-x64-gnu": 1.3.36 + "@swc/core-linux-x64-musl": 1.3.36 + "@swc/core-win32-arm64-msvc": 1.3.36 + "@swc/core-win32-ia32-msvc": 1.3.36 + "@swc/core-win32-x64-msvc": 1.3.36 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -3071,7 +3071,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: 263e01904fe4f4d6cbf6deef90439d6d93f28c04252d917fc290aadde131a1716820eb488a615b3c0dbe3f48d6d7ac0f1c886e2c2acd07a72e3d99e4a245b3de + checksum: 36e96e86d1ab8fd84eb51e7264a7ae781ee7e507d36b9ccc028d7f31a2ccf2949f074656e34139c970196774d24d55a54c3aa5c53d04eb6e3569c71cbfed0c0d languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 48294a3bf5..411d54d94d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13718,90 +13718,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-darwin-arm64@npm:1.3.35" +"@swc/core-darwin-arm64@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-darwin-arm64@npm:1.3.36" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-darwin-x64@npm:1.3.35" +"@swc/core-darwin-x64@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-darwin-x64@npm:1.3.36" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.35" +"@swc/core-linux-arm-gnueabihf@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.36" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.35" +"@swc/core-linux-arm64-gnu@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.36" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.35" +"@swc/core-linux-arm64-musl@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.36" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.35" +"@swc/core-linux-x64-gnu@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.36" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-linux-x64-musl@npm:1.3.35" +"@swc/core-linux-x64-musl@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-linux-x64-musl@npm:1.3.36" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.35" +"@swc/core-win32-arm64-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.36" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.35" +"@swc/core-win32-ia32-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.36" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.35": - version: 1.3.35 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.35" +"@swc/core-win32-x64-msvc@npm:1.3.36": + version: 1.3.36 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.36" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.35 - resolution: "@swc/core@npm:1.3.35" + version: 1.3.36 + resolution: "@swc/core@npm:1.3.36" dependencies: - "@swc/core-darwin-arm64": 1.3.35 - "@swc/core-darwin-x64": 1.3.35 - "@swc/core-linux-arm-gnueabihf": 1.3.35 - "@swc/core-linux-arm64-gnu": 1.3.35 - "@swc/core-linux-arm64-musl": 1.3.35 - "@swc/core-linux-x64-gnu": 1.3.35 - "@swc/core-linux-x64-musl": 1.3.35 - "@swc/core-win32-arm64-msvc": 1.3.35 - "@swc/core-win32-ia32-msvc": 1.3.35 - "@swc/core-win32-x64-msvc": 1.3.35 + "@swc/core-darwin-arm64": 1.3.36 + "@swc/core-darwin-x64": 1.3.36 + "@swc/core-linux-arm-gnueabihf": 1.3.36 + "@swc/core-linux-arm64-gnu": 1.3.36 + "@swc/core-linux-arm64-musl": 1.3.36 + "@swc/core-linux-x64-gnu": 1.3.36 + "@swc/core-linux-x64-musl": 1.3.36 + "@swc/core-win32-arm64-msvc": 1.3.36 + "@swc/core-win32-ia32-msvc": 1.3.36 + "@swc/core-win32-x64-msvc": 1.3.36 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -13823,7 +13823,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: 263e01904fe4f4d6cbf6deef90439d6d93f28c04252d917fc290aadde131a1716820eb488a615b3c0dbe3f48d6d7ac0f1c886e2c2acd07a72e3d99e4a245b3de + checksum: 36e96e86d1ab8fd84eb51e7264a7ae781ee7e507d36b9ccc028d7f31a2ccf2949f074656e34139c970196774d24d55a54c3aa5c53d04eb6e3569c71cbfed0c0d languageName: node linkType: hard From 7b7e5caca084e7b03dbac321cae0fc16c729d2a0 Mon Sep 17 00:00:00 2001 From: Stefan Fuchs Date: Wed, 22 Feb 2023 11:49:16 +1100 Subject: [PATCH 390/417] Render database configuration link correctly This fixes an issue where a markdown link isn't rendered correctly in the 3rd paragraph here: https://backstage.io/docs/tutorials/configuring-plugin-databases#connection-configuration-per-plugin Signed-off-by: Stefan Fuchs --- docs/tutorials/configuring-plugin-databases.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/configuring-plugin-databases.md b/docs/tutorials/configuring-plugin-databases.md index 34e62c285a..8cd5ce99a9 100644 --- a/docs/tutorials/configuring-plugin-databases.md +++ b/docs/tutorials/configuring-plugin-databases.md @@ -21,8 +21,8 @@ instance or cluster. With infrastructure defined as code or data (Terraform, AWS CloudFormation, etc.), you may have database credentials which lack permissions to create new databases or you do not have control over the database names. In these -instances, you can set the database connection configuration on a [per plugin basis] -(#connection-configuration-per-plugin). +instances, you can set the database connection configuration on a +[per plugin basis](#connection-configuration-per-plugin). Backstage supports all of these use cases with the `DatabaseManager` provided by `@backstage/backend-common`. We will now cover how to use and configure From 519477cf8c19975e1195f79edd24619fc868270f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 00:55:10 +0000 Subject: [PATCH 391/417] fix(deps): update dependency @tanstack/react-query to v4.24.10 Signed-off-by: Renovate Bot --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index cb756d1903..f08867b72d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13857,18 +13857,18 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:4.24.9": - version: 4.24.9 - resolution: "@tanstack/query-core@npm:4.24.9" - checksum: 7b84e960d82c046c9eef6083cbc13b21c2ed8552fe8a5f092a66ca2586af66b770ca71ad838135ef49ac8b990e5f85d34a1d8b8de13fffb3abb0fb780a64a532 +"@tanstack/query-core@npm:4.24.10": + version: 4.24.10 + resolution: "@tanstack/query-core@npm:4.24.10" + checksum: 8268b9dca4a2ed39f8575976d8a3e2f839bb6f4fb821dc00ba8e2aeffffe2f73e23344bcc24b9cb6dae9dbfe3ba2b14c76a1e0a38b4064c83beb9aa607fd94bc languageName: node linkType: hard "@tanstack/react-query@npm:^4.1.3": - version: 4.24.9 - resolution: "@tanstack/react-query@npm:4.24.9" + version: 4.24.10 + resolution: "@tanstack/react-query@npm:4.24.10" dependencies: - "@tanstack/query-core": 4.24.9 + "@tanstack/query-core": 4.24.10 use-sync-external-store: ^1.2.0 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -13879,7 +13879,7 @@ __metadata: optional: true react-native: optional: true - checksum: 409c945c5043d11fa2f3c219254df5b0505bdf7d9dc94821f5db495d87a38fe27e0a373144446cef42fc829d1449a64e3fa873adf37e8abe15562e5832d59516 + checksum: 576a2c73e98cf6a3c9584283989383d5ac63b01efe546cc7580ec7b1edf0c0cb8958a3071778cb0af908f5269d45c7516fa388e5f856e37f5b2d3c6110974cbe languageName: node linkType: hard From c092655f11755ee96eeaac0a7c7703e8ae25c409 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 01:07:27 +0000 Subject: [PATCH 392/417] fix(deps): update dependency json-schema-library to v7.4.6 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index cb756d1903..e8f7404ac6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27340,15 +27340,15 @@ __metadata: linkType: hard "json-schema-library@npm:^7.3.9": - version: 7.4.5 - resolution: "json-schema-library@npm:7.4.5" + version: 7.4.6 + resolution: "json-schema-library@npm:7.4.6" dependencies: "@sagold/json-pointer": ^5.0.0 "@sagold/json-query": ^6.0.0 deepmerge: ^4.2.2 fast-deep-equal: ^3.1.3 valid-url: ^1.0.9 - checksum: 3e7a070ab81dca119ae259c71eec01f81a9287573c5e47de366d1ee48cf85c694fc5402a7c090947e3367cc9118bdbb34d1ce131135077f9f83b7387f6a0471c + checksum: 4639464c3c25cc6ca04b1aea081c97426598f2477bdd20e4df57e39408bcf2de7a5f54f3e108c497b3e63f41904a251fbb5444451cf7a60fd83020941c55cdda languageName: node linkType: hard From aa632d2e58f1fee4f44c23ae49d4e217fcd7bfdb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 02:03:56 +0000 Subject: [PATCH 393/417] fix(deps): update dependency raw-body to v2.5.2 Signed-off-by: Renovate Bot --- yarn.lock | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index f08867b72d..cb89df95a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33128,7 +33128,7 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.1, raw-body@npm:^2.4.1": +"raw-body@npm:2.5.1": version: 2.5.1 resolution: "raw-body@npm:2.5.1" dependencies: @@ -33140,6 +33140,18 @@ __metadata: languageName: node linkType: hard +"raw-body@npm:^2.4.1": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + checksum: ba1583c8d8a48e8fbb7a873fdbb2df66ea4ff83775421bfe21ee120140949ab048200668c47d9ae3880012f6e217052690628cf679ddfbd82c9fc9358d574676 + languageName: node + linkType: hard + "rc-progress@npm:3.4.1": version: 3.4.1 resolution: "rc-progress@npm:3.4.1" From 2689ea7d9e01f80e83f55a463a82aab54b6d1a18 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 02:35:57 +0000 Subject: [PATCH 394/417] fix(deps): update aws-sdk-js-v3 monorepo to v3.276.0 Signed-off-by: Renovate Bot --- yarn.lock | 76 +++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/yarn.lock b/yarn.lock index b6b73ed78d..544b7beec4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -402,13 +402,13 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/client-cognito-identity@npm:3.272.0": - version: 3.272.0 - resolution: "@aws-sdk/client-cognito-identity@npm:3.272.0" +"@aws-sdk/client-cognito-identity@npm:3.276.0": + version: 3.276.0 + resolution: "@aws-sdk/client-cognito-identity@npm:3.276.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.272.0 + "@aws-sdk/client-sts": 3.276.0 "@aws-sdk/config-resolver": 3.272.0 "@aws-sdk/credential-provider-node": 3.272.0 "@aws-sdk/fetch-http-handler": 3.272.0 @@ -441,18 +441,18 @@ __metadata: "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: fd17c705b2de99fd1570239b62032525380b5e17799fc15f720196a488889fa10bbccd01952d5694ca8c20249d8a808de86de07d5a1b0d21486964a70d9b6d4d + checksum: ff79c1c727d956e03510307b001c24534d522b327871b2b0a1d39120e6d6717e17d7b9c2b7a6d28c3e5c3f41cd8ff28e5150ddd1fda9bff0c239fdfef0a78e00 languageName: node linkType: hard "@aws-sdk/client-s3@npm:^3.208.0": - version: 3.272.0 - resolution: "@aws-sdk/client-s3@npm:3.272.0" + version: 3.276.0 + resolution: "@aws-sdk/client-s3@npm:3.276.0" dependencies: "@aws-crypto/sha1-browser": 3.0.0 "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.272.0 + "@aws-sdk/client-sts": 3.276.0 "@aws-sdk/config-resolver": 3.272.0 "@aws-sdk/credential-provider-node": 3.272.0 "@aws-sdk/eventstream-serde-browser": 3.272.0 @@ -501,19 +501,19 @@ __metadata: "@aws-sdk/util-utf8": 3.254.0 "@aws-sdk/util-waiter": 3.272.0 "@aws-sdk/xml-builder": 3.201.0 - fast-xml-parser: 4.0.11 + fast-xml-parser: 4.1.2 tslib: ^2.3.1 - checksum: 34b9c3515a01b75b170c5942fbfe2ac860efae5856dfeb831691a46f086f21a0d0f36fb05e7f8fe3bc4b84f476abd16ea6cd734592b6fb7a2d86aaaad54c4457 + checksum: f7f475b92c0cff800536fb910bb6ffefcee6e650208f1791ea64c95bcbb6c63ef7a55e3f72af44e2e730a53865857ac4b974f00cb7da1e369d742cc95e33f02a languageName: node linkType: hard "@aws-sdk/client-sqs@npm:^3.208.0": - version: 3.272.0 - resolution: "@aws-sdk/client-sqs@npm:3.272.0" + version: 3.276.0 + resolution: "@aws-sdk/client-sqs@npm:3.276.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.272.0 + "@aws-sdk/client-sts": 3.276.0 "@aws-sdk/config-resolver": 3.272.0 "@aws-sdk/credential-provider-node": 3.272.0 "@aws-sdk/fetch-http-handler": 3.272.0 @@ -547,9 +547,9 @@ __metadata: "@aws-sdk/util-user-agent-browser": 3.272.0 "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 - fast-xml-parser: 4.0.11 + fast-xml-parser: 4.1.2 tslib: ^2.3.1 - checksum: 7188f5b769b98710624bf389475f5eb345fc20fb7078dc9c425c65803aa9006258ba32467ec71dd082832c3af0388ef6fa59aabb76b736eb97fe2f937082b86b + checksum: 88139fde34fa6348e841de13fce5e68b2dfb735c5358c959f9956a8c918048bde8b1ff701e8e701807af5f67f6df129056986b62a7e07096cc7097f3491d36b8 languageName: node linkType: hard @@ -633,9 +633,9 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/client-sts@npm:3.272.0, @aws-sdk/client-sts@npm:^3.208.0": - version: 3.272.0 - resolution: "@aws-sdk/client-sts@npm:3.272.0" +"@aws-sdk/client-sts@npm:3.276.0, @aws-sdk/client-sts@npm:^3.208.0": + version: 3.276.0 + resolution: "@aws-sdk/client-sts@npm:3.276.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 @@ -671,9 +671,9 @@ __metadata: "@aws-sdk/util-user-agent-browser": 3.272.0 "@aws-sdk/util-user-agent-node": 3.272.0 "@aws-sdk/util-utf8": 3.254.0 - fast-xml-parser: 4.0.11 + fast-xml-parser: 4.1.2 tslib: ^2.3.1 - checksum: 2e3083803a4d64de3148ef49b6dccb1a54d6766a8c60a2002cff32f005159d69d8323e50b7cb6055cb0bd595b8e8f2bc8ccd839ee9ca17c5db47fc6b63b10269 + checksum: 3250322448500789588d24b6fac295b551ab4c1661ab9aa93f173e63b4673260bb2e551c079d811da752115e583b76f5c7ffb16d94b3c66275e75e52a93f35f3 languageName: node linkType: hard @@ -690,15 +690,15 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/credential-provider-cognito-identity@npm:3.272.0": - version: 3.272.0 - resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.272.0" +"@aws-sdk/credential-provider-cognito-identity@npm:3.276.0": + version: 3.276.0 + resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.276.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.272.0 + "@aws-sdk/client-cognito-identity": 3.276.0 "@aws-sdk/property-provider": 3.272.0 "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: ba19883f08b8c4625d53a9c243eb8a831f51d7764157d86fc9a0343cd02c5fbd41923a21b5579c718c3b490a97eacc83fe398f5f920dcbd3ce41a3326959b652 + checksum: 2d255475f08beeccd000745b2f2c46553559fd6fe15c0ea9960956655535fb927df9ec3431cf743b80f9a460d033ede7e1c47e91aff44956559a70c5f43f7bab languageName: node linkType: hard @@ -799,13 +799,13 @@ __metadata: linkType: hard "@aws-sdk/credential-providers@npm:^3.208.0": - version: 3.272.0 - resolution: "@aws-sdk/credential-providers@npm:3.272.0" + version: 3.276.0 + resolution: "@aws-sdk/credential-providers@npm:3.276.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.272.0 + "@aws-sdk/client-cognito-identity": 3.276.0 "@aws-sdk/client-sso": 3.272.0 - "@aws-sdk/client-sts": 3.272.0 - "@aws-sdk/credential-provider-cognito-identity": 3.272.0 + "@aws-sdk/client-sts": 3.276.0 + "@aws-sdk/credential-provider-cognito-identity": 3.276.0 "@aws-sdk/credential-provider-env": 3.272.0 "@aws-sdk/credential-provider-imds": 3.272.0 "@aws-sdk/credential-provider-ini": 3.272.0 @@ -817,7 +817,7 @@ __metadata: "@aws-sdk/shared-ini-file-loader": 3.272.0 "@aws-sdk/types": 3.272.0 tslib: ^2.3.1 - checksum: ce311afb81267bc984a9dabffb3df1689cd63c8ed75010163aced4855bf96399a225ae594b494cfcfbb970e9bfe0461576d82a5695065d9e4ca0c82755edd52b + checksum: 825fb0feda57ef98cc11ab3febc2a337161193dfa24bcc31ad2b47ecb4af564b3b5a5a0d9c17fd1a3ec118321d21fc515948980ba50c323e21ed79905c13dfe4 languageName: node linkType: hard @@ -957,8 +957,8 @@ __metadata: linkType: hard "@aws-sdk/lib-storage@npm:^3.208.0": - version: 3.272.0 - resolution: "@aws-sdk/lib-storage@npm:3.272.0" + version: 3.276.0 + resolution: "@aws-sdk/lib-storage@npm:3.276.0" dependencies: "@aws-sdk/middleware-endpoint": 3.272.0 "@aws-sdk/smithy-client": 3.272.0 @@ -969,7 +969,7 @@ __metadata: peerDependencies: "@aws-sdk/abort-controller": ^3.0.0 "@aws-sdk/client-s3": ^3.0.0 - checksum: 7c4f25fec63d60ade365062fbd1cf9807593268f3b0354ea22b5e06619e443f5421da920255875455d84fc19900d5472fa5e92a5bd46c1f3be148da67afa58f8 + checksum: 1e34d3569c8cf2f7c42efdd7966a9faea64bf49f4fe1fcb0ff30ed86670a5ba2361bb14279e7dc1bc110a1ff9e5cec3551bc8a56b3c9c4d19f98ff4842a8de19 languageName: node linkType: hard @@ -23117,14 +23117,14 @@ __metadata: languageName: node linkType: hard -"fast-xml-parser@npm:4.0.11": - version: 4.0.11 - resolution: "fast-xml-parser@npm:4.0.11" +"fast-xml-parser@npm:4.1.2": + version: 4.1.2 + resolution: "fast-xml-parser@npm:4.1.2" dependencies: strnum: ^1.0.5 bin: fxparser: src/cli/cli.js - checksum: d8a08e4d5597e0fc00a86735195872eeb03008913e298830941516f3766e16ee555e2d431acc92e1dda887938edc445252ec5b59494aab60a8389888bd13719c + checksum: 6a7d1b17057f8470e70603eddfa75f990625735d068d57ece861d0154ad8d27fda63c2831d07e1ecd7e68e993738b2448925cb9277d8c0ed68009623bbcd63c6 languageName: node linkType: hard From e506d512159176f78ea9fd930710e24f2c555d93 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 03:20:27 +0000 Subject: [PATCH 395/417] fix(deps): update dependency sass to v1.58.3 Signed-off-by: Renovate Bot --- microsite-next/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 3d3870d142..f9e2f6cf22 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -9305,15 +9305,15 @@ __metadata: linkType: hard "sass@npm:^1.57.1": - version: 1.57.1 - resolution: "sass@npm:1.57.1" + version: 1.58.3 + resolution: "sass@npm:1.58.3" dependencies: chokidar: ">=3.0.0 <4.0.0" immutable: ^4.0.0 source-map-js: ">=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 734a08781bcbe0e8defb2d54864e7012014ed3e68ba5fcb766189b002929019fc37b2f83a18d4be0b5f69ad77317c92396ce6112447ab47a194ed600ae1afb27 + checksum: 35a2b98c037ef80fdc93c9b0be846e6ccc7d75596351a37ee79c397e66666d0a754c52c4696e746c0aff32327471e185343ca349e998a58340411adc9d0489a5 languageName: node linkType: hard From 86cece2c1fbe04dd5164ad33d10e28b28db37d0d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 09:28:58 +0000 Subject: [PATCH 396/417] chore(deps): update dependency @types/passport-microsoft to v1 Signed-off-by: Renovate Bot --- .changeset/renovate-488b7e7.md | 5 +++++ plugins/auth-backend/package.json | 2 +- yarn.lock | 10 +++++----- 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .changeset/renovate-488b7e7.md diff --git a/.changeset/renovate-488b7e7.md b/.changeset/renovate-488b7e7.md new file mode 100644 index 0000000000..35940f474b --- /dev/null +++ b/.changeset/renovate-488b7e7.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Updated dependency `@types/passport-microsoft` to `^1.0.0`. diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 523568cc2c..92f3264503 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -86,7 +86,7 @@ "@types/passport-auth0": "^1.0.5", "@types/passport-github2": "^1.2.4", "@types/passport-google-oauth20": "^2.0.3", - "@types/passport-microsoft": "^0.0.0", + "@types/passport-microsoft": "^1.0.0", "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", diff --git a/yarn.lock b/yarn.lock index 4731f18a66..1b4b3a9aeb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4564,7 +4564,7 @@ __metadata: "@types/passport-auth0": ^1.0.5 "@types/passport-github2": ^1.2.4 "@types/passport-google-oauth20": ^2.0.3 - "@types/passport-microsoft": ^0.0.0 + "@types/passport-microsoft": ^1.0.0 "@types/passport-saml": ^1.1.3 "@types/passport-strategy": ^0.2.35 "@types/xml2js": ^0.4.7 @@ -15325,12 +15325,12 @@ __metadata: languageName: node linkType: hard -"@types/passport-microsoft@npm:^0.0.0": - version: 0.0.0 - resolution: "@types/passport-microsoft@npm:0.0.0" +"@types/passport-microsoft@npm:^1.0.0": + version: 1.0.0 + resolution: "@types/passport-microsoft@npm:1.0.0" dependencies: "@types/passport-oauth2": "*" - checksum: fee27b238975ba86982616d713247bd9f8ab4e325270dd42841c140710ece3f32655b2536fcbffe0166f25b51e1b25316006718f037b5a88018406c64351ae27 + checksum: d7c8b439b18cddcf707ea0c575748ecb344b6fb3c78a847aaad83246abf081c8b485efa86a3788cd5f49f4ca84a1444d813697a433fab9d04f35fb67d628cb23 languageName: node linkType: hard From 4b4998466b45facdf60f0d7c8efb346ecac78d87 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 10:31:09 +0000 Subject: [PATCH 397/417] chore(deps): update dependency del to v7 Signed-off-by: Renovate Bot --- .changeset/renovate-3672e5e.md | 5 ++ packages/cli/package.json | 2 +- yarn.lock | 112 +++++++++++++++++++++++++-------- 3 files changed, 93 insertions(+), 26 deletions(-) create mode 100644 .changeset/renovate-3672e5e.md diff --git a/.changeset/renovate-3672e5e.md b/.changeset/renovate-3672e5e.md new file mode 100644 index 0000000000..c94eec2245 --- /dev/null +++ b/.changeset/renovate-3672e5e.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `del` to `^7.0.0`. diff --git a/packages/cli/package.json b/packages/cli/package.json index 64311a767d..a640761c6a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -155,7 +155,7 @@ "@types/tar": "^6.1.1", "@types/terser-webpack-plugin": "^5.0.4", "@types/yarnpkg__lockfile": "^1.1.4", - "del": "^6.0.0", + "del": "^7.0.0", "mock-fs": "^5.1.0", "msw": "^0.49.0", "nodemon": "^2.0.2", diff --git a/yarn.lock b/yarn.lock index 58e4f38111..c11c002280 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3723,7 +3723,7 @@ __metadata: commander: ^9.1.0 cross-spawn: ^7.0.3 css-loader: ^6.5.1 - del: ^6.0.0 + del: ^7.0.0 diff: ^5.0.0 esbuild: ^0.17.0 esbuild-loader: ^2.18.0 @@ -16630,6 +16630,16 @@ __metadata: languageName: node linkType: hard +"aggregate-error@npm:^4.0.0": + version: 4.0.1 + resolution: "aggregate-error@npm:4.0.1" + dependencies: + clean-stack: ^4.0.0 + indent-string: ^5.0.0 + checksum: bb3ffdfd13447800fff237c2cba752c59868ee669104bb995dfbbe0b8320e967d679e683dabb640feb32e4882d60258165cde0baafc4cd467cc7d275a13ad6b5 + languageName: node + linkType: hard + "ajv-formats@npm:^2.1.1": version: 2.1.1 resolution: "ajv-formats@npm:2.1.1" @@ -18808,6 +18818,15 @@ __metadata: languageName: node linkType: hard +"clean-stack@npm:^4.0.0": + version: 4.2.0 + resolution: "clean-stack@npm:4.2.0" + dependencies: + escape-string-regexp: 5.0.0 + checksum: 373f656a31face5c615c0839213b9b542a0a48057abfb1df66900eab4dc2a5c6097628e4a0b5aa559cdfc4e66f8a14ea47be9681773165a44470ef5fb8ccc172 + languageName: node + linkType: hard + "cli-cursor@npm:^3.1.0": version: 3.1.0 resolution: "cli-cursor@npm:3.1.0" @@ -20752,19 +20771,19 @@ __metadata: languageName: node linkType: hard -"del@npm:^6.0.0": - version: 6.1.1 - resolution: "del@npm:6.1.1" +"del@npm:^7.0.0": + version: 7.0.0 + resolution: "del@npm:7.0.0" dependencies: - globby: ^11.0.1 - graceful-fs: ^4.2.4 - is-glob: ^4.0.1 - is-path-cwd: ^2.2.0 - is-path-inside: ^3.0.2 - p-map: ^4.0.0 + globby: ^13.1.2 + graceful-fs: ^4.2.10 + is-glob: ^4.0.3 + is-path-cwd: ^3.0.0 + is-path-inside: ^4.0.0 + p-map: ^5.5.0 rimraf: ^3.0.2 - slash: ^3.0.0 - checksum: 563288b73b8b19a7261c47fd21a330eeab6e2acd7c6208c49790dfd369127120dd7836cdf0c1eca216b77c94782a81507eac6b4734252d3bef2795cb366996b6 + slash: ^4.0.0 + checksum: 33e5077f18b5dfbe81971d1f8a2cd8bf676dd5ede491bab85ec17a4a1d59001bd3ec47fd38e9a4ae01a3c98c07b98c7b3dc56190b86d88926798802d7858d827 languageName: node linkType: hard @@ -22008,6 +22027,13 @@ __metadata: languageName: node linkType: hard +"escape-string-regexp@npm:5.0.0, escape-string-regexp@npm:^5.0.0": + version: 5.0.0 + resolution: "escape-string-regexp@npm:5.0.0" + checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e + languageName: node + linkType: hard + "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -22029,13 +22055,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^5.0.0": - version: 5.0.0 - resolution: "escape-string-regexp@npm:5.0.0" - checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e - languageName: node - linkType: hard - "escodegen@npm:^1.13.0": version: 1.14.3 resolution: "escodegen@npm:1.14.3" @@ -23039,7 +23058,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9": +"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9": version: 3.2.12 resolution: "fast-glob@npm:3.2.12" dependencies: @@ -24200,6 +24219,19 @@ __metadata: languageName: node linkType: hard +"globby@npm:^13.1.2": + version: 13.1.3 + resolution: "globby@npm:13.1.3" + dependencies: + dir-glob: ^3.0.1 + fast-glob: ^3.2.11 + ignore: ^5.2.0 + merge2: ^1.4.1 + slash: ^4.0.0 + checksum: 93f06e02002cdf368f7e3d55bd59e7b00784c7cc8fe92c7ee5082cc7171ff6109fda45e1c97a80bb48bc811dedaf7843c7c9186f5f84bde4883ab630e13c43df + languageName: node + linkType: hard + "good-listener@npm:^1.2.2": version: 1.2.2 resolution: "good-listener@npm:1.2.2" @@ -24298,7 +24330,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.1.9, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.1.9, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.10 resolution: "graceful-fs@npm:4.2.10" checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da @@ -25311,6 +25343,13 @@ __metadata: languageName: node linkType: hard +"indent-string@npm:^5.0.0": + version: 5.0.0 + resolution: "indent-string@npm:5.0.0" + checksum: e466c27b6373440e6d84fbc19e750219ce25865cb82d578e41a6053d727e5520dc5725217d6eb1cc76005a1bb1696a0f106d84ce7ebda3033b963a38583fb3b3 + languageName: node + linkType: hard + "infer-owner@npm:^1.0.4": version: 1.0.4 resolution: "infer-owner@npm:1.0.4" @@ -25878,10 +25917,10 @@ __metadata: languageName: node linkType: hard -"is-path-cwd@npm:^2.2.0": - version: 2.2.0 - resolution: "is-path-cwd@npm:2.2.0" - checksum: 46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048 +"is-path-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "is-path-cwd@npm:3.0.0" + checksum: bc34d13b6a03dfca4a3ab6a8a5ba78ae4b24f4f1db4b2b031d2760c60d0913bd16a4b980dcb4e590adfc906649d5f5132684079a3972bd219da49deebb9adea8 languageName: node linkType: hard @@ -25892,6 +25931,13 @@ __metadata: languageName: node linkType: hard +"is-path-inside@npm:^4.0.0": + version: 4.0.0 + resolution: "is-path-inside@npm:4.0.0" + checksum: 8810fa11c58e6360b82c3e0d6cd7d9c7d0392d3ac9eb10f980b81f9839f40ac6d1d6d6f05d069db0d227759801228f0b072e1b6c343e4469b065ab5fe0b68fe5 + languageName: node + linkType: hard + "is-plain-obj@npm:^1.1.0": version: 1.1.0 resolution: "is-plain-obj@npm:1.1.0" @@ -31147,6 +31193,15 @@ __metadata: languageName: node linkType: hard +"p-map@npm:^5.5.0": + version: 5.5.0 + resolution: "p-map@npm:5.5.0" + dependencies: + aggregate-error: ^4.0.0 + checksum: 065cb6fca6b78afbd070dd9224ff160dc23eea96e57863c09a0c8ea7ce921043f76854be7ee0abc295cff1ac9adcf700e79a1fbe3b80b625081087be58e7effb + languageName: node + linkType: hard + "p-queue@npm:^6.6.2": version: 6.6.2 resolution: "p-queue@npm:6.6.2" @@ -35471,6 +35526,13 @@ __metadata: languageName: node linkType: hard +"slash@npm:^4.0.0": + version: 4.0.0 + resolution: "slash@npm:4.0.0" + checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d + languageName: node + linkType: hard + "slice-ansi@npm:^3.0.0": version: 3.0.0 resolution: "slice-ansi@npm:3.0.0" From 6ca71a71100048a429ddf023f369c9bbe59ac41b Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 22 Feb 2023 11:36:56 +0100 Subject: [PATCH 398/417] bump microsite build memory limit Signed-off-by: Johan Haals --- .github/workflows/deploy_microsite.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 1b0f7753bd..ec7124ed35 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -14,7 +14,7 @@ jobs: env: CI: true - NODE_OPTIONS: --max-old-space-size=4096 + NODE_OPTIONS: --max-old-space-size=7168 DOCUSAURUS_SSR_CONCURRENCY: 5 steps: From a6913174e1c13dd9d79c109468b88f1431a29bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20K=C3=B6hler?= <9337156+axdotl@users.noreply.github.com> Date: Wed, 22 Feb 2023 13:23:13 +0100 Subject: [PATCH 399/417] Update links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Axel Köhler <9337156+axdotl@users.noreply.github.com> --- microsite/data/plugins/backstage-kubernetes.yaml | 2 +- microsite/data/plugins/backstage-search-platform.yaml | 2 +- microsite/data/plugins/backstage-software-catalog.yaml | 2 +- microsite/data/plugins/backstage-software-templates.yaml | 2 +- microsite/data/plugins/backstage-techdocs.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/microsite/data/plugins/backstage-kubernetes.yaml b/microsite/data/plugins/backstage-kubernetes.yaml index a070ea99b0..603211eb21 100644 --- a/microsite/data/plugins/backstage-kubernetes.yaml +++ b/microsite/data/plugins/backstage-kubernetes.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Core Feature description: Monitor all your service's deployments at a glance, even across clusters. -documentation: https://backstage.io/docs/features/kubernetes/overview +documentation: https://backstage.io/docs/features/kubernetes/ iconUrl: img/backstage-k8s.svg npmPackageName: '@backstage/plugin-kubernetes' order: 4 diff --git a/microsite/data/plugins/backstage-search-platform.yaml b/microsite/data/plugins/backstage-search-platform.yaml index 33faaba310..1488b8a283 100644 --- a/microsite/data/plugins/backstage-search-platform.yaml +++ b/microsite/data/plugins/backstage-search-platform.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Core Feature description: A composable and extensible search platform built to fit your organization’s needs and find information quickly. -documentation: https://backstage.io/docs/features/search/search-overview +documentation: https://backstage.io/docs/features/search/ iconUrl: img/backstage-search-platform.svg npmPackageName: '@backstage/plugin-search' order: 5 diff --git a/microsite/data/plugins/backstage-software-catalog.yaml b/microsite/data/plugins/backstage-software-catalog.yaml index e633e17e8e..13dac42e0c 100644 --- a/microsite/data/plugins/backstage-software-catalog.yaml +++ b/microsite/data/plugins/backstage-software-catalog.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Core Feature description: Manage all your services and software components, all in one place. -documentation: https://backstage.io/docs/features/software-catalog/software-catalog-overview +documentation: https://backstage.io/docs/features/software-catalog/ iconUrl: img/backstage-software-catalog.svg npmPackageName: '@backstage/plugin-catalog' order: 1 diff --git a/microsite/data/plugins/backstage-software-templates.yaml b/microsite/data/plugins/backstage-software-templates.yaml index f111ee30ce..492f26f97a 100644 --- a/microsite/data/plugins/backstage-software-templates.yaml +++ b/microsite/data/plugins/backstage-software-templates.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Core Feature description: Create new software components in just a few steps, with your standards built-in (Scaffolder). -documentation: https://backstage.io/docs/features/software-templates/software-templates-index +documentation: https://backstage.io/docs/features/software-templates/ iconUrl: img/backstage-software-templates.svg npmPackageName: '@backstage/plugin-scaffolder' order: 2 diff --git a/microsite/data/plugins/backstage-techdocs.yaml b/microsite/data/plugins/backstage-techdocs.yaml index 8d89ac5060..f49fe98811 100644 --- a/microsite/data/plugins/backstage-techdocs.yaml +++ b/microsite/data/plugins/backstage-techdocs.yaml @@ -4,7 +4,7 @@ author: Spotify authorUrl: https://github.com/spotify category: Core Feature description: A docs-like-code solution to technical documentation. Write your docs right alongside your code. -documentation: https://backstage.io/docs/features/techdocs/techdocs-overview +documentation: https://backstage.io/docs/features/techdocs/ iconUrl: img/backstage-techdocs.svg npmPackageName: '@backstage/plugin-techdocs' order: 3 From 41dae83d55de0c895dbf4270a35a41798b9ca856 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 22 Feb 2023 13:33:32 +0100 Subject: [PATCH 400/417] microsite2: Update releases to latest release Signed-off-by: Johan Haals --- microsite-next/docusaurus.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index 4b44604ab5..73171e65ea 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -131,7 +131,7 @@ module.exports = { position: 'left', }, { - to: 'docs/releases/v1.8.0', + to: 'docs/releases/v1.11.0', label: 'Releases', position: 'left', }, From 52b0022dab774d17d3d87f97cc277d99e6f8e66f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 12:55:28 +0000 Subject: [PATCH 401/417] chore(deps): update dependency msw to v1 Signed-off-by: Renovate Bot --- .changeset/renovate-fb85ae7.md | 125 ++++++++ packages/backend-common/package.json | 2 +- packages/backend-test-utils/package.json | 2 +- packages/catalog-client/package.json | 2 +- packages/cli/package.json | 2 +- packages/config-loader/package.json | 2 +- packages/core-app-api/package.json | 2 +- packages/core-components/package.json | 2 +- packages/core-plugin-api/package.json | 2 +- packages/integration-react/package.json | 2 +- packages/integration/package.json | 2 +- packages/release-manifests/package.json | 2 +- packages/test-utils/package.json | 2 +- plugins/adr-backend/package.json | 2 +- plugins/adr/package.json | 2 +- plugins/airbrake-backend/package.json | 2 +- plugins/airbrake/package.json | 2 +- plugins/allure/package.json | 2 +- plugins/analytics-module-ga/package.json | 2 +- plugins/apache-airflow/package.json | 2 +- plugins/api-docs/package.json | 2 +- plugins/apollo-explorer/package.json | 2 +- plugins/app-backend/package.json | 2 +- plugins/auth-backend/package.json | 2 +- plugins/auth-node/package.json | 2 +- plugins/azure-devops-backend/package.json | 2 +- plugins/azure-devops/package.json | 2 +- plugins/azure-sites-backend/package.json | 2 +- plugins/azure-sites/package.json | 2 +- plugins/badges/package.json | 2 +- plugins/bitbucket-cloud-common/package.json | 2 +- plugins/bitrise/package.json | 2 +- .../catalog-backend-module-azure/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- plugins/catalog-backend/package.json | 2 +- plugins/catalog-graphql/package.json | 2 +- plugins/catalog-import/package.json | 2 +- plugins/circleci/package.json | 2 +- plugins/cloudbuild/package.json | 2 +- plugins/code-climate/package.json | 2 +- plugins/code-coverage-backend/package.json | 2 +- plugins/code-coverage/package.json | 2 +- plugins/codescene/package.json | 2 +- plugins/config-schema/package.json | 2 +- plugins/cost-insights/package.json | 2 +- plugins/dynatrace/package.json | 2 +- plugins/entity-feedback-backend/package.json | 2 +- plugins/entity-feedback/package.json | 2 +- plugins/entity-validation/package.json | 2 +- .../example-todo-list-backend/package.json | 2 +- plugins/example-todo-list-common/package.json | 2 +- plugins/example-todo-list/package.json | 2 +- plugins/explore-backend/package.json | 2 +- plugins/explore-react/package.json | 2 +- plugins/explore/package.json | 2 +- plugins/firehydrant/package.json | 2 +- plugins/fossa/package.json | 2 +- plugins/gcalendar/package.json | 2 +- plugins/gcp-projects/package.json | 2 +- plugins/git-release-manager/package.json | 2 +- plugins/github-actions/package.json | 2 +- plugins/github-deployments/package.json | 2 +- plugins/github-issues/package.json | 2 +- .../github-pull-requests-board/package.json | 2 +- plugins/gitops-profiles/package.json | 2 +- plugins/gocd/package.json | 2 +- plugins/graphiql/package.json | 2 +- plugins/graphql-backend/package.json | 2 +- plugins/graphql-voyager/package.json | 2 +- plugins/home/package.json | 2 +- plugins/ilert/package.json | 2 +- plugins/jenkins-backend/package.json | 2 +- plugins/jenkins/package.json | 2 +- plugins/kafka/package.json | 2 +- plugins/kubernetes-backend/package.json | 2 +- plugins/kubernetes/package.json | 2 +- plugins/lighthouse/package.json | 2 +- plugins/linguist-backend/package.json | 2 +- plugins/linguist/package.json | 2 +- plugins/microsoft-calendar/package.json | 2 +- plugins/newrelic/package.json | 2 +- plugins/octopus-deploy/package.json | 2 +- plugins/org-react/package.json | 2 +- plugins/org/package.json | 2 +- plugins/pagerduty/package.json | 2 +- plugins/periskop-backend/package.json | 2 +- plugins/periskop/package.json | 2 +- plugins/permission-backend/package.json | 2 +- plugins/permission-common/package.json | 2 +- plugins/permission-node/package.json | 2 +- plugins/playlist-backend/package.json | 2 +- plugins/playlist/package.json | 2 +- plugins/proxy-backend/package.json | 2 +- plugins/rollbar-backend/package.json | 2 +- plugins/rollbar/package.json | 2 +- .../package.json | 2 +- plugins/scaffolder-backend/package.json | 2 +- plugins/scaffolder/package.json | 2 +- plugins/search/package.json | 2 +- plugins/sentry/package.json | 2 +- plugins/shortcuts/package.json | 2 +- plugins/sonarqube-backend/package.json | 2 +- plugins/sonarqube/package.json | 2 +- plugins/splunk-on-call/package.json | 2 +- plugins/stack-overflow-backend/package.json | 2 +- plugins/stack-overflow/package.json | 2 +- plugins/stackstorm/package.json | 2 +- plugins/tech-insights/package.json | 2 +- plugins/tech-radar/package.json | 2 +- .../techdocs-addons-test-utils/package.json | 2 +- plugins/techdocs-backend/package.json | 2 +- .../package.json | 2 +- plugins/techdocs/package.json | 2 +- plugins/todo-backend/package.json | 2 +- plugins/todo/package.json | 2 +- plugins/user-settings/package.json | 2 +- plugins/vault-backend/package.json | 2 +- plugins/vault/package.json | 2 +- plugins/xcmetrics/package.json | 2 +- yarn.lock | 284 ++++++++---------- 126 files changed, 374 insertions(+), 283 deletions(-) create mode 100644 .changeset/renovate-fb85ae7.md diff --git a/.changeset/renovate-fb85ae7.md b/.changeset/renovate-fb85ae7.md new file mode 100644 index 0000000000..920469850c --- /dev/null +++ b/.changeset/renovate-fb85ae7.md @@ -0,0 +1,125 @@ +--- +'@backstage/backend-common': patch +'@backstage/backend-test-utils': patch +'@backstage/catalog-client': patch +'@backstage/cli': patch +'@backstage/config-loader': patch +'@backstage/core-app-api': patch +'@backstage/core-components': patch +'@backstage/core-plugin-api': patch +'@backstage/integration-react': patch +'@backstage/integration': patch +'@backstage/release-manifests': patch +'@backstage/test-utils': patch +'@backstage/plugin-adr-backend': patch +'@backstage/plugin-adr': patch +'@backstage/plugin-airbrake-backend': patch +'@backstage/plugin-airbrake': patch +'@backstage/plugin-allure': patch +'@backstage/plugin-analytics-module-ga': patch +'@backstage/plugin-apache-airflow': patch +'@backstage/plugin-api-docs': patch +'@backstage/plugin-apollo-explorer': patch +'@backstage/plugin-app-backend': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-auth-node': patch +'@backstage/plugin-azure-devops-backend': patch +'@backstage/plugin-azure-devops': patch +'@backstage/plugin-azure-sites-backend': patch +'@backstage/plugin-azure-sites': patch +'@backstage/plugin-badges': patch +'@backstage/plugin-bitbucket-cloud-common': patch +'@backstage/plugin-bitrise': patch +'@backstage/plugin-catalog-backend-module-azure': patch +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch +'@backstage/plugin-catalog-backend-module-bitbucket-server': patch +'@backstage/plugin-catalog-backend-module-bitbucket': patch +'@backstage/plugin-catalog-backend-module-gerrit': patch +'@backstage/plugin-catalog-backend-module-github': patch +'@backstage/plugin-catalog-backend-module-gitlab': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog-graphql': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-circleci': patch +'@backstage/plugin-cloudbuild': patch +'@backstage/plugin-code-climate': patch +'@backstage/plugin-code-coverage-backend': patch +'@backstage/plugin-code-coverage': patch +'@backstage/plugin-codescene': patch +'@backstage/plugin-config-schema': patch +'@backstage/plugin-cost-insights': patch +'@backstage/plugin-dynatrace': patch +'@backstage/plugin-entity-feedback-backend': patch +'@backstage/plugin-entity-feedback': patch +'@backstage/plugin-entity-validation': patch +'@backstage/plugin-explore-backend': patch +'@backstage/plugin-explore-react': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-firehydrant': patch +'@backstage/plugin-fossa': patch +'@backstage/plugin-gcalendar': patch +'@backstage/plugin-gcp-projects': patch +'@backstage/plugin-git-release-manager': patch +'@backstage/plugin-github-actions': patch +'@backstage/plugin-github-deployments': patch +'@backstage/plugin-github-issues': patch +'@backstage/plugin-github-pull-requests-board': patch +'@backstage/plugin-gitops-profiles': patch +'@backstage/plugin-gocd': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-graphql-backend': patch +'@backstage/plugin-graphql-voyager': patch +'@backstage/plugin-home': patch +'@backstage/plugin-ilert': patch +'@backstage/plugin-jenkins-backend': patch +'@backstage/plugin-jenkins': patch +'@backstage/plugin-kafka': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-lighthouse': patch +'@backstage/plugin-linguist-backend': patch +'@backstage/plugin-linguist': patch +'@backstage/plugin-microsoft-calendar': patch +'@backstage/plugin-newrelic': patch +'@backstage/plugin-octopus-deploy': patch +'@backstage/plugin-org-react': patch +'@backstage/plugin-org': patch +'@backstage/plugin-pagerduty': patch +'@backstage/plugin-periskop-backend': patch +'@backstage/plugin-periskop': patch +'@backstage/plugin-permission-backend': patch +'@backstage/plugin-permission-common': patch +'@backstage/plugin-permission-node': patch +'@backstage/plugin-playlist-backend': patch +'@backstage/plugin-playlist': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-rollbar-backend': patch +'@backstage/plugin-rollbar': patch +'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-search': patch +'@backstage/plugin-sentry': patch +'@backstage/plugin-shortcuts': patch +'@backstage/plugin-sonarqube-backend': patch +'@backstage/plugin-sonarqube': patch +'@backstage/plugin-splunk-on-call': patch +'@backstage/plugin-stack-overflow-backend': patch +'@backstage/plugin-stack-overflow': patch +'@backstage/plugin-stackstorm': patch +'@backstage/plugin-tech-insights': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-techdocs-addons-test-utils': patch +'@backstage/plugin-techdocs-backend': patch +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-todo-backend': patch +'@backstage/plugin-todo': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-vault-backend': patch +'@backstage/plugin-vault': patch +'@backstage/plugin-xcmetrics': patch +--- + +Updated dependency `msw` to `^1.0.0`. diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 4738a1bc97..28c11e39e0 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -132,7 +132,7 @@ "better-sqlite3": "^8.0.0", "http-errors": "^2.0.0", "mock-fs": "^5.1.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "mysql2": "^2.2.5", "recursive-readdir": "^2.2.2", "supertest": "^6.1.3" diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 59b6fd057d..73f0e9762d 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -51,7 +51,7 @@ "better-sqlite3": "^8.0.0", "express": "^4.17.1", "knex": "^2.0.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "mysql2": "^2.2.5", "pg": "^8.3.0", "testcontainers": "^8.1.2", diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 4915bfa636..91e852c3b0 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -38,7 +38,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/packages/cli/package.json b/packages/cli/package.json index a640761c6a..0260a1c59b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -157,7 +157,7 @@ "@types/yarnpkg__lockfile": "^1.1.4", "del": "^7.0.0", "mock-fs": "^5.1.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "nodemon": "^2.0.2", "ts-node": "^10.0.0" }, diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index c78eb632da..657c6630eb 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -56,7 +56,7 @@ "@types/node": "^16.11.26", "@types/yup": "^0.29.13", "mock-fs": "^5.1.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index f9a17bd88c..c43b27009b 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -57,7 +57,7 @@ "@types/node": "^16.11.26", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0", + "msw": "^1.0.0", "react-router-beta": "npm:react-router@6.0.0-beta.0", "react-router-dom-beta": "npm:react-router-dom@6.0.0-beta.0", "react-router-dom-stable": "npm:react-router-dom@^6.3.0", diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 736b7a415b..aa47734d8b 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -98,7 +98,7 @@ "@types/react-window": "^1.8.5", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 561b08f3e5..1da87fa457 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -69,7 +69,7 @@ "@types/prop-types": "^15.7.3", "@types/zen-observable": "^0.8.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index f074245dcb..ab163f9b1a 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -45,7 +45,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/packages/integration/package.json b/packages/integration/package.json index 90f82dae35..3ad53b1e08 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -46,7 +46,7 @@ "@backstage/config-loader": "workspace:^", "@backstage/test-utils": "workspace:^", "@types/luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/packages/release-manifests/package.json b/packages/release-manifests/package.json index 4abeb9dc6a..96c5aec484 100644 --- a/packages/release-manifests/package.json +++ b/packages/release-manifests/package.json @@ -38,7 +38,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@types/node": "^16.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 925f42b49b..ef57be6a57 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -69,7 +69,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/node": "^16.11.26", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 34231c549c..719b3808a7 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -49,7 +49,7 @@ "@backstage/cli": "workspace:^", "@types/marked": "^4.0.0", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/adr/package.json b/plugins/adr/package.json index c5c99c6e24..3910fbdef9 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -54,7 +54,7 @@ "@types/git-url-parse": "^9.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index faa401da7b..6f79200b0e 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -35,7 +35,7 @@ "@backstage/cli": "workspace:^", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 1430fc0546..22d961419c 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -48,7 +48,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 017fe5908c..98296190b7 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -47,7 +47,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 71b71887b4..2cf706b25e 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -45,7 +45,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 42a1177aea..b249948e90 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -43,7 +43,7 @@ "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 49f70c038b..7660e62320 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -65,7 +65,7 @@ "@types/node": "^16.11.26", "@types/swagger-ui-react": "^4.1.1", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 3f6b8202a8..8251dac9b9 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -45,7 +45,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 5f9856d322..203faaa517 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -69,7 +69,7 @@ "@backstage/types": "workspace:^", "@types/supertest": "^2.0.8", "mock-fs": "^5.1.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "node-fetch": "^2.6.7", "supertest": "^6.1.3" }, diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 523568cc2c..fe2748c6eb 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -90,7 +90,7 @@ "@types/passport-saml": "^1.1.3", "@types/passport-strategy": "^0.2.35", "@types/xml2js": "^0.4.7", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 97539fadcb..fcb0ed8e48 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -35,7 +35,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "lodash": "^4.17.21", - "msw": "^0.49.0", + "msw": "^1.0.0", "uuid": "^8.0.0" }, "files": [ diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index e75adc2344..a8baac3673 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index ca01418465..4174675f03 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -56,7 +56,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index 760765303a..50618bb0ad 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -48,7 +48,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index aa2d92ffab..7d37bf287a 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -57,7 +57,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 54de1216d2..a5a610c041 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -54,7 +54,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index d42d00e4f3..da9ebadcca 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -33,7 +33,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@openapitools/openapi-generator-cli": "^2.4.26", - "msw": "^0.49.0", + "msw": "^1.0.0", "ts-morph": "^17.0.0" }, "files": [ diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index cb7eeae705..3366b34d9a 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -51,7 +51,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "@types/recharts": "^1.8.15", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index a327679807..1594e88955 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -65,7 +65,7 @@ "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", "luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "config.d.ts", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 55f5d710f9..470ab9b813 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -65,7 +65,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "config.d.ts", diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 2de59cdc33..d96e7c91f9 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -62,7 +62,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "config.d.ts", diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index d01e1e7d30..4f10b4c567 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -49,7 +49,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index e9c9572b5f..b5482affb1 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -60,7 +60,7 @@ "@backstage/cli": "workspace:^", "@types/fs-extra": "^9.0.1", "luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index b30b211c92..5a528a8e05 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -72,7 +72,7 @@ "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", "luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index d73b6666e5..be78589199 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -66,7 +66,7 @@ "@types/lodash": "^4.14.151", "@types/uuid": "^8.0.0", "luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "config.d.ts", diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 7ccc8f4fd9..29909d4c50 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -68,7 +68,7 @@ "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", "luxon": "^3.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "config.d.ts", diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index c9b3b93857..5d1be38754 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -94,7 +94,7 @@ "@types/uuid": "^8.0.0", "better-sqlite3": "^8.0.0", "luxon": "^3.0.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3", "wait-for-expect": "^3.0.2" }, diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 0a6cff187c..7c4909d1d2 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -53,7 +53,7 @@ "@graphql-codegen/typescript": "^2.4.2", "@graphql-codegen/typescript-resolvers": "^2.4.3", "@graphql-tools/schema": "^9.0.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index e07725bedb..57633f7b22 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -68,7 +68,7 @@ "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 0167f9ff98..b657d07f28 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -62,7 +62,7 @@ "@types/humanize-duration": "^3.25.1", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index d888dc6a7b..7604fdaf63 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -59,7 +59,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index d353b2443f..0f99afff6a 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -49,7 +49,7 @@ "@types/luxon": "^3.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 24309c128e..bb0c7df590 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -42,7 +42,7 @@ "@backstage/cli": "workspace:^", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6", "xml2js": "^0.4.23" }, diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 2dd0041002..3a2de06c7f 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -55,7 +55,7 @@ "@types/node": "^16.11.26", "@types/recharts": "^1.8.15", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index d44f3f3fa6..23af32e94a 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -47,7 +47,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 2c0fb2ae7c..07773496c0 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -49,7 +49,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index c20d42928b..bce00a354f 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -74,7 +74,7 @@ "@types/yup": "^0.29.13", "canvas": "^2.10.2", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index cca4d9254f..ef8c2bb22b 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -50,7 +50,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "express": "^4.18.1", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index c7b5146267..b7951e1db9 100644 --- a/plugins/entity-feedback-backend/package.json +++ b/plugins/entity-feedback-backend/package.json @@ -40,7 +40,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.12", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.2.4" }, "files": [ diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 3602d08c2f..bcf3895d7b 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -55,7 +55,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index a6697d0722..5d509f1eea 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -60,7 +60,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 4dad898939..963bf847ac 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -40,7 +40,7 @@ "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/example-todo-list-common/package.json b/plugins/example-todo-list-common/package.json index c1be8da2f8..3d7a66e012 100644 --- a/plugins/example-todo-list-common/package.json +++ b/plugins/example-todo-list-common/package.json @@ -32,7 +32,7 @@ "@backstage/test-utils": "workspace:^", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 961fe4ef08..4eb7d3357f 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -43,7 +43,7 @@ "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 00b2f18bbc..0a6de1ab85 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.2.4" }, "files": [ diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 3d674c9506..2aa8f1b6fc 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -44,7 +44,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 1a4da26abb..c53f00ff6a 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -64,7 +64,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index a1bd316856..06edc1cd38 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -46,7 +46,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 655aab51ed..5864780dca 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -59,7 +59,7 @@ "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 1121849277..37df64f7f4 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -54,7 +54,7 @@ "@types/node": "^16.11.26", "@types/sanitize-html": "^2.6.2", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index ff8fd9d57e..2a382f97bb 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -55,7 +55,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index b208099a62..63ebb36dfb 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -53,7 +53,7 @@ "@types/node": "^16.11.26", "@types/recharts": "^1.8.15", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index e3bc9a9764..8a51def8c4 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -61,7 +61,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 1cfaafe758..9027c5f23a 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -51,7 +51,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index d3544d2dbe..d891951537 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -51,7 +51,7 @@ "@types/node": "*", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 0500193a8f..e837da56e9 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -58,7 +58,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0", diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index c6798383d6..1f42adc3d9 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -55,7 +55,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 08c4d6991c..4567a6e59b 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -58,7 +58,7 @@ "@types/luxon": "^3.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 1d825744d8..7f1bd12beb 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -58,7 +58,7 @@ "@types/codemirror": "^5.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 34fb0d6c04..11e69c3eae 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -52,7 +52,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index 599bc1ce3c..3f6d833f7f 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -45,7 +45,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/home/package.json b/plugins/home/package.json index 28b17e89d2..f7f98a26fd 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -60,7 +60,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 474f55845e..1bf968218a 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -51,7 +51,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 11ae1d4799..b9a421d408 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -43,7 +43,7 @@ "@backstage/cli": "workspace:^", "@types/jenkins": "^0.23.1", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index a756afba3c..f6eb791af0 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -61,7 +61,7 @@ "@types/node": "^16.11.26", "@types/testing-library__jest-dom": "^5.9.1", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index f829b4568d..98f01102f3 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -51,7 +51,7 @@ "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", "jest-when": "^3.1.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 06c8df39f6..e7e03ae93e 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -71,7 +71,7 @@ "@types/http-proxy-middleware": "^0.19.3", "aws-sdk-mock": "^5.2.1", "mock-fs": "^5.2.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 0538b099cb..b69efb0d65 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -66,7 +66,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 3c9fe20494..0d9d1365eb 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -61,7 +61,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index 568730bc85..8a49f8dca2 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -46,7 +46,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.2.4" }, "files": [ diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index 61bb4b19a6..0b234878b1 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -55,7 +55,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index c4b445c97b..ce2f148d6c 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -55,7 +55,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 32ee89f6aa..9d183f34d6 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -54,7 +54,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index f62166478d..c469b55c38 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -45,7 +45,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 8b51cd3d91..42dd6c1f26 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -54,7 +54,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/org/package.json b/plugins/org/package.json index cbf97e95d4..c1a4e8b1e5 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -56,7 +56,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 3514bd2b75..f248c6f31f 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -61,7 +61,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index ca7e096505..0472be43b0 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 2c1f98eb56..eba10dc41e 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -50,7 +50,7 @@ "@types/luxon": "^3.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index bd3342e142..eaa2f6ddd1 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -42,7 +42,7 @@ "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 472a86aaab..960ca249d3 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -50,6 +50,6 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", - "msw": "^0.49.0" + "msw": "^1.0.0" } } diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 440b6f411b..673250cd19 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -48,7 +48,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 908362893a..b4232ff786 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -45,7 +45,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index d30e6fb4b1..0cf67652f3 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -61,7 +61,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0", + "msw": "^1.0.0", "swr": "^2.0.0" }, "files": [ diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 7fa3f35e45..a08900fd83 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -53,7 +53,7 @@ "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", "@types/yup": "^0.29.13", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 28a0f1bf3b..7a2f27cea0 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -52,7 +52,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 36b31e9338..f95f2cb8c4 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -61,7 +61,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 29a79640d2..de055be7e8 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -41,7 +41,7 @@ "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "mock-fs": "^5.1.0", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 872759815b..12ef31899c 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -107,7 +107,7 @@ "esbuild": "^0.17.0", "jest-when": "^3.1.0", "mock-fs": "^5.1.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3", "yaml": "^2.0.0" }, diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index c1e257b398..b3d33298cb 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -108,7 +108,7 @@ "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", "event-source-polyfill": "1.0.25", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/search/package.json b/plugins/search/package.json index 1e1552172f..31b57878dd 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -65,7 +65,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index d68eb06ea9..7d385260f4 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -62,7 +62,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 64af56efbd..0209e76ec7 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -50,7 +50,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 3934abe862..6fc9a7080a 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -36,7 +36,7 @@ "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@types/supertest": "^2.0.12", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.2.4" }, "files": [ diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index be3135f790..ef14f6da58 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -61,7 +61,7 @@ "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index cd098d238f..2703a95871 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -60,7 +60,7 @@ "@types/luxon": "^3.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "configSchema": "config.d.ts", "files": [ diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 6698afc182..e5cf07c515 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -43,7 +43,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 2997d331f3..cd0cfeabf3 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -49,7 +49,7 @@ "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index 767abf5118..e00821cf77 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -56,7 +56,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 57def61d19..25b72e0de5 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -56,7 +56,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 4686d329ef..afb484dc06 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -59,7 +59,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 673aafa93c..2f9078c7f8 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -63,7 +63,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index bcba399086..5964e3f58f 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -59,7 +59,7 @@ "@backstage/cli": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", "@types/dockerode": "^3.3.0", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 233e933e89..51d656007d 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -62,7 +62,7 @@ "@types/node": "^16.11.26", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 308987f757..57eca44976 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -78,7 +78,7 @@ "@types/node": "^16.11.26", "canvas": "^2.10.2", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index a0a1db2e0e..f95ae498a7 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -47,7 +47,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.3" }, "files": [ diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 979ee1dacc..8c925c5cf7 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -55,7 +55,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 85614aa8db..cce6dfa1e5 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -59,7 +59,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index fc6fab1b41..fda7059dc5 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -53,7 +53,7 @@ "@backstage/cli": "workspace:^", "@types/compression": "^1.7.2", "@types/supertest": "^2.0.8", - "msw": "^0.49.0", + "msw": "^1.0.0", "supertest": "^6.1.6" }, "files": [ diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 163f9a649d..e0754b9c8d 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -57,7 +57,7 @@ "@testing-library/user-event": "^14.0.0", "@types/node": "*", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 15be9d2579..107cb9600e 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -49,7 +49,7 @@ "@types/luxon": "^3.0.0", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", - "msw": "^0.49.0" + "msw": "^1.0.0" }, "files": [ "dist" diff --git a/yarn.lock b/yarn.lock index c11c002280..858baf1f40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3485,7 +3485,7 @@ __metadata: minimist: ^1.2.5 mock-fs: ^5.1.0 morgan: ^1.10.0 - msw: ^0.49.0 + msw: ^1.0.0 mysql2: ^2.2.5 node-fetch: ^2.6.7 node-forge: ^1.3.1 @@ -3582,7 +3582,7 @@ __metadata: better-sqlite3: ^8.0.0 express: ^4.17.1 knex: ^2.0.0 - msw: ^0.49.0 + msw: ^1.0.0 mysql2: ^2.2.5 pg: ^8.3.0 supertest: ^6.1.3 @@ -3610,7 +3610,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/errors": "workspace:^" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 languageName: unknown linkType: soft @@ -3754,7 +3754,7 @@ __metadata: mini-css-extract-plugin: ^2.4.2 minimatch: ^5.1.1 mock-fs: ^5.1.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 node-libs-browser: ^2.2.1 nodemon: ^2.0.2 @@ -3836,7 +3836,7 @@ __metadata: json-schema-merge-allof: ^0.8.1 json-schema-traverse: ^1.0.0 mock-fs: ^5.1.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 typescript-json-schema: ^0.55.0 yaml: ^2.0.0 @@ -3874,7 +3874,7 @@ __metadata: "@types/prop-types": ^15.7.3 "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 prop-types: ^15.7.2 react-router-beta: "npm:react-router@6.0.0-beta.0" react-router-dom-beta: "npm:react-router-dom@6.0.0-beta.0" @@ -3986,7 +3986,7 @@ __metadata: history: ^5.0.0 immer: ^9.0.1 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 pluralize: ^8.0.0 prop-types: ^15.7.2 qs: ^6.9.4 @@ -4048,7 +4048,7 @@ __metadata: "@types/zen-observable": ^0.8.0 cross-fetch: ^3.1.5 history: ^5.0.0 - msw: ^0.49.0 + msw: ^1.0.0 prop-types: ^15.7.2 zen-observable: ^0.10.0 peerDependencies: @@ -4194,7 +4194,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -4217,7 +4217,7 @@ __metadata: git-url-parse: ^13.0.0 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 languageName: unknown linkType: soft @@ -4241,7 +4241,7 @@ __metadata: express-promise-router: ^4.1.0 luxon: ^3.0.0 marked: ^4.0.14 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.5 supertest: ^6.1.3 winston: ^3.2.1 @@ -4286,7 +4286,7 @@ __metadata: "@types/git-url-parse": ^9.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-markdown: ^8.0.0 react-use: ^17.2.4 remark-gfm: ^3.0.1 @@ -4310,7 +4310,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 http-proxy-middleware: ^2.0.0 - msw: ^0.49.0 + msw: ^1.0.0 supertest: ^6.1.6 winston: ^3.2.1 yn: ^4.0.0 @@ -4338,7 +4338,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -4367,7 +4367,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -4395,7 +4395,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-ga: ^3.3.0 react-use: ^17.2.4 peerDependencies: @@ -4421,7 +4421,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: @@ -4470,7 +4470,7 @@ __metadata: graphql: ^16.0.0 graphql-ws: ^5.4.1 isomorphic-form-data: ^2.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 swagger-ui-react: ^4.11.1 peerDependencies: @@ -4500,7 +4500,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 use-deep-compare-effect: ^1.8.1 peerDependencies: @@ -4531,7 +4531,7 @@ __metadata: lodash: ^4.17.21 luxon: ^3.0.0 mock-fs: ^5.1.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.1.3 winston: ^3.2.1 @@ -4583,7 +4583,7 @@ __metadata: luxon: ^3.0.0 minimatch: ^5.0.0 morgan: ^1.10.0 - msw: ^0.49.0 + msw: ^1.0.0 node-cache: ^5.1.2 node-fetch: ^2.6.7 openid-client: ^5.2.1 @@ -4617,7 +4617,7 @@ __metadata: express: ^4.17.1 jose: ^4.6.0 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 uuid: ^8.0.0 winston: ^3.2.1 @@ -4638,7 +4638,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 mime-types: ^2.1.27 - msw: ^0.49.0 + msw: ^1.0.0 p-limit: ^3.1.0 supertest: ^6.1.6 winston: ^3.2.1 @@ -4679,7 +4679,7 @@ __metadata: cross-fetch: ^3.1.5 humanize-duration: ^3.27.0 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -4702,7 +4702,7 @@ __metadata: "@types/supertest": ^2.0.8 express: ^4.17.1 express-promise-router: ^4.1.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 winston: ^3.2.1 yn: ^4.0.0 @@ -4740,7 +4740,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -4791,7 +4791,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -4857,7 +4857,7 @@ __metadata: "@backstage/integration": "workspace:^" "@openapitools/openapi-generator-cli": ^2.4.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 ts-morph: ^17.0.0 languageName: unknown linkType: soft @@ -4886,7 +4886,7 @@ __metadata: cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.9.6 react-use: ^17.2.4 recharts: ^2.0.0 @@ -4944,7 +4944,7 @@ __metadata: "@types/lodash": ^4.14.151 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 uuid: ^8.0.0 winston: ^3.2.1 @@ -4970,7 +4970,7 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-node": "workspace:^" luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 uuid: ^8.0.0 winston: ^3.2.1 languageName: unknown @@ -4993,7 +4993,7 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@types/node-fetch": ^2.5.12 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 uuid: ^8.0.0 winston: ^3.2.1 @@ -5016,7 +5016,7 @@ __metadata: "@backstage/types": "workspace:^" "@types/lodash": ^4.14.151 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 winston: ^3.2.1 languageName: unknown @@ -5040,7 +5040,7 @@ __metadata: "@types/fs-extra": ^9.0.1 fs-extra: 10.1.0 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 uuid: ^8.0.0 winston: ^3.2.1 @@ -5073,7 +5073,7 @@ __metadata: lodash: ^4.17.21 luxon: ^3.0.0 minimatch: ^5.1.2 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 uuid: ^8.0.0 winston: ^3.2.1 @@ -5100,7 +5100,7 @@ __metadata: "@types/uuid": ^8.0.0 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 uuid: ^8.0.0 winston: ^3.2.1 @@ -5176,7 +5176,7 @@ __metadata: "@types/node-fetch": ^2.5.12 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 p-limit: ^3.0.2 qs: ^6.9.4 @@ -5246,7 +5246,7 @@ __metadata: lodash: ^4.17.21 luxon: ^3.0.0 minimatch: ^5.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 p-limit: ^3.0.2 prom-client: ^14.0.1 @@ -5336,7 +5336,7 @@ __metadata: graphql-modules: ^2.0.0 graphql-tag: ^2.11.0 graphql-type-json: ^0.3.2 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 winston: ^3.2.1 languageName: unknown @@ -5372,7 +5372,7 @@ __metadata: git-url-parse: ^13.0.0 js-base64: ^3.6.0 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 react-hook-form: ^7.12.2 react-use: ^17.2.4 yaml: ^2.0.0 @@ -5588,7 +5588,7 @@ __metadata: humanize-duration: ^3.27.0 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -5618,7 +5618,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: @@ -5651,7 +5651,7 @@ __metadata: cross-fetch: ^3.1.5 humanize-duration: ^3.27.1 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -5677,7 +5677,7 @@ __metadata: express-promise-router: ^4.1.0 express-xml-bodyparser: ^0.3.0 knex: ^2.0.0 - msw: ^0.49.0 + msw: ^1.0.0 supertest: ^6.1.6 uuid: ^8.3.2 winston: ^3.2.1 @@ -5714,7 +5714,7 @@ __metadata: cross-fetch: ^3.1.5 highlight.js: ^10.6.0 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 recharts: ^2.0.0 peerDependencies: @@ -5744,7 +5744,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 rc-progress: 3.4.1 react-use: ^17.2.4 peerDependencies: @@ -5776,7 +5776,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 jsonschema: ^1.2.6 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: @@ -5824,7 +5824,7 @@ __metadata: cross-fetch: ^3.1.5 history: ^5.0.0 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 pluralize: ^8.0.0 qs: ^6.9.4 react-use: ^17.2.4 @@ -5858,7 +5858,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" express: ^4.18.1 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: "@backstage/plugin-catalog-react": "workspace:^" @@ -5883,7 +5883,7 @@ __metadata: express: ^4.18.1 express-promise-router: ^4.1.0 knex: ^2.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.2.4 winston: ^3.2.1 @@ -5923,7 +5923,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 @@ -5962,7 +5962,7 @@ __metadata: "@uiw/react-codemirror": ^4.9.3 cross-fetch: ^3.1.5 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 yaml: ^2.0.0 peerDependencies: @@ -6115,7 +6115,7 @@ __metadata: express: ^4.18.1 express-promise-router: ^4.1.0 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.2.4 winston: ^3.2.1 @@ -6145,7 +6145,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 languageName: unknown linkType: soft @@ -6177,7 +6177,7 @@ __metadata: "@types/node": ^16.11.26 classnames: ^2.2.6 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 @@ -6207,7 +6207,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6237,7 +6237,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 p-limit: ^3.0.2 react-use: ^17.2.4 peerDependencies: @@ -6274,7 +6274,7 @@ __metadata: lodash: ^4.17.21 luxon: ^3.0.0 material-ui-popup-state: ^1.9.3 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6301,7 +6301,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 peerDependencies: react: ^16.13.1 || ^17.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 @@ -6332,7 +6332,7 @@ __metadata: "@types/recharts": ^1.8.15 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.10.1 react-use: ^17.2.4 recharts: ^2.0.0 @@ -6367,7 +6367,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6401,7 +6401,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6434,7 +6434,7 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 octokit: ^2.0.4 react-use: ^17.4.0 peerDependencies: @@ -6466,7 +6466,7 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 p-limit: ^4.0.0 react-use: ^17.2.4 peerDependencies: @@ -6494,7 +6494,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6528,7 +6528,7 @@ __metadata: cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: @@ -6559,7 +6559,7 @@ __metadata: graphiql: ^1.5.12 graphql: ^16.0.0 graphql-ws: ^5.4.1 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6585,7 +6585,7 @@ __metadata: graphql: ^16.0.0 graphql-modules: ^2.0.0 helmet: ^6.0.0 - msw: ^0.49.0 + msw: ^1.0.0 reflect-metadata: ^0.1.13 supertest: ^6.1.3 winston: ^3.2.1 @@ -6613,7 +6613,7 @@ __metadata: "@types/node": "*" cross-fetch: ^3.1.5 graphql-voyager: ^1.0.0-rc.31 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6666,7 +6666,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 @@ -6701,7 +6701,7 @@ __metadata: cross-fetch: ^3.1.5 humanize-duration: ^3.26.0 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6727,7 +6727,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 jenkins: ^1.0.0 - msw: ^0.49.0 + msw: ^1.0.0 supertest: ^6.1.6 winston: ^3.2.1 yn: ^4.0.0 @@ -6769,7 +6769,7 @@ __metadata: "@types/testing-library__jest-dom": ^5.9.1 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6824,7 +6824,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 jest-when: ^3.1.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6867,7 +6867,7 @@ __metadata: luxon: ^3.0.0 mock-fs: ^5.2.0 morgan: ^1.10.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 stream-buffers: ^3.0.2 supertest: ^6.1.3 @@ -6916,7 +6916,7 @@ __metadata: js-yaml: ^4.0.0 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -6974,7 +6974,7 @@ __metadata: "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -7004,7 +7004,7 @@ __metadata: knex: ^2.0.0 linguist-js: ^2.5.3 luxon: ^2.0.2 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.2.4 uuid: ^8.3.2 @@ -7045,7 +7045,7 @@ __metadata: "@types/node": "*" cross-fetch: ^3.1.5 luxon: ^2.0.2 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 slugify: ^1.6.4 peerDependencies: @@ -7079,7 +7079,7 @@ __metadata: lodash: ^4.17.21 luxon: ^3.0.0 material-ui-popup-state: ^1.9.3 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -7128,7 +7128,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -7156,7 +7156,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -7185,7 +7185,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -7214,7 +7214,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 p-limit: ^3.1.0 pluralize: ^8.0.0 qs: ^6.10.1 @@ -7249,7 +7249,7 @@ __metadata: classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 @@ -7270,7 +7270,7 @@ __metadata: "@types/supertest": ^2.0.8 express: ^4.17.1 express-promise-router: ^4.1.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.1.6 winston: ^3.2.1 @@ -7302,7 +7302,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -7328,7 +7328,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.1.6 winston: ^3.2.1 @@ -7346,7 +7346,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/types": "workspace:^" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 uuid: ^8.0.0 zod: ~3.18.0 languageName: unknown @@ -7367,7 +7367,7 @@ __metadata: "@types/supertest": ^2.0.8 express: ^4.17.1 express-promise-router: ^4.1.0 - msw: ^0.49.0 + msw: ^1.0.0 supertest: ^6.1.3 zod: ~3.18.0 zod-to-json-schema: ~3.18.0 @@ -7433,7 +7433,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 knex: ^2.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.1.3 uuid: ^8.2.0 @@ -7481,7 +7481,7 @@ __metadata: "@types/node": "*" cross-fetch: ^3.1.5 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.9.4 react-hook-form: ^7.13.0 react-use: ^17.2.4 @@ -7509,7 +7509,7 @@ __metadata: express-promise-router: ^4.1.0 http-proxy-middleware: ^2.0.0 morgan: ^1.10.0 - msw: ^0.49.0 + msw: ^1.0.0 supertest: ^6.1.3 uuid: ^8.0.0 winston: ^3.2.1 @@ -7537,7 +7537,7 @@ __metadata: fs-extra: 10.1.0 lodash: ^4.17.21 morgan: ^1.10.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.1.3 winston: ^3.2.1 @@ -7569,7 +7569,7 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 react-sparklines: ^1.7.0 react-use: ^17.2.4 peerDependencies: @@ -7596,7 +7596,7 @@ __metadata: command-exists: ^1.2.9 fs-extra: 10.1.0 mock-fs: ^5.1.0 - msw: ^0.49.0 + msw: ^1.0.0 winston: ^3.2.1 yn: ^4.0.0 languageName: unknown @@ -7700,7 +7700,7 @@ __metadata: luxon: ^3.0.0 mock-fs: ^5.1.0 morgan: ^1.10.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 nunjucks: ^3.2.3 octokit: ^2.0.0 @@ -7844,7 +7844,7 @@ __metadata: json-schema-library: ^7.3.9 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.9.4 react-use: ^17.2.4 use-immer: ^0.8.0 @@ -8015,7 +8015,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: @@ -8050,7 +8050,7 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-sparklines: ^1.7.0 react-use: ^17.2.4 peerDependencies: @@ -8080,7 +8080,7 @@ __metadata: "@types/node": ^16.11.26 "@types/zen-observable": ^0.8.2 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-hook-form: ^7.12.2 react-use: ^17.2.4 uuid: ^8.3.2 @@ -8104,7 +8104,7 @@ __metadata: "@types/supertest": ^2.0.12 express: ^4.18.1 express-promise-router: ^4.1.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 supertest: ^6.2.4 winston: ^3.2.1 @@ -8147,7 +8147,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 rc-progress: 3.4.1 react-use: ^17.2.4 peerDependencies: @@ -8179,7 +8179,7 @@ __metadata: classnames: ^2.2.6 cross-fetch: ^3.1.5 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -8197,7 +8197,7 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" "@backstage/plugin-search-common": "workspace:^" - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 qs: ^6.9.4 winston: ^3.2.1 @@ -8227,7 +8227,7 @@ __metadata: "@types/node": ^16.11.26 cross-fetch: ^3.1.5 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: @@ -8256,7 +8256,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -8365,7 +8365,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: @@ -8399,7 +8399,7 @@ __metadata: color: ^4.0.1 cross-fetch: ^3.1.5 d3-force: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 prop-types: ^15.7.2 react-use: ^17.2.4 peerDependencies: @@ -8431,7 +8431,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 testing-library__dom: ^7.29.4-beta.1 peerDependencies: @@ -8467,7 +8467,7 @@ __metadata: fs-extra: 10.1.0 knex: ^2.0.0 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 p-limit: ^3.1.0 supertest: ^6.1.3 @@ -8501,7 +8501,7 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 git-url-parse: ^13.0.0 - msw: ^0.49.0 + msw: ^1.0.0 photoswipe: ^5.3.5 react-use: ^17.2.4 peerDependencies: @@ -8619,7 +8619,7 @@ __metadata: git-url-parse: ^13.0.0 jss: ~10.9.0 lodash: ^4.17.21 - msw: ^0.49.0 + msw: ^1.0.0 react-helmet: 6.1.0 react-use: ^17.2.4 peerDependencies: @@ -8648,7 +8648,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 leasot: ^12.0.0 - msw: ^0.49.0 + msw: ^1.0.0 supertest: ^6.1.3 winston: ^3.2.1 yn: ^4.0.0 @@ -8677,7 +8677,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -8731,7 +8731,7 @@ __metadata: "@types/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: @@ -8758,7 +8758,7 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 helmet: ^6.0.0 - msw: ^0.49.0 + msw: ^1.0.0 node-fetch: ^2.6.7 p-limit: ^3.1.0 supertest: ^6.1.6 @@ -8789,7 +8789,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": "*" cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -8819,7 +8819,7 @@ __metadata: cross-fetch: ^3.1.5 lodash: ^4.17.21 luxon: ^3.0.0 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 recharts: ^2.0.0 peerDependencies: @@ -8835,7 +8835,7 @@ __metadata: "@backstage/test-utils": "workspace:^" "@types/node": ^16.0.0 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 languageName: unknown linkType: soft @@ -8893,7 +8893,7 @@ __metadata: "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 zen-observable: ^0.10.0 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 @@ -10941,7 +10941,7 @@ __metadata: "@types/uuid": ^8.0.0 express: ^4.17.1 express-promise-router: ^4.1.0 - msw: ^0.49.0 + msw: ^1.0.0 supertest: ^6.1.6 uuid: ^8.3.2 winston: ^3.2.1 @@ -10960,7 +10960,7 @@ __metadata: "@backstage/test-utils": "workspace:^" "@types/node": ^16.11.26 cross-fetch: ^3.1.5 - msw: ^0.49.0 + msw: ^1.0.0 languageName: unknown linkType: soft @@ -10982,7 +10982,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 "@types/node": ^16.11.26 - msw: ^0.49.0 + msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -29977,41 +29977,7 @@ __metadata: languageName: node linkType: hard -"msw@npm:^0.49.0": - version: 0.49.3 - resolution: "msw@npm:0.49.3" - dependencies: - "@mswjs/cookies": ^0.2.2 - "@mswjs/interceptors": ^0.17.5 - "@open-draft/until": ^1.0.3 - "@types/cookie": ^0.4.1 - "@types/js-levenshtein": ^1.1.1 - chalk: 4.1.1 - chokidar: ^3.4.2 - cookie: ^0.4.2 - graphql: ^15.0.0 || ^16.0.0 - headers-polyfill: ^3.1.0 - inquirer: ^8.2.0 - is-node-process: ^1.0.1 - js-levenshtein: ^1.1.6 - node-fetch: ^2.6.7 - outvariant: ^1.3.0 - path-to-regexp: ^6.2.0 - strict-event-emitter: ^0.4.3 - type-fest: ^2.19.0 - yargs: ^17.3.1 - peerDependencies: - typescript: ">= 4.4.x <= 4.9.x" - peerDependenciesMeta: - typescript: - optional: true - bin: - msw: cli/index.js - checksum: 8322cd42cd69f289c05517d02bde22fc2f10e86fc2d0d209d9df54bd03d10b8123723c5587a2654dcd2cd0f314a016f9eccac88cffa30fafd1f9fead16db639e - languageName: node - linkType: hard - -"msw@npm:^1.0.1": +"msw@npm:^1.0.0, msw@npm:^1.0.1": version: 1.0.1 resolution: "msw@npm:1.0.1" dependencies: From 7c5d76473627eda41ef699d759f380160c87811d Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 22 Feb 2023 14:09:01 +0100 Subject: [PATCH 402/417] microsite: Add overview header image to assets Signed-off-by: Johan Haals --- docs/assets/header.png | Bin 0 -> 492757 bytes docs/overview/what-is-backstage.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/assets/header.png diff --git a/docs/assets/header.png b/docs/assets/header.png new file mode 100644 index 0000000000000000000000000000000000000000..3c39971d361f3a0d1f65547b102c5db387bf1118 GIT binary patch literal 492757 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%0D3B124Zw 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

    jmZVh8#H_D%C4v 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

    n!C?uhSZvj&=YlOMH|J)=~$w?J?5C|?%!*4d(m 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%0DdY0G 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 fioz#n@Bt*4d4PxS-nGTlDb5)Z@gQL6Z9Uo_#{ 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 B&?o=^ literal 0 HcmV?d00001 diff --git a/docs/overview/what-is-backstage.md b/docs/overview/what-is-backstage.md index 38b67e81de..7e20cda568 100644 --- a/docs/overview/what-is-backstage.md +++ b/docs/overview/what-is-backstage.md @@ -5,7 +5,7 @@ title: What is Backstage? description: Backstage is an open platform for building developer portals. Powered by a centralized software catalog, Backstage restores order to your microservices and infrastructure --- -![software-catalog](https://backstage.io/blog/assets/6/header.png) +![software-catalog](../assets/header.png) [Backstage](https://backstage.io/) is an open platform for building developer portals. Powered by a centralized software catalog, Backstage restores order to From c10384a92358511f9dbcb4197fa2b9d87eebc02e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 20 Feb 2023 11:09:08 +0100 Subject: [PATCH 403/417] Get rid of usages of the old Button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/quiet-ghosts-float.md | 12 ++++++++++++ packages/core-components/api-report.md | 4 ++-- .../src/components/LinkButton/LinkButton.tsx | 8 +++++--- .../src/layout/ErrorBoundary/ErrorBoundary.tsx | 6 +++--- .../src/layout/ItemCard/ItemCard.stories.tsx | 10 +++++----- .../core-components/src/layout/ItemCard/ItemCard.tsx | 10 +++++----- .../BuildWithStepsPage/BuildWithStepsPage.tsx | 6 +++--- .../EntityValidationPage/EntityValidationPage.tsx | 1 + .../explore/src/components/DomainCard/DomainCard.tsx | 6 +++--- plugins/explore/src/components/ToolCard/ToolCard.tsx | 6 +++--- .../components/KubernetesDrawer/KubernetesDrawer.tsx | 2 +- .../src/components/PlaylistCard/PlaylistCard.tsx | 6 +++--- .../src/components/TemplateCard/TemplateCard.tsx | 7 ++++--- .../DefaultResultListItem.stories.tsx | 6 +++--- .../src/home/components/Grids/DocsCardGrid.tsx | 6 +++--- .../src/home/components/Tables/DocsTable.tsx | 6 +++--- 16 files changed, 59 insertions(+), 43 deletions(-) create mode 100644 .changeset/quiet-ghosts-float.md diff --git a/.changeset/quiet-ghosts-float.md b/.changeset/quiet-ghosts-float.md new file mode 100644 index 0000000000..dc8df90206 --- /dev/null +++ b/.changeset/quiet-ghosts-float.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-entity-validation': patch +'@backstage/core-components': patch +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-circleci': patch +'@backstage/plugin-playlist': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-explore': patch +--- + +Switch to using `LinkButton` instead of the deprecated `Button` diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 721c208406..6439be23a7 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -131,7 +131,7 @@ export type BreadcrumbsStyledBoxClassKey = 'root'; export function BrokenImageIcon(props: IconComponentProps): JSX.Element; // @public @deprecated (undocumented) -export const Button: (props: ButtonProps) => JSX.Element; +export const Button: (props: LinkButtonProps) => JSX.Element; // @public @deprecated (undocumented) export type ButtonProps = LinkButtonProps; @@ -631,7 +631,7 @@ export function LinearGauge(props: Props_11): JSX.Element | null; export const Link: (props: LinkProps) => JSX.Element; // @public -export const LinkButton: (props: ButtonProps) => JSX.Element; +export const LinkButton: (props: LinkButtonProps) => JSX.Element; // @public export type LinkButtonProps = ButtonProps_2 & diff --git a/packages/core-components/src/components/LinkButton/LinkButton.tsx b/packages/core-components/src/components/LinkButton/LinkButton.tsx index a6ba4d67a7..7da25bcb41 100644 --- a/packages/core-components/src/components/LinkButton/LinkButton.tsx +++ b/packages/core-components/src/components/LinkButton/LinkButton.tsx @@ -44,9 +44,11 @@ const LinkWrapper = React.forwardRef((props, ref) => ( * @public * @remarks */ -export const LinkButton = React.forwardRef((props, ref) => ( - -)) as (props: ButtonProps) => JSX.Element; +export const LinkButton = React.forwardRef( + (props, ref) => ( + + ), +) as (props: LinkButtonProps) => JSX.Element; /** * @public diff --git a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx index 9157b57fe2..037e170640 100644 --- a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx +++ b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.tsx @@ -16,7 +16,7 @@ import Typography from '@material-ui/core/Typography'; import React, { ComponentClass, Component, ErrorInfo } from 'react'; -import { Button } from '../../components/LinkButton'; +import { LinkButton } from '../../components/LinkButton'; import { ErrorPanel } from '../../components/ErrorPanel'; type SlackChannel = { @@ -49,9 +49,9 @@ const SlackLink = (props: { slackChannel?: string | SlackChannel }) => { } return ( - + ); }; diff --git a/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx b/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx index f7df3d43cc..1ba3dec3fd 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx @@ -22,7 +22,7 @@ import CardMedia from '@material-ui/core/CardMedia'; import Typography from '@material-ui/core/Typography'; import React from 'react'; import { MemoryRouter } from 'react-router-dom'; -import { Button } from '../../components'; +import { LinkButton } from '../../components'; import { ItemCardGrid } from './ItemCardGrid'; import { ItemCardHeader } from './ItemCardHeader'; @@ -63,9 +63,9 @@ export const Default = () => ( .join(' ')} - + ))} @@ -99,9 +99,9 @@ export const Styling = () => { .join(' ')} - + ))} diff --git a/packages/core-components/src/layout/ItemCard/ItemCard.tsx b/packages/core-components/src/layout/ItemCard/ItemCard.tsx index fedcf7de8f..0b1ee34c0c 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCard.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCard.tsx @@ -21,7 +21,7 @@ import CardContent from '@material-ui/core/CardContent'; import CardMedia from '@material-ui/core/CardMedia'; import Chip from '@material-ui/core/Chip'; import React, { ReactNode } from 'react'; -import { Button } from '../../components'; +import { LinkButton } from '../../components'; import { ItemCardHeader } from './ItemCardHeader'; type ItemCardProps = { @@ -80,14 +80,14 @@ export function ItemCard(props: ItemCardProps) { {!href && ( - + )} {href && ( - + )} diff --git a/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx b/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx index 8d48be915e..8a5dc1c47f 100644 --- a/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx +++ b/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx @@ -24,7 +24,7 @@ import LaunchIcon from '@material-ui/icons/Launch'; import { useBuildWithSteps } from '../../state/useBuildWithSteps'; import { Breadcrumbs, - Button, + LinkButton, InfoCard, Progress, Link, @@ -33,9 +33,9 @@ import { const BuildName = ({ build }: { build?: BuildWithSteps }) => ( #{build?.build_num} - {build?.subject} - + ); diff --git a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx index 52628e6ad2..0f0e60366b 100644 --- a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx +++ b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import React, { useState } from 'react'; import { Content, Header, LinkButton, Page } from '@backstage/core-components'; import { EntityTextArea } from '../EntityTextArea'; diff --git a/plugins/explore/src/components/DomainCard/DomainCard.tsx b/plugins/explore/src/components/DomainCard/DomainCard.tsx index a20a5e1f0c..0d37e3e273 100644 --- a/plugins/explore/src/components/DomainCard/DomainCard.tsx +++ b/plugins/explore/src/components/DomainCard/DomainCard.tsx @@ -31,7 +31,7 @@ import { } from '@material-ui/core'; import React from 'react'; -import { Button, ItemCardHeader } from '@backstage/core-components'; +import { LinkButton, ItemCardHeader } from '@backstage/core-components'; import { useRouteRef } from '@backstage/core-plugin-api'; /** @public */ @@ -66,9 +66,9 @@ export const DomainCard = (props: { entity: DomainEntity }) => { {entity.metadata.description} - + ); diff --git a/plugins/explore/src/components/ToolCard/ToolCard.tsx b/plugins/explore/src/components/ToolCard/ToolCard.tsx index 904db0c00b..27729ea085 100644 --- a/plugins/explore/src/components/ToolCard/ToolCard.tsx +++ b/plugins/explore/src/components/ToolCard/ToolCard.tsx @@ -26,7 +26,7 @@ import { makeStyles, Typography, } from '@material-ui/core'; -import { Button } from '@backstage/core-components'; +import { LinkButton } from '@backstage/core-components'; import classNames from 'classnames'; import React from 'react'; @@ -97,9 +97,9 @@ export const ToolCard = ({ card, objectFit }: Props) => { )} - + ); diff --git a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx b/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx index 8a177cf6dd..7e194c3ec2 100644 --- a/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx +++ b/plugins/kubernetes/src/components/KubernetesDrawer/KubernetesDrawer.tsx @@ -33,7 +33,7 @@ import { V1ObjectMeta } from '@kubernetes/client-node'; import { withStyles } from '@material-ui/core/styles'; import jsYaml from 'js-yaml'; import { - Button as BackstageButton, + LinkButton as BackstageButton, CodeSnippet, StructuredMetadataTable, WarningPanel, diff --git a/plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx b/plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx index 2db7e85f7e..1bf698f6be 100644 --- a/plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx +++ b/plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx @@ -15,8 +15,8 @@ */ import { - Button, ItemCardHeader, + LinkButton, MarkdownContent, } from '@backstage/core-components'; import { useRouteRef } from '@backstage/core-plugin-api'; @@ -118,13 +118,13 @@ export const PlaylistCard = ({ playlist }: PlaylistCardProps) => { - + ); diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index 984e51f3b5..e557f4d165 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { DEFAULT_NAMESPACE, Entity, @@ -22,9 +23,9 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { - Button, ItemCardHeader, Link, + LinkButton, MarkdownContent, } from '@backstage/core-components'; import { @@ -291,13 +292,13 @@ export const TemplateCard = ({ template, deprecated }: TemplateCardProps) => { ))}

    - + ); diff --git a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx index a790c12a8a..7049b7f4ef 100644 --- a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx +++ b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.stories.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Button } from '@backstage/core-components'; +import { LinkButton } from '@backstage/core-components'; import { lightTheme } from '@backstage/theme'; import { Grid } from '@material-ui/core'; import CssBaseline from '@material-ui/core/CssBaseline'; @@ -66,7 +66,7 @@ export const WithSecondaryAction = () => { { style={{ textTransform: 'lowercase' }} > {mockSearchResult.owner} - + } /> ); diff --git a/plugins/techdocs/src/home/components/Grids/DocsCardGrid.tsx b/plugins/techdocs/src/home/components/Grids/DocsCardGrid.tsx index 6f1d9fbe61..8843249291 100644 --- a/plugins/techdocs/src/home/components/Grids/DocsCardGrid.tsx +++ b/plugins/techdocs/src/home/components/Grids/DocsCardGrid.tsx @@ -19,7 +19,7 @@ import { toLowerMaybe } from '../../../helpers'; import { Entity } from '@backstage/catalog-model'; import { useApi, useRouteRef, configApiRef } from '@backstage/core-plugin-api'; import { - Button, + LinkButton, ItemCardGrid, ItemCardHeader, } from '@backstage/core-components'; @@ -58,7 +58,7 @@ export const DocsCardGrid = (props: DocsCardGridProps) => { {entity.metadata.description} - + ))} diff --git a/plugins/techdocs/src/home/components/Tables/DocsTable.tsx b/plugins/techdocs/src/home/components/Tables/DocsTable.tsx index 842c80018f..5e5b41ee3e 100644 --- a/plugins/techdocs/src/home/components/Tables/DocsTable.tsx +++ b/plugins/techdocs/src/home/components/Tables/DocsTable.tsx @@ -25,7 +25,7 @@ import { } from '@backstage/plugin-catalog-react'; import { rootDocsRouteRef } from '../../../routes'; import { - Button, + LinkButton, EmptyState, Table, TableColumn, @@ -121,13 +121,13 @@ export const DocsTable = (props: DocsTableProps) => { title="No documents to show" description="Create your own document. Check out our Getting Started Information" action={ - + } /> )} From c3dc3fedda7c1166ccf553daab270e124270ec7a Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 22 Feb 2023 14:30:46 +0100 Subject: [PATCH 404/417] backend-system: doc tweaks Signed-off-by: Patrik Oldsberg --- docs/backend-system/architecture/01-index.md | 2 +- docs/backend-system/architecture/06-modules.md | 4 ---- docs/backend-system/building-backends/01-index.md | 4 ++-- .../building-plugins-and-modules/01-index.md | 8 +++----- docs/backend-system/core-services/01-index.md | 2 +- docs/backend-system/index.md | 2 +- 6 files changed, 8 insertions(+), 14 deletions(-) diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index 76953f7009..aff730b0d1 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -1,7 +1,7 @@ --- id: index title: Backend System Architecture -sidebar_label: System Architecture +sidebar_label: Overview # prettier-ignore description: The structure and architecture of the new Backend System and its component parts --- diff --git a/docs/backend-system/architecture/06-modules.md b/docs/backend-system/architecture/06-modules.md index 53aae9e38d..b4a2e8338a 100644 --- a/docs/backend-system/architecture/06-modules.md +++ b/docs/backend-system/architecture/06-modules.md @@ -43,7 +43,3 @@ export const catalogModuleExampleCustomProcessor = createBackendModule({ Notice that we're placing the extension point we want to interact with in the `deps` option, while also depending on the logger service at the same time. When initializing modules we can depend on both extension points and services interchangeably. You can also depend on multiple extension points at once, in case the implementation of the module requires it. It is typically best to keep modules slim and to each only add a single new feature. It is often the case that it is better to create two separate modules rather than one that provides both features. The one limitation here is that modules can not interact with each other and need to be self contained. - -## HTTP Handlers - -Since modules have access to the same services as the plugin they extend, they are also able to register their own HTTP handlers. For more information about the HTTP service, see [core services](../core-services/01-index.md). When registering HTTP handlers, it is important to try to avoid any future conflict with the plugin itself, or other modules. A recommended naming pattern is to register the handlers under the `/modules/` path, where `` is the kebab-case ID of the module, for example `/modules/example-custom-processor/v1/validators`. In a standard backend setup the full path would then be `/api/catalog/modules/example-custom-processor/v1/validators`. diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index 65c536afdd..66bf68ab07 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -11,12 +11,12 @@ description: Building backends using the new backend system > NOTE: If you have an existing backend that is not yet using the new backend > system, see [migrating](./08-migrating.md). +This section covers how to set up and customize your own Backstage backend. It covers some aspects of how backend instances fit into the larger system, but for a more in-depth explanation of the role of backends in the backend system, see [the architecture section](../architecture/02-backends.md). + # Overview A minimal Backstage backend is very lightweight. It is a single package with a `package.json` file and a `src/index.ts` file, not counting surrounding tooling and documentation. The package is typically placed within the `packages/backend` folder of a Backstage monorepo, but that is up to you. The backend package is part of any project created with `@backstage/create-app`, so you typically do not need to create it yourself. -You'll get a brief description here, but for a more in-depth explanation of the role of backends in the backend system, see [the architecture section](../architecture/02-backends.md). - When you create a new project with `@backstage/create-app`, you'll get a backend package with a `src/index.ts` that looks something like this: ```ts diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index 848a38ce16..1556b6b377 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -11,11 +11,9 @@ description: Building backend plugins and modules using the new backend system > NOTE: If you have an existing backend and/or backend plugins that are not yet > using the new backend system, see [migrating](./08-migrating.md). -## Overview - -Backend [plugins](../architecture/04-plugins.md) and -[modules](../architecture/06-modules.md), sometimes collectively referred to as -backend _features_, are the building blocks that adopters add to their +This section covers how to build your own backend [plugins](../architecture/04-plugins.md) and +[modules](../architecture/06-modules.md). They are sometimes collectively referred to as +backend _features_, and are the building blocks that adopters add to their [backends](../architecture/02-backends.md). ## Creating a new Plugin diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index 6448943e3a..c688055c96 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -1,7 +1,7 @@ --- id: index title: Core Backend Service APIs -sidebar_label: Core Services +sidebar_label: Overview # prettier-ignore description: Core backend service APIs --- diff --git a/docs/backend-system/index.md b/docs/backend-system/index.md index d2d7c8e69e..87eb008129 100644 --- a/docs/backend-system/index.md +++ b/docs/backend-system/index.md @@ -1,7 +1,7 @@ --- id: index title: The Backend System -sidebar_label: Overview +sidebar_label: Introduction # prettier-ignore description: The Backend System --- From cc1ad26fd88152ca2e515a273eb92882c064c808 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 22 Feb 2023 14:33:48 +0100 Subject: [PATCH 405/417] docs/releases: fix bad links in changelog Signed-off-by: Patrik Oldsberg --- docs/releases/v1.10.0-next.2-changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/releases/v1.10.0-next.2-changelog.md b/docs/releases/v1.10.0-next.2-changelog.md index 8f1dec1e8d..4d8243799b 100644 --- a/docs/releases/v1.10.0-next.2-changelog.md +++ b/docs/releases/v1.10.0-next.2-changelog.md @@ -127,7 +127,7 @@ - e4469d0ec1: The ADR plugin can now work with sites other than GitHub. Expanded the ADR backend plugin to provide endpoints to facilitate this. - **BREAKING** The ADR plugin now uses UrlReaders. You will have to [configure integrations](https://backstage.io/docs/integrations/index#configuration) for all sites you want to get ADRs from. If you would like to create your own implementation that has different behavior, you can override the AdrApi [just like you can with other apis.](https://backstage.io/docs/api/utility-apis#app-apis) The previously used Octokit implementation has been completely removed. + **BREAKING** The ADR plugin now uses UrlReaders. You will have to [configure integrations](https://backstage.io/docs/integrations#configuration) for all sites you want to get ADRs from. If you would like to create your own implementation that has different behavior, you can override the AdrApi [just like you can with other apis.](https://backstage.io/docs/api/utility-apis#app-apis) The previously used Octokit implementation has been completely removed. ### Patch Changes @@ -424,7 +424,7 @@ - e4469d0ec1: The ADR plugin can now work with sites other than GitHub. Expanded the ADR backend plugin to provide endpoints to facilitate this. - **BREAKING** The ADR plugin now uses UrlReaders. You will have to [configure integrations](https://backstage.io/docs/integrations/index#configuration) for all sites you want to get ADRs from. If you would like to create your own implementation that has different behavior, you can override the AdrApi [just like you can with other apis.](https://backstage.io/docs/api/utility-apis#app-apis) The previously used Octokit implementation has been completely removed. + **BREAKING** The ADR plugin now uses UrlReaders. You will have to [configure integrations](https://backstage.io/docs/integrations#configuration) for all sites you want to get ADRs from. If you would like to create your own implementation that has different behavior, you can override the AdrApi [just like you can with other apis.](https://backstage.io/docs/api/utility-apis#app-apis) The previously used Octokit implementation has been completely removed. - 21ffbdd5ee: Clarify that default ADR parsers support MADR specification v2.x From e1d244d50c6b406c24543246eb3116e25e562c04 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 14:23:45 +0000 Subject: [PATCH 406/417] chore(deps): update dependency @types/http-proxy to v1.17.10 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c11c002280..754e1666de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14803,11 +14803,11 @@ __metadata: linkType: hard "@types/http-proxy@npm:*, @types/http-proxy@npm:^1.17.4, @types/http-proxy@npm:^1.17.8": - version: 1.17.9 - resolution: "@types/http-proxy@npm:1.17.9" + version: 1.17.10 + resolution: "@types/http-proxy@npm:1.17.10" dependencies: "@types/node": "*" - checksum: 7a6746d00729b2a9fe9f9dd3453430b099931df879ec8f7a7b5f07b1795f6d99b0512640c45a67390b1e4bacb9401e36824952aeeaf089feba8627a063cf8e00 + checksum: 8fabee5d01715e338f426715325121d6c4b7a9694dee716ab61c874e0aaccee9a0fff7ccc3c9d7e37a8feeaab7c783c17aaa9943efbc8849c5e79ecd7eaf02ab languageName: node linkType: hard From b990021ddebf17c861bbc481e817536db40fbb7e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Feb 2023 15:11:43 +0000 Subject: [PATCH 407/417] chore(deps): update graphqlcodegenerator monorepo to v3 Signed-off-by: Renovate Bot --- .changeset/renovate-4775edd.md | 8 ++ plugins/catalog-graphql/package.json | 8 +- yarn.lock | 204 +++++++++++++++++---------- 3 files changed, 139 insertions(+), 81 deletions(-) create mode 100644 .changeset/renovate-4775edd.md diff --git a/.changeset/renovate-4775edd.md b/.changeset/renovate-4775edd.md new file mode 100644 index 0000000000..6472fac254 --- /dev/null +++ b/.changeset/renovate-4775edd.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-graphql': patch +--- + +Updated dependency `@graphql-codegen/cli` to `^3.0.0`. +Updated dependency `@graphql-codegen/graphql-modules-preset` to `^3.0.0`. +Updated dependency `@graphql-codegen/typescript` to `^3.0.0`. +Updated dependency `@graphql-codegen/typescript-resolvers` to `^3.0.0`. diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 0a6cff187c..332283c7c6 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -48,10 +48,10 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", - "@graphql-codegen/cli": "^2.3.1", - "@graphql-codegen/graphql-modules-preset": "^2.3.2", - "@graphql-codegen/typescript": "^2.4.2", - "@graphql-codegen/typescript-resolvers": "^2.4.3", + "@graphql-codegen/cli": "^3.0.0", + "@graphql-codegen/graphql-modules-preset": "^3.0.0", + "@graphql-codegen/typescript": "^3.0.0", + "@graphql-codegen/typescript-resolvers": "^3.0.0", "@graphql-tools/schema": "^9.0.0", "msw": "^0.49.0" }, diff --git a/yarn.lock b/yarn.lock index 6b7d97d53c..9a2196787c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5326,10 +5326,10 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" - "@graphql-codegen/cli": ^2.3.1 - "@graphql-codegen/graphql-modules-preset": ^2.3.2 - "@graphql-codegen/typescript": ^2.4.2 - "@graphql-codegen/typescript-resolvers": ^2.4.3 + "@graphql-codegen/cli": ^3.0.0 + "@graphql-codegen/graphql-modules-preset": ^3.0.0 + "@graphql-codegen/typescript": ^3.0.0 + "@graphql-codegen/typescript-resolvers": ^3.0.0 "@graphql-tools/schema": ^9.0.0 apollo-server: ^3.0.0 graphql: ^16.0.0 @@ -10071,17 +10071,17 @@ __metadata: languageName: node linkType: hard -"@graphql-codegen/cli@npm:^2.3.1": - version: 2.16.5 - resolution: "@graphql-codegen/cli@npm:2.16.5" +"@graphql-codegen/cli@npm:^3.0.0": + version: 3.1.0 + resolution: "@graphql-codegen/cli@npm:3.1.0" dependencies: "@babel/generator": ^7.18.13 "@babel/template": ^7.18.10 "@babel/types": ^7.18.13 - "@graphql-codegen/core": ^2.6.8 - "@graphql-codegen/plugin-helpers": ^3.1.2 + "@graphql-codegen/core": ^3.1.0 + "@graphql-codegen/plugin-helpers": ^4.1.0 "@graphql-tools/apollo-engine-loader": ^7.3.6 - "@graphql-tools/code-file-loader": ^7.3.13 + "@graphql-tools/code-file-loader": ^7.3.17 "@graphql-tools/git-loader": ^7.2.13 "@graphql-tools/github-loader": ^7.3.20 "@graphql-tools/graphql-file-loader": ^7.5.0 @@ -10090,7 +10090,7 @@ __metadata: "@graphql-tools/prisma-loader": ^7.2.49 "@graphql-tools/url-loader": ^7.13.2 "@graphql-tools/utils": ^9.0.0 - "@whatwg-node/fetch": ^0.6.0 + "@whatwg-node/fetch": ^0.8.0 chalk: ^4.1.0 chokidar: ^3.5.2 cosmiconfig: ^7.0.0 @@ -10117,105 +10117,105 @@ __metadata: graphql-code-generator: cjs/bin.js graphql-codegen: cjs/bin.js graphql-codegen-esm: esm/bin.js - checksum: d1fdc1a0e678d03995bc7e4927ccd1683b7e50686f13b81d01ad6b295e2033876d05cc71d1d489270d314ac25801a9b82e16aa79982a04e982813854990e4a53 + checksum: 8e445196cb95165c715fbc2656763764c4ac3b15d370abd8b3321cf19a5a93fb66a0a53e38c121b18256f820c536c7a686dd3776ff2e3c7be5b989230503129b languageName: node linkType: hard -"@graphql-codegen/core@npm:^2.6.8": - version: 2.6.8 - resolution: "@graphql-codegen/core@npm:2.6.8" +"@graphql-codegen/core@npm:^3.1.0": + version: 3.1.0 + resolution: "@graphql-codegen/core@npm:3.1.0" dependencies: - "@graphql-codegen/plugin-helpers": ^3.1.1 + "@graphql-codegen/plugin-helpers": ^4.1.0 "@graphql-tools/schema": ^9.0.0 "@graphql-tools/utils": ^9.1.1 - tslib: ~2.4.0 + tslib: ~2.5.0 peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 33a222798fd99adcaf5d6d48fcd6949798a62d7a25e9b2af5b13e4def3de4338e5a743e5ea87661d2b32ae3279e3ad8b555d0e212efe86018088cb85a7d59d6a + checksum: 7ace2b185242d00575b877b0bbb884c66915d246ba17a98c0ab82c2ee3a93ff2c9ae9d7d75a1d346de02ca8f12eb02801ffe2da4846da6e164b43176cd02dd8c languageName: node linkType: hard -"@graphql-codegen/graphql-modules-preset@npm:^2.3.2": - version: 2.5.12 - resolution: "@graphql-codegen/graphql-modules-preset@npm:2.5.12" +"@graphql-codegen/graphql-modules-preset@npm:^3.0.0": + version: 3.1.0 + resolution: "@graphql-codegen/graphql-modules-preset@npm:3.1.0" dependencies: - "@graphql-codegen/plugin-helpers": ^3.1.2 - "@graphql-codegen/visitor-plugin-common": 2.13.8 + "@graphql-codegen/plugin-helpers": ^4.1.0 + "@graphql-codegen/visitor-plugin-common": 3.0.1 "@graphql-tools/utils": ^9.0.0 change-case-all: 1.0.15 parse-filepath: ^1.0.2 - tslib: ~2.4.0 + tslib: ~2.5.0 peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: ca2354d5eb899bca7af2ddb68a1ad96fd046b53c07bb0323478d18e155e0bb988bb6bae4ed1578e37ffb9cb004900e7abb92b4a8b3826b6fe903b422501f8ef2 + checksum: cee2e7f8afbc0b0d81592abfc8894422b791f0eca6e878a789de980bf1710a3c726786ade296e653cc83f920b2618aa9f5c9dbb6934ee9da0122b2d10ef5bdb5 languageName: node linkType: hard -"@graphql-codegen/plugin-helpers@npm:^3.1.1, @graphql-codegen/plugin-helpers@npm:^3.1.2": - version: 3.1.2 - resolution: "@graphql-codegen/plugin-helpers@npm:3.1.2" +"@graphql-codegen/plugin-helpers@npm:^4.1.0": + version: 4.1.0 + resolution: "@graphql-codegen/plugin-helpers@npm:4.1.0" dependencies: "@graphql-tools/utils": ^9.0.0 change-case-all: 1.0.15 common-tags: 1.8.2 import-from: 4.0.0 lodash: ~4.17.0 - tslib: ~2.4.0 + tslib: ~2.5.0 peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 4d0c615738570681b5ffd3c07305a35d6aa3e5fd87c9199c0a670b95529ab865b1df978ce584d5b415107a567ac484e56a48db129a6d1d2eb8a254fbd3260e39 + checksum: a4d89909d7a62bd7a93041b6073b1d46e912b42f7af1d15c44f7ed595ab1185b6c257cccf8272e0ae36ba22724578449d0e21524e8dbc21fb375da0620687868 languageName: node linkType: hard -"@graphql-codegen/schema-ast@npm:^2.6.1": - version: 2.6.1 - resolution: "@graphql-codegen/schema-ast@npm:2.6.1" +"@graphql-codegen/schema-ast@npm:^3.0.1": + version: 3.0.1 + resolution: "@graphql-codegen/schema-ast@npm:3.0.1" dependencies: - "@graphql-codegen/plugin-helpers": ^3.1.2 + "@graphql-codegen/plugin-helpers": ^4.1.0 "@graphql-tools/utils": ^9.0.0 - tslib: ~2.4.0 + tslib: ~2.5.0 peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: f44338ac66e6a1f6238c33cdf65778bb467fe5a93767988135cb4e112d3be4d3c7e8aeeffe323754e8d6b0cbc5a52cb71452bfc42a15bc7031ebaa9b3d5da676 + checksum: 620aa67a4ae59ccb4609763b7347d05e2cec62bf1362be3e1e01fc00969cdbb858398542aa261128e5b5e3cb6808b77861bdcf82662e80326e72b418f25f465f languageName: node linkType: hard -"@graphql-codegen/typescript-resolvers@npm:^2.4.3": - version: 2.7.13 - resolution: "@graphql-codegen/typescript-resolvers@npm:2.7.13" +"@graphql-codegen/typescript-resolvers@npm:^3.0.0": + version: 3.1.0 + resolution: "@graphql-codegen/typescript-resolvers@npm:3.1.0" dependencies: - "@graphql-codegen/plugin-helpers": ^3.1.2 - "@graphql-codegen/typescript": ^2.8.8 - "@graphql-codegen/visitor-plugin-common": 2.13.8 + "@graphql-codegen/plugin-helpers": ^4.1.0 + "@graphql-codegen/typescript": ^3.0.1 + "@graphql-codegen/visitor-plugin-common": 3.0.1 "@graphql-tools/utils": ^9.0.0 auto-bind: ~4.0.0 - tslib: ~2.4.0 + tslib: ~2.5.0 peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 9ddfeb295e55055d450f30942c476edbc05722943d5265e9eaea9f89cef9eecb749be1ece9ce9247d53bdcc7688ca305100327d28096f5fe6aee387cf3f275f5 + checksum: 05888a9dfd1556fe15465a524750c36881334c231297e2e89bccb536450bed61fde2ba182ba4e79e34be846ce2e2439f3f6b31a67e7437f03a4e4ace62e84dcd languageName: node linkType: hard -"@graphql-codegen/typescript@npm:^2.4.2, @graphql-codegen/typescript@npm:^2.8.8": - version: 2.8.8 - resolution: "@graphql-codegen/typescript@npm:2.8.8" +"@graphql-codegen/typescript@npm:^3.0.0, @graphql-codegen/typescript@npm:^3.0.1": + version: 3.0.1 + resolution: "@graphql-codegen/typescript@npm:3.0.1" dependencies: - "@graphql-codegen/plugin-helpers": ^3.1.2 - "@graphql-codegen/schema-ast": ^2.6.1 - "@graphql-codegen/visitor-plugin-common": 2.13.8 + "@graphql-codegen/plugin-helpers": ^4.1.0 + "@graphql-codegen/schema-ast": ^3.0.1 + "@graphql-codegen/visitor-plugin-common": 3.0.1 auto-bind: ~4.0.0 - tslib: ~2.4.0 + tslib: ~2.5.0 peerDependencies: graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: ebc338bc88fd239b9ef70d900778791af2c68f7a0fa074d870cc5fcaee3ea182dfce8a1f366f53bcd5e81f95bb9e26e00e1b41e6b2ad3305cf7e6f44bf57d649 + checksum: 56a369237971cc4a5a4987628ec0fcceed66ec03a292b3d17b6ffb64279185cd085be351268c55be6b152634c430e885b9c584d816aaa25f067d91c6996c329a languageName: node linkType: hard -"@graphql-codegen/visitor-plugin-common@npm:2.13.8": - version: 2.13.8 - resolution: "@graphql-codegen/visitor-plugin-common@npm:2.13.8" +"@graphql-codegen/visitor-plugin-common@npm:3.0.1": + version: 3.0.1 + resolution: "@graphql-codegen/visitor-plugin-common@npm:3.0.1" dependencies: - "@graphql-codegen/plugin-helpers": ^3.1.2 + "@graphql-codegen/plugin-helpers": ^4.1.0 "@graphql-tools/optimize": ^1.3.0 "@graphql-tools/relay-operation-optimizer": ^6.5.0 "@graphql-tools/utils": ^9.0.0 @@ -10224,10 +10224,10 @@ __metadata: dependency-graph: ^0.11.0 graphql-tag: ^2.11.0 parse-filepath: ^1.0.2 - tslib: ~2.4.0 + tslib: ~2.5.0 peerDependencies: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 4ca8074bfb84a7c6f88216c2b327a600b57da35eae9b659656592c48f197e44004dcc5c2ab500a5d3a94e2753f47903e5e113162c8a362de08e307e564d416a5 + checksum: 32bf553f73938581f634b1bbdf8616b1cb30cc85c73d7a8f6088d2a81a957e198c7c278edf6582c1eee7328a4463cea4725316b1743b87b26dc3e9fdd8318648 languageName: node linkType: hard @@ -10273,18 +10273,18 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/code-file-loader@npm:^7.3.13": - version: 7.3.13 - resolution: "@graphql-tools/code-file-loader@npm:7.3.13" +"@graphql-tools/code-file-loader@npm:^7.3.17": + version: 7.3.21 + resolution: "@graphql-tools/code-file-loader@npm:7.3.21" dependencies: - "@graphql-tools/graphql-tag-pluck": 7.4.0 - "@graphql-tools/utils": 9.1.1 + "@graphql-tools/graphql-tag-pluck": 7.5.0 + "@graphql-tools/utils": 9.2.1 globby: ^11.0.3 tslib: ^2.4.0 unixify: ^1.0.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 18eeea4d3a89c15cf74d89630b647b6951487072f70a1b193d39c47b03533d3fe89f3e8f232b604db21b597768802b4884446b9820bf1febbdf1c094924be279 + checksum: 5d0d0a70bac673b4925a65f2283e3fcc5c093d2466a144cc577cb515d3de92ca2458d92842e02fe82a95d57d30ce6d2998b8ee5674393f7cd3df52f69671d565 languageName: node linkType: hard @@ -10448,6 +10448,22 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/graphql-tag-pluck@npm:7.5.0": + version: 7.5.0 + resolution: "@graphql-tools/graphql-tag-pluck@npm:7.5.0" + dependencies: + "@babel/parser": ^7.16.8 + "@babel/plugin-syntax-import-assertions": 7.20.0 + "@babel/traverse": ^7.16.8 + "@babel/types": ^7.16.8 + "@graphql-tools/utils": 9.2.1 + tslib: ^2.4.0 + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 47edaacdeafc4a464f8a51e047cafbb82a9a2700536a5b075eb4afad43c80b513a7b0ac4ad49a1e8a74b566ed7dfd677ebb0d0a967fe1e2ee66408cd5d4f294b + languageName: node + linkType: hard + "@graphql-tools/import@npm:6.7.1": version: 6.7.1 resolution: "@graphql-tools/import@npm:6.7.1" @@ -16384,6 +16400,13 @@ __metadata: languageName: node linkType: hard +"@whatwg-node/events@npm:^0.0.2": + version: 0.0.2 + resolution: "@whatwg-node/events@npm:0.0.2" + checksum: 6d491801d36967d5d62443cca6ef39d41cf882d575839d2e9d1a5f394722cd24ef84fe9e897bb72c01bd198871fda9ff0e8b1ac5aa6f3f814f87d92b7f28fdcc + languageName: node + linkType: hard + "@whatwg-node/fetch@npm:0.5.3, @whatwg-node/fetch@npm:^0.5.0": version: 0.5.3 resolution: "@whatwg-node/fetch@npm:0.5.3" @@ -16417,20 +16440,31 @@ __metadata: languageName: node linkType: hard -"@whatwg-node/fetch@npm:^0.6.0": - version: 0.6.1 - resolution: "@whatwg-node/fetch@npm:0.6.1" +"@whatwg-node/fetch@npm:^0.8.0": + version: 0.8.1 + resolution: "@whatwg-node/fetch@npm:0.8.1" dependencies: "@peculiar/webcrypto": ^1.4.0 - abort-controller: ^3.0.0 + "@whatwg-node/node-fetch": ^0.3.0 busboy: ^1.6.0 - form-data-encoder: ^1.7.1 - formdata-node: ^4.3.1 - node-fetch: ^2.6.7 - undici: ^5.12.0 urlpattern-polyfill: ^6.0.2 - web-streams-polyfill: ^3.2.0 - checksum: 81b469c03e53f49f6a1a2d8059ba28d40b710611e01a60f6396cf95f0d4b48d596c176dccc19876e32b3c67b77b1e72c1053cea05f6417f1c5340150037a3da1 + web-streams-polyfill: ^3.2.1 + checksum: b827ac2299676705d98d31be4b68e70741200618b38daaae0d70e587f61fae573854170e2ca219d64bbd910b96960e26b64aa9869e9194a4d162e2a751d6f7a7 + languageName: node + linkType: hard + +"@whatwg-node/node-fetch@npm:^0.3.0": + version: 0.3.0 + resolution: "@whatwg-node/node-fetch@npm:0.3.0" + dependencies: + "@whatwg-node/events": ^0.0.2 + busboy: ^1.6.0 + fast-querystring: ^1.1.1 + fast-url-parser: ^1.1.3 + tslib: ^2.3.1 + peerDependencies: + "@types/node": ^18.0.6 + checksum: 141deb3f44d1978218c64ca285120b3e2427159773056774f2251f9d5d418c8e1d6f27f4b593d031ff4124f9cd00cb4bd9fd681e4528c9f498c72356a520b69f languageName: node linkType: hard @@ -23099,6 +23133,15 @@ __metadata: languageName: node linkType: hard +"fast-querystring@npm:^1.1.1": + version: 1.1.1 + resolution: "fast-querystring@npm:1.1.1" + dependencies: + fast-decode-uri-component: ^1.0.1 + checksum: 86d2b75b9b299a552353532fb1a542f09730ee2a61e657d68710971d9a2afc9a3c5c7b7e106b6534f4cc506d2ff1c08ab0fda4ae614b4e7720798c9ac2a88e02 + languageName: node + linkType: hard + "fast-redact@npm:^2.0.0": version: 2.1.0 resolution: "fast-redact@npm:2.1.0" @@ -23127,7 +23170,7 @@ __metadata: languageName: node linkType: hard -"fast-url-parser@npm:1.1.3": +"fast-url-parser@npm:1.1.3, fast-url-parser@npm:^1.1.3": version: 1.1.3 resolution: "fast-url-parser@npm:1.1.3" dependencies: @@ -37414,7 +37457,14 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:~2.4.0": +"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:~2.5.0": + version: 2.5.0 + resolution: "tslib@npm:2.5.0" + checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1 + languageName: node + linkType: hard + +"tslib@npm:~2.4.0": version: 2.4.1 resolution: "tslib@npm:2.4.1" checksum: 19480d6e0313292bd6505d4efe096a6b31c70e21cf08b5febf4da62e95c265c8f571f7b36fcc3d1a17e068032f59c269fab3459d6cd3ed6949eafecf64315fca @@ -38529,7 +38579,7 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:^3.2.0": +"web-streams-polyfill@npm:^3.2.0, web-streams-polyfill@npm:^3.2.1": version: 3.2.1 resolution: "web-streams-polyfill@npm:3.2.1" checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02 From 6e612b58577e0e9a7ae439d185459e67bd78e0dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 22 Feb 2023 16:31:25 +0100 Subject: [PATCH 408/417] Move backend-defaults to devDependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/tricky-jars-film.md | 5 +++++ .../package.json | 2 +- .../catalog-backend-module-incremental-ingestion/src/run.ts | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/tricky-jars-film.md diff --git a/.changeset/tricky-jars-film.md b/.changeset/tricky-jars-film.md new file mode 100644 index 0000000000..9533634614 --- /dev/null +++ b/.changeset/tricky-jars-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +Move `@backstage/backend-defaults` to `devDependencies` diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 326f4d7bec..e3f6be3a88 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -46,7 +46,6 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", - "@backstage/backend-defaults": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", "@backstage/catalog-model": "workspace:^", @@ -68,6 +67,7 @@ }, "devDependencies": { "@backstage/backend-app-api": "workspace:^", + "@backstage/backend-defaults": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^" diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index c94af368d1..f1b6bd1529 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// Think this file will probably go away once we move to backend system +// And restructure into the /dev folder +// eslint-disable-next-line @backstage/no-undeclared-imports import { createBackend } from '@backstage/backend-defaults'; import { coreServices, From 8e465ce52e2aca70e6023163ab264fea6e33aa5b Mon Sep 17 00:00:00 2001 From: Morgan Bentell Date: Wed, 22 Feb 2023 17:18:35 +0100 Subject: [PATCH 409/417] print the mkdocs output when running the generate command with the --verbose flag Signed-off-by: Morgan Bentell --- .changeset/quick-coats-sneeze.md | 5 +++++ .../src/commands/generate/generate.ts | 4 ++-- packages/techdocs-cli/src/lib/utility.ts | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 .changeset/quick-coats-sneeze.md diff --git a/.changeset/quick-coats-sneeze.md b/.changeset/quick-coats-sneeze.md new file mode 100644 index 0000000000..24f7f70e83 --- /dev/null +++ b/.changeset/quick-coats-sneeze.md @@ -0,0 +1,5 @@ +--- +'@techdocs/cli': minor +--- + +Running `@techdocs/cli generate` with the `--verbose` flag will now print the mkdocs output. diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index b8ad466bb3..5d80beb38a 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -31,8 +31,8 @@ import { ConfigReader } from '@backstage/config'; import { convertTechDocsRefToLocationAnnotation, createLogger, + getLogStream, } from '../../lib/utility'; -import { stdout } from 'process'; export default async function generate(opts: OptionValues) { // Use techdocs-node package to generate docs. Keep consistency between Backstage and CI generating docs. @@ -110,7 +110,7 @@ export default async function generate(opts: OptionValues) { : {}), logger, etag: opts.etag, - ...(process.env.LOG_LEVEL === 'debug' ? { logStream: stdout } : {}), + logStream: getLogStream(logger), siteOptions: { name: opts.siteName }, }); diff --git a/packages/techdocs-cli/src/lib/utility.ts b/packages/techdocs-cli/src/lib/utility.ts index 3f91f3c82d..00927fd1df 100644 --- a/packages/techdocs-cli/src/lib/utility.ts +++ b/packages/techdocs-cli/src/lib/utility.ts @@ -18,6 +18,8 @@ import { ParsedLocationAnnotation, } from '@backstage/plugin-techdocs-node'; import * as winston from 'winston'; +import { Writable } from 'stream'; +import { stdout } from 'process'; export const convertTechDocsRefToLocationAnnotation = ( techdocsRef: string, @@ -52,3 +54,17 @@ export const createLogger = ({ return logger; }; + +export const getLogStream = (logger: winston.Logger): Writable => { + if (process.env.LOG_LEVEL === 'debug') { + return stdout; + } + + return new Writable({ + defaultEncoding: 'utf8', + write(chunk, _encoding, next) { + logger.verbose(chunk.toString().trim()); + next(); + }, + }); +}; From 1ad8d885d30bd1975a202818d3b8b83448587f4c Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 22 Feb 2023 18:42:00 +0100 Subject: [PATCH 410/417] cli: fix local dev entry points Signed-off-by: Patrik Oldsberg --- .changeset/cool-clocks-prove.md | 5 +++++ packages/cli/src/lib/bundler/config.ts | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 .changeset/cool-clocks-prove.md diff --git a/.changeset/cool-clocks-prove.md b/.changeset/cool-clocks-prove.md new file mode 100644 index 0000000000..dfd7b8c5eb --- /dev/null +++ b/.changeset/cool-clocks-prove.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fixed a bug where additional backend package entry points where not properly marked as internal during local development. diff --git a/packages/cli/src/lib/bundler/config.ts b/packages/cli/src/lib/bundler/config.ts index ce216f5c59..a6d757028f 100644 --- a/packages/cli/src/lib/bundler/config.ts +++ b/packages/cli/src/lib/bundler/config.ts @@ -15,7 +15,7 @@ */ import fs from 'fs-extra'; -import { resolve as resolvePath } from 'path'; +import { resolve as resolvePath, join as joinPath } from 'path'; import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import ModuleScopePlugin from 'react-dev-utils/ModuleScopePlugin'; @@ -36,6 +36,8 @@ import { runPlain } from '../run'; import ESLintPlugin from 'eslint-webpack-plugin'; import pickBy from 'lodash/pickBy'; import yn from 'yn'; +import { readEntryPoints } from '../monorepo/entryPoints'; +import { ExtendedPackage } from '../monorepo'; const BUILD_CACHE_ENV_VAR = 'BACKSTAGE_CLI_EXPERIMENTAL_BUILD_CACHE'; @@ -232,7 +234,10 @@ export async function createBackendConfig( // Find all local monorepo packages and their node_modules, and mark them as external. const { packages } = await getPackages(cliPaths.targetDir); - const localPackageNames = packages.map(p => p.packageJson.name); + const localPackageEntryPoints = packages.flatMap(p => { + const entryPoints = readEntryPoints((p as ExtendedPackage).packageJson); + return entryPoints.map(e => joinPath(p.packageJson.name, e.mount)); + }); const moduleDirs = packages.map(p => resolvePath(p.dir, 'node_modules')); // See frontend config const externalPkgs = packages.filter(p => !isChildPath(paths.root, p.dir)); @@ -261,7 +266,7 @@ export async function createBackendConfig( nodeExternalsWithResolve({ modulesDir: paths.rootNodeModules, additionalModuleDirs: moduleDirs, - allowlist: ['webpack/hot/poll?100', ...localPackageNames], + allowlist: ['webpack/hot/poll?100', ...localPackageEntryPoints], }), ], target: 'node' as const, From f79bafb844215b05b7fbe87ab76274f9c39b2e67 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 23 Feb 2023 10:27:53 +0100 Subject: [PATCH 411/417] chore: fix doscird links Signed-off-by: blam --- .github/ISSUE_TEMPLATE/config.yml | 2 +- CONTRIBUTING.md | 2 +- README.md | 4 ++-- app-config.yaml | 2 +- docs/FAQ.md | 2 +- docs/dls/design.md | 12 ++++++------ .../migrating-from-v1beta2-to-v1beta3.md | 2 +- docs/getting-started/configuration.md | 2 +- docs/getting-started/index.md | 2 +- docs/getting-started/running-backstage-locally.md | 2 +- docs/overview/roadmap.md | 2 +- docs/overview/support.md | 2 +- docs/overview/what-is-backstage.md | 2 +- docs/releases/v1.0.0.md | 2 +- docs/releases/v1.1.0.md | 2 +- docs/releases/v1.10.0.md | 2 +- docs/releases/v1.11.0.md | 2 +- docs/releases/v1.2.0.md | 2 +- docs/releases/v1.3.0.md | 2 +- docs/releases/v1.4.0.md | 2 +- docs/releases/v1.5.0.md | 2 +- docs/releases/v1.6.0.md | 2 +- docs/releases/v1.7.0.md | 2 +- docs/releases/v1.8.0.md | 2 +- docs/releases/v1.9.0.md | 2 +- microsite-next/docusaurus.config.js | 2 +- microsite-next/src/pages/community/index.tsx | 2 +- microsite/blog/2020-03-18-what-is-backstage.md | 2 +- .../2020-04-30-how-to-quickly-set-up-backstage.md | 2 +- .../2020-06-22-backstage-service-catalog-alpha.md | 2 +- ...-08-05-announcing-backstage-software-templates.md | 2 +- ...ackstage-feature-kubernetes-for-service-owners.md | 2 +- .../blog/2021-06-22-spotify-backstage-is-growing.md | 2 +- ...021-06-24-announcing-backstage-search-platform.md | 2 +- .../blog/2021-09-16-the-techdocs-beta-has-landed.md | 2 +- .../blog/2022-03-04-backstage-upgrade-helper.md | 2 +- microsite/blog/2022-03-17-backstage-1.0.md | 2 +- microsite/blog/2022-12-19-backstage-wrapped-2022.md | 2 +- microsite/core/Footer.js | 4 +++- microsite/pages/en/community.js | 4 +++- microsite/pages/en/live.js | 4 +++- plugins/pagerduty/README.md | 2 +- 42 files changed, 54 insertions(+), 48 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e9f23287b7..e4b99b3be1 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -6,7 +6,7 @@ contact_links: url: 'https://github.com/backstage/backstage/discussions' - about: 'Alternatively, you can use the Backstage Community Discord' name: Chat - url: 'https://discord.gg/MUpMjP2' + url: 'https://discord.gg/backstage-687207715902193673' - about: 'Please check the FAQ before filing new issues' name: 'Backstage FAQ' url: 'https://backstage.io/docs/FAQ' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e22fbf29a4..c2df005a1c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,7 +72,7 @@ Have you started using Backstage? Adding your company to [ADOPTERS](ADOPTERS.md) So...feel ready to jump in? Let's do this. 👏🏻💯 -Start by reading our [Getting Started for Contributors](https://backstage.io/docs/getting-started/contributors) page to get yourself setup with a fresh copy of Backstage ready for your contributions. If you need help, just jump into our [Discord chatroom](https://discord.gg/MUpMjP2). +Start by reading our [Getting Started for Contributors](https://backstage.io/docs/getting-started/contributors) page to get yourself setup with a fresh copy of Backstage ready for your contributions. If you need help, just jump into our [Discord chatroom](https://discord.gg/backstage-687207715902193673). ## Coding Guidelines diff --git a/README.md b/README.md index 8a2bd338d9..60324a7789 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![CNCF Status](https://img.shields.io/badge/cncf%20status-incubation-blue.svg)](https://www.cncf.io/projects) [![Main CI Build](https://github.com/backstage/backstage/workflows/Main%20Master%20Build/badge.svg)](https://github.com/backstage/backstage/actions?query=workflow%3A%22Main+Master+Build%22) -[![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.gg/EBHEGzX) +[![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.gg/backstage-687207715902193673) ![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg) [![Codecov](https://img.shields.io/codecov/c/github/backstage/backstage)](https://codecov.io/gh/backstage/backstage) [![](https://img.shields.io/github/v/release/backstage/backstage)](https://github.com/backstage/backstage/releases) @@ -45,7 +45,7 @@ Check out [the documentation](https://backstage.io/docs/getting-started) on how ## Community -- [Discord chatroom](https://discord.gg/MUpMjP2) - Get support or discuss the project +- [Discord chatroom](https://discord.gg/backstage-687207715902193673) - Get support or discuss the project - [Contributing to Backstage](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md) - Start here if you want to contribute - [RFCs](https://github.com/backstage/backstage/labels/rfc) - Help shape the technical direction - [FAQ](https://backstage.io/docs/FAQ) - Frequently Asked Questions diff --git a/app-config.yaml b/app-config.yaml index c97adec5ef..22f3f4c9c5 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -17,7 +17,7 @@ app: - title: Discord Chatroom icon: chat links: - - url: https://discord.gg/MUpMjP2 + - url: https://discord.gg/backstage-687207715902193673 title: '#backstage' backend: diff --git a/docs/FAQ.md b/docs/FAQ.md index fcd5542f74..5b93f07d78 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -231,7 +231,7 @@ We take security seriously. When it comes to packages and code we scan our repositories periodically and update our packages to the latest versions. When it comes to deployment of Backstage within an organisation it depends on the deployment and security setup in your organisation. Reach out to us on -[Discord](https://discord.gg/MUpMjP2) if you have specific queries. +[Discord](https://discord.gg/backstage-687207715902193673) if you have specific queries. Please report sensitive security issues via Spotify's [bug-bounty program](https://hackerone.com/spotify) rather than GitHub. diff --git a/docs/dls/design.md b/docs/dls/design.md index a2091aeb10..3444ff3ad2 100644 --- a/docs/dls/design.md +++ b/docs/dls/design.md @@ -26,7 +26,7 @@ that growth, check out the issues in this GitHub repo! The Backstage Design Team is small but mighty, and we truly cherish the amazing opportunity we have to work with the Backstage Open Source community! Have an idea? A component request? Feel free to communicate with us via -[Discord](https://discord.gg/EBHEGzX) (_#design_ channel). Collaboration trumps +[Discord](https://discord.gg/backstage-687207715902193673) (_#design_ channel). Collaboration trumps individual speed, and we want to work with you to make Backstage work for all of our users. @@ -38,7 +38,7 @@ loop! Keep an eye on our where we're headed and review the [open design issues](https://github.com/backstage/backstage/issues?q=is%3Aopen+is%3Aissue+label%3Adesign), to see if you can help. We'll also be posting updates in the _#design_ channel -on [Discord](https://discord.gg/EBHEGzX). Not only that, we want to keep you +on [Discord](https://discord.gg/backstage-687207715902193673). Not only that, we want to keep you informed on the decisions we've made and why we've made them. ## 🛠 Our Practice @@ -101,14 +101,14 @@ focused on building up our core Backstage user experience. We’ll be labeling o issues in GitHub with ‘design’ and/or ‘storybook’ - so feel free to browse and tackle the tasks that interest you. If you have any questions regarding an issue, you can ask them in the comments section of the issue or on -[Discord](https://discord.gg/EBHEGzX). We absolutely adore our external +[Discord](https://discord.gg/backstage-687207715902193673). We absolutely adore our external contributors and will send you virtual [semlas](https://en.wikipedia.org/wiki/Semla) for your contributions! ### Request a component Create an issue (label it design and assign it to katz95) or send us a message -on [Discord](https://discord.gg/EBHEGzX) (_#design_ channel) with details of +on [Discord](https://discord.gg/backstage-687207715902193673) (_#design_ channel) with details of what the component is and its relevant use cases. Your request will be reviewed by our design team and you should hear back from us within 1-2 business days. We’ll get back to you and let you know whether your requested component will get @@ -124,7 +124,7 @@ components we’ve designed to the Storybook as well. Community to share our design assets. You can duplicate our UI Kit and design your own plugin for Backstage. -**[Discord](https://discord.gg/EBHEGzX)** - all design questions should be +**[Discord](https://discord.gg/backstage-687207715902193673)** - all design questions should be directed to the _#design_ channel. **[Customize Backstage's look and feel](https://backstage.io/docs/getting-started/app-custom-theme)** - @@ -142,4 +142,4 @@ scenes, we’re setting up a few foundational elements to make sure that contributing to Backstage as a designer is easy. From styling guidelines to UX principles to Figma documents, we’ll make sure you’re equipped to chip in on this project. We’re excited to work with you! In the meantime, we’d love to hear -from you on [Discord](https://discord.gg/EBHEGzX). +from you on [Discord](https://discord.gg/backstage-687207715902193673). diff --git a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md index 6e37a4df3e..f9d2c4eb0c 100644 --- a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md +++ b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md @@ -211,7 +211,7 @@ input: ### Summary -Of course, we're always available on [discord](https://discord.gg/MUpMjP2) if +Of course, we're always available on [discord](https://discord.gg/backstage-687207715902193673) if you're stuck or something's not working as expected. You can also [raise an issue](https://github.com/backstage/backstage/issues/new/choose) with feedback or bugs! diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index 1c25606ac3..a436321fe2 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -299,7 +299,7 @@ Achievement unlocked. You've set up an installation of the core Backstage App, made it persistent, and configured it so you are now able to use software templates. -Let us know how your experience was: [on discord](https://discord.gg/EBHEGzX), +Let us know how your experience was: [on discord](https://discord.gg/backstage-687207715902193673), file issues for any [feature](https://github.com/backstage/backstage/issues/new?labels=help+wanted&template=feature_template.md) or diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index c3d6b21923..2617cfb654 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -83,7 +83,7 @@ database, configure authentication, and add your first integration. Continue with [getting started: Configuring Backstage](configuration.md). Share your experiences, comments, or suggestions with us: -[on discord](https://discord.gg/EBHEGzX), file issues for any +[on discord](https://discord.gg/backstage-687207715902193673), file issues for any [feature](https://github.com/backstage/backstage/issues/new?labels=help+wanted&template=feature_template.md) or [plugin suggestions](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME), diff --git a/docs/getting-started/running-backstage-locally.md b/docs/getting-started/running-backstage-locally.md index e7e96316f4..d56bdf7990 100644 --- a/docs/getting-started/running-backstage-locally.md +++ b/docs/getting-started/running-backstage-locally.md @@ -86,7 +86,7 @@ option will be GitHub. To setup GitHub authentication in Backstage, see --- Congratulations! That should be it. Let us know how it went -[on discord](https://discord.gg/EBHEGzX), file issues for any +[on discord](https://discord.gg/backstage-687207715902193673), file issues for any [feature](https://github.com/backstage/backstage/issues/new?labels=help+wanted&template=feature_template.md) or [plugin suggestions](https://github.com/backstage/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME), diff --git a/docs/overview/roadmap.md b/docs/overview/roadmap.md index 2ac211bf97..8e3d73ded6 100644 --- a/docs/overview/roadmap.md +++ b/docs/overview/roadmap.md @@ -111,4 +111,4 @@ guidelines to get started. If you have specific questions about the roadmap, please create an [issue](https://github.com/backstage/backstage/issues/new/choose), ping us on -[Discord](https://discord.gg/qxsEfa8Vq8), or [book time](https://info.backstage.spotify.com/office-hours) with the Spotify team. +[Discord](https://discord.gg/backstage-687207715902193673), or [book time](https://info.backstage.spotify.com/office-hours) with the Spotify team. diff --git a/docs/overview/support.md b/docs/overview/support.md index 662a37c6ae..a0444c4d34 100644 --- a/docs/overview/support.md +++ b/docs/overview/support.md @@ -4,7 +4,7 @@ title: Support and community description: Support and Community Details and Links --- -- [Discord chatroom](https://discord.gg/MUpMjP2) - Get support or discuss the +- [Discord chatroom](https://discord.gg/backstage-687207715902193673) - Get support or discuss the project. - [Stack Overflow](https://stackoverflow.com/questions/tagged/backstage) - Browse or ask questions on Stack Overflow. - [Good First Issues](https://github.com/backstage/backstage/contribute) - Start diff --git a/docs/overview/what-is-backstage.md b/docs/overview/what-is-backstage.md index 38b67e81de..b5e5ad48b6 100644 --- a/docs/overview/what-is-backstage.md +++ b/docs/overview/what-is-backstage.md @@ -61,4 +61,4 @@ Backstage is a CNCF Incubation project after graduating from Sandbox. Read the a administrators together in one place. If you have questions or want support, please join our -[Discord chatroom](https://discord.gg/EBHEGzX). +[Discord chatroom](https://discord.gg/backstage-687207715902193673). diff --git a/docs/releases/v1.0.0.md b/docs/releases/v1.0.0.md index 44a4f48213..6906ef8ae7 100644 --- a/docs/releases/v1.0.0.md +++ b/docs/releases/v1.0.0.md @@ -85,7 +85,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/releases/tag/v1.0.0) for this release - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.1.0.md b/docs/releases/v1.1.0.md index 0417423247..daf31a536f 100644 --- a/docs/releases/v1.1.0.md +++ b/docs/releases/v1.1.0.md @@ -63,7 +63,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.1.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.10.0.md b/docs/releases/v1.10.0.md index 93ab357370..b06ab63747 100644 --- a/docs/releases/v1.10.0.md +++ b/docs/releases/v1.10.0.md @@ -71,7 +71,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.10.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.11.0.md b/docs/releases/v1.11.0.md index e385bfead5..1afed5fbb6 100644 --- a/docs/releases/v1.11.0.md +++ b/docs/releases/v1.11.0.md @@ -93,7 +93,7 @@ Below you can find a list of links and references to help you learn about and st - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.11.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.2.0.md b/docs/releases/v1.2.0.md index b2d50a09a2..3751217ae4 100644 --- a/docs/releases/v1.2.0.md +++ b/docs/releases/v1.2.0.md @@ -60,7 +60,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.2.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.3.0.md b/docs/releases/v1.3.0.md index 8014e0a121..96aa88a05e 100644 --- a/docs/releases/v1.3.0.md +++ b/docs/releases/v1.3.0.md @@ -58,7 +58,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.3.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap), and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.4.0.md b/docs/releases/v1.4.0.md index 20b1739f4a..9a178ea8ff 100644 --- a/docs/releases/v1.4.0.md +++ b/docs/releases/v1.4.0.md @@ -63,7 +63,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.4.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.5.0.md b/docs/releases/v1.5.0.md index ca4ae11185..d7bbfa62a2 100644 --- a/docs/releases/v1.5.0.md +++ b/docs/releases/v1.5.0.md @@ -53,7 +53,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.5.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.6.0.md b/docs/releases/v1.6.0.md index a1ece6bf94..417491c1e4 100644 --- a/docs/releases/v1.6.0.md +++ b/docs/releases/v1.6.0.md @@ -53,7 +53,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.6.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.7.0.md b/docs/releases/v1.7.0.md index cb87ead4c9..56eda8b20d 100644 --- a/docs/releases/v1.7.0.md +++ b/docs/releases/v1.7.0.md @@ -114,7 +114,7 @@ start using this new release. - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.7.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), diff --git a/docs/releases/v1.8.0.md b/docs/releases/v1.8.0.md index cbe16a0cba..78cc5ab7cd 100644 --- a/docs/releases/v1.8.0.md +++ b/docs/releases/v1.8.0.md @@ -71,7 +71,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.8.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/docs/releases/v1.9.0.md b/docs/releases/v1.9.0.md index 53a1769108..a677acb643 100644 --- a/docs/releases/v1.9.0.md +++ b/docs/releases/v1.9.0.md @@ -78,7 +78,7 @@ Below you can find a list of links and references to help you learn about and st - [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) - [GitHub repository](https://github.com/backstage/backstage) - Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) -- [Community Discord](https://discord.gg/bFESRKVt) for discussions and support +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support - [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.9.0-changelog.md) - Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) diff --git a/microsite-next/docusaurus.config.js b/microsite-next/docusaurus.config.js index 73171e65ea..c3956bb308 100644 --- a/microsite-next/docusaurus.config.js +++ b/microsite-next/docusaurus.config.js @@ -187,7 +187,7 @@ module.exports = { items: [ { label: 'Support chatroom', - to: 'https://discord.gg/MUpMjP2', + to: 'https://discord.gg/backstage-687207715902193673', }, { label: 'Contributing', diff --git a/microsite-next/src/pages/community/index.tsx b/microsite-next/src/pages/community/index.tsx index a6dbf8432b..d334b04ee2 100644 --- a/microsite-next/src/pages/community/index.tsx +++ b/microsite-next/src/pages/community/index.tsx @@ -24,7 +24,7 @@ const Community = () => { { content: 'Chat and get support on our', label: 'Discord', - link: 'https://discord.gg/MUpMjP2', + link: 'https://discord.gg/backstage-687207715902193673', }, { content: 'Get into contributing with the', diff --git a/microsite/blog/2020-03-18-what-is-backstage.md b/microsite/blog/2020-03-18-what-is-backstage.md index 2c2b81d64d..5e3ec4ac90 100644 --- a/microsite/blog/2020-03-18-what-is-backstage.md +++ b/microsite/blog/2020-03-18-what-is-backstage.md @@ -85,4 +85,4 @@ We are envisioning [three phases](https://github.com/backstage/backstage/milesto https://github.com/backstage/backstage/milestones -Want to discuss the project or need support? Join us on [Discord](https://discord.gg/MUpMjP2) or reach out on [backstage-interest@spotify.com](mailto:backstage-interest@spotify.com). +Want to discuss the project or need support? Join us on [Discord](https://discord.gg/backstage-687207715902193673) or reach out on [backstage-interest@spotify.com](mailto:backstage-interest@spotify.com). diff --git a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md index 17f095f1fb..7d5098a721 100644 --- a/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md +++ b/microsite/blog/2020-04-30-how-to-quickly-set-up-backstage.md @@ -125,4 +125,4 @@ If you are developing a plugin that might be useful for others, consider releasi ## Ready to get started? -Head over to GitHub and check out the [project](https://github.com/backstage/backstage) or download our [CLI](https://www.npmjs.com/package/@backstage/cli). If you have more questions, join us on [Discord](https://discord.gg/MUpMjP2) or [create an issue](https://github.com/backstage/backstage/issues/new/choose). +Head over to GitHub and check out the [project](https://github.com/backstage/backstage) or download our [CLI](https://www.npmjs.com/package/@backstage/cli). If you have more questions, join us on [Discord](https://discord.gg/backstage-687207715902193673) or [create an issue](https://github.com/backstage/backstage/issues/new/choose). diff --git a/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md b/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md index 7f8fe01e11..0f324cd5be 100644 --- a/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md +++ b/microsite/blog/2020-06-22-backstage-service-catalog-alpha.md @@ -49,6 +49,6 @@ Alpha is our shorthand for "we don’t yet think Backstage is ready for producti As with most alpha releases, you should expect things to change quite a lot until we reach the beta stage (we’re targeting the end of summer). There are obviously many things missing as well, but we wanted to start collecting feedback early and make it easier to see the end-to-end flow. -If you have feedback or questions, please open a [GitHub issue](https://github.com/backstage/backstage/issues), ping us on [Discord chat](https://discord.gg/EBHEGzX) or send us an email at [backstage-interest@spotify.com](mailto:backstage-interest@spotify.com) 🙏 +If you have feedback or questions, please open a [GitHub issue](https://github.com/backstage/backstage/issues), ping us on [Discord chat](https://discord.gg/backstage-687207715902193673) or send us an email at [backstage-interest@spotify.com](mailto:backstage-interest@spotify.com) 🙏 To get regular product updates and news about the Backstage community, sign up for the [Backstage newsletter](https://info.backstage.spotify.com/newsletter_subscribe). diff --git a/microsite/blog/2020-08-05-announcing-backstage-software-templates.md b/microsite/blog/2020-08-05-announcing-backstage-software-templates.md index 18bfa64c19..6acefa571c 100644 --- a/microsite/blog/2020-08-05-announcing-backstage-software-templates.md +++ b/microsite/blog/2020-08-05-announcing-backstage-software-templates.md @@ -73,6 +73,6 @@ Backstage ships with four example templates, but since these are likely not the We have learned that one of the keys to getting these standards adopted is to keep an open process. Templates are code. By making it clear to your engineers that you are open to pull requests, and that teams with different needs can add their own templates, you are on the path of striking a good balance between autonomy and standardization. -If you have feedback or questions, please open a [GitHub issue](https://github.com/backstage/backstage/issues), ping us on [Discord chat](https://discord.gg/EBHEGzX) or send us an email at [backstage-interest@spotify.com](mailto:backstage-interest@spotify.com) 🙏 +If you have feedback or questions, please open a [GitHub issue](https://github.com/backstage/backstage/issues), ping us on [Discord chat](https://discord.gg/backstage-687207715902193673) or send us an email at [backstage-interest@spotify.com](mailto:backstage-interest@spotify.com) 🙏 To get regular product updates and news about the Backstage community, sign up for the [Backstage newsletter](https://info.backstage.spotify.com/newsletter_subscribe). diff --git a/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md b/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md index 8981f276be..7b0686aae7 100644 --- a/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md +++ b/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.md @@ -70,4 +70,4 @@ To contribute or get more information on Kubernetes in Backstage, [join the disc [here]: https://github.com/backstage/backstage/issues?q=is%3Aissue+is%3Aopen+kubernetes+label%3Ak8s-plugin [read the docs]: https://backstage.io/docs/features/kubernetes/overview -[join the discussion on discord]: https://discord.gg/MUpMjP2 +[join the discussion on discord]: https://discord.gg/backstage-687207715902193673 diff --git a/microsite/blog/2021-06-22-spotify-backstage-is-growing.md b/microsite/blog/2021-06-22-spotify-backstage-is-growing.md index a12ddf7443..35285c5e04 100644 --- a/microsite/blog/2021-06-22-spotify-backstage-is-growing.md +++ b/microsite/blog/2021-06-22-spotify-backstage-is-growing.md @@ -49,7 +49,7 @@ We’ve launched a new website at: [backstage.spotify.com](https://backstage.spo You’ll find a high-level introduction to the platform, tips and tricks tested by Spotify to accelerate developer effectiveness, and access to a group of partners that have scaled Backstage for numerous adopters. You can also use the site to book product overviews, demos, and technical deep dives with members of the Spotify team. -We will continue to post important product announcements, technical documentation, feature demos, and community news here on Backstage.io. ([Subscribe to the newsletter](https://info.backstage.spotify.com/newsletter_subscribe) to stay up to date.) And both contributors and adopting companies can continue to find around-the-clock/around-the-world technical support on [GitHub](https://github.com/backstage/backstage) and [Discord](https://discord.gg/MUpMjP2). +We will continue to post important product announcements, technical documentation, feature demos, and community news here on Backstage.io. ([Subscribe to the newsletter](https://info.backstage.spotify.com/newsletter_subscribe) to stay up to date.) And both contributors and adopting companies can continue to find around-the-clock/around-the-world technical support on [GitHub](https://github.com/backstage/backstage) and [Discord](https://discord.gg/backstage-687207715902193673). ## Separate community sessions for adopters and contributors diff --git a/microsite/blog/2021-06-24-announcing-backstage-search-platform.md b/microsite/blog/2021-06-24-announcing-backstage-search-platform.md index 6914077522..118ac1f43c 100644 --- a/microsite/blog/2021-06-24-announcing-backstage-search-platform.md +++ b/microsite/blog/2021-06-24-announcing-backstage-search-platform.md @@ -99,4 +99,4 @@ We’ve built the foundation for the Backstage Search platform, and we can't wai You can check out our [project roadmap](https://backstage.io/docs/features/search/search-overview#project-roadmap) in our search documentation or track the progress of our [Beta milestone](https://github.com/backstage/backstage/milestone/27) and [GA milestone](https://github.com/backstage/backstage/milestone/28). -For any questions, feedback or ideas about the Backstage Search platform, join us in the #search channel on [Discord](https://discord.gg/MUpMjP2)! +For any questions, feedback or ideas about the Backstage Search platform, join us in the #search channel on [Discord](https://discord.gg/backstage-687207715902193673)! diff --git a/microsite/blog/2021-09-16-the-techdocs-beta-has-landed.md b/microsite/blog/2021-09-16-the-techdocs-beta-has-landed.md index f3f79abf44..27df0b3a44 100644 --- a/microsite/blog/2021-09-16-the-techdocs-beta-has-landed.md +++ b/microsite/blog/2021-09-16-the-techdocs-beta-has-landed.md @@ -61,4 +61,4 @@ If you're upgrading from a prior, alpha version of TechDocs, be aware that there - If you've configured TechDocs to publish generated content to a remote storage solution provider like AWS S3, Google Cloud Storage, or Azure Blob Storage, you will need to use the TechDocs CLI to migrate the contents of your storage bucket. [See full migration instructions here](https://backstage.io/docs/features/techdocs/how-to-guides#how-to-migrate-from-techdocs-alpha-to-beta). - In order to take advantage of the stale file deletion functionality, you may need to add some permissions to the account or role used by your TechDocs backend to publish contents to your storage provider. [See "Using Cloud Storage docs"](https://backstage.io/docs/features/techdocs/using-cloud-storage) for updated permissions recommendations. -Thanks again to the whole community for hitting this milestone with us! Catch us in [Discord](https://discord.gg/MUpMjP2) or an [upcoming community session](https://github.com/backstage/community) if you have any questions. +Thanks again to the whole community for hitting this milestone with us! Catch us in [Discord](https://discord.gg/backstage-687207715902193673) or an [upcoming community session](https://github.com/backstage/community) if you have any questions. diff --git a/microsite/blog/2022-03-04-backstage-upgrade-helper.md b/microsite/blog/2022-03-04-backstage-upgrade-helper.md index 80b3b9c0a8..3f4fc6da77 100644 --- a/microsite/blog/2022-03-04-backstage-upgrade-helper.md +++ b/microsite/blog/2022-03-04-backstage-upgrade-helper.md @@ -13,7 +13,7 @@ _TLDR;_ The Spotify team recently announced [Backstage Upgrade Helper](https://b ## Upgrading Backstage was a common pain point -Without a doubt, one of the most exciting things about Backstage is our community. Step into our daily [Discord conversations](https://discord.gg/sBEF5VkG) and the monthly [Community Sessions](https://www.youtube.com/watch?v=0QMQYSTKAx0) and you’ll find a ton of great ideas, problem-solving, and support for one another. +Without a doubt, one of the most exciting things about Backstage is our community. Step into our daily [Discord conversations](https://discord.gg/backstage-687207715902193673) and the monthly [Community Sessions](https://www.youtube.com/watch?v=0QMQYSTKAx0) and you’ll find a ton of great ideas, problem-solving, and support for one another. During one of these discussions, we realized we all shared the same pain point — upgrading a Backstage application. diff --git a/microsite/blog/2022-03-17-backstage-1.0.md b/microsite/blog/2022-03-17-backstage-1.0.md index 02ead0390c..8cc627c127 100644 --- a/microsite/blog/2022-03-17-backstage-1.0.md +++ b/microsite/blog/2022-03-17-backstage-1.0.md @@ -54,6 +54,6 @@ If you want to know more about this first major release, check out the following - [Release notes](https://backstage.io/docs/releases/v1.0.0) and [Changelog](https://github.com/backstage/backstage/releases/tag/v1.0.0). - [Backstage official documentation](https://backstage.io/docs/) and [backstage.spotify.com](https://backstage.spotify.com/). -- [Discord channel](https://discord.gg/EUaBAS58). +- [Discord channel](https://discord.gg/backstage-687207715902193673). - [Backstage repository on GitHub](https://github.com/backstage/backstage). - [List of public adopters](https://github.com/backstage/backstage/blob/master/ADOPTERS.md). diff --git a/microsite/blog/2022-12-19-backstage-wrapped-2022.md b/microsite/blog/2022-12-19-backstage-wrapped-2022.md index 967bc14433..4986b3effd 100644 --- a/microsite/blog/2022-12-19-backstage-wrapped-2022.md +++ b/microsite/blog/2022-12-19-backstage-wrapped-2022.md @@ -20,7 +20,7 @@ Last year we celebrated 75 [public adopters](https://github.com/backstage/backst ![Accelerated growth of Public Backstage Adopters, from January 2021–December 2022.](assets/2022-12-19/public-backstage-adopters-2022.png) -Not only are our adopters growing at an exponential rate, but so too are our contributors. Our [Discord server](https://discord.gg/backstage-687207715902193673) is a perfect example of the worlds of our adopters and contributors melding. On average, at any given hour of the day or night, there are more than 500 people online available to talk and provide support on any Backstage topic. Discord discussions run a full gamut of topics – from technical support questions to best practices for onboarding engineers to Backstage – basically, anything and everything an adopter may be interested to know and learn. At the very beginning of 2022, we “only” had 4k Discord members. Today, we have a growing membership of 8.2k. +Not only are our adopters growing at an exponential rate, but so too are our contributors. Our [Discord server](https://discord.gg/backstage-687207715902193673-687207715902193673) is a perfect example of the worlds of our adopters and contributors melding. On average, at any given hour of the day or night, there are more than 500 people online available to talk and provide support on any Backstage topic. Discord discussions run a full gamut of topics – from technical support questions to best practices for onboarding engineers to Backstage – basically, anything and everything an adopter may be interested to know and learn. At the very beginning of 2022, we “only” had 4k Discord members. Today, we have a growing membership of 8.2k. Isn’t it what we can call a great and vibrant community of enthusiasts? diff --git a/microsite/core/Footer.js b/microsite/core/Footer.js index 327e42f38a..c93b1779cf 100644 --- a/microsite/core/Footer.js +++ b/microsite/core/Footer.js @@ -40,7 +40,9 @@ class Footer extends React.Component {
    Community
    -
    Support chatroom + + Support chatroom + Contributing diff --git a/microsite/pages/en/community.js b/microsite/pages/en/community.js index a5fd5353e0..69330e6569 100644 --- a/microsite/pages/en/community.js +++ b/microsite/pages/en/community.js @@ -62,7 +62,9 @@ const Background = props => {
  • Chat and get support on our{' '} - Discord + + Discord +
  • diff --git a/microsite/pages/en/live.js b/microsite/pages/en/live.js index 166e3bf13a..cad5e52bd2 100644 --- a/microsite/pages/en/live.js +++ b/microsite/pages/en/live.js @@ -58,7 +58,9 @@ const Background = props => { Main community channels
    - Chat and get support on our{' '} - Discord + + Discord +
    - Get into contributing with the{' '} Good First Issues diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index 98f769e9f3..ac3ba529dd 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -16,7 +16,7 @@ # Support -If you need help with this plugin, please reach out on the [Backstage Discord server](https://discord.gg/MUpMjP2). +If you need help with this plugin, please reach out on the [Backstage Discord server](https://discord.gg/backstage-687207715902193673). # Integration Walk-through From 5d0693edc09b776985ac2842fdf0a4d19d9d6493 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 23 Feb 2023 10:44:57 +0100 Subject: [PATCH 412/417] backend-defaults: workaround for cyclic import Signed-off-by: Patrik Oldsberg --- .changeset/young-scissors-cough.md | 5 +++++ packages/backend-defaults/package.json | 1 + packages/backend-defaults/src/index.ts | 5 +++++ yarn.lock | 1 + 4 files changed, 12 insertions(+) create mode 100644 .changeset/young-scissors-cough.md diff --git a/.changeset/young-scissors-cough.md b/.changeset/young-scissors-cough.md new file mode 100644 index 0000000000..fa35588224 --- /dev/null +++ b/.changeset/young-scissors-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Added a workaround for the cyclic dependency bug across `@backstage/backend-common` and `@backstage/backend-app-api`. diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index cc10118bb8..b5f6018d64 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -33,6 +33,7 @@ }, "dependencies": { "@backstage/backend-app-api": "workspace:^", + "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^" }, "devDependencies": { diff --git a/packages/backend-defaults/src/index.ts b/packages/backend-defaults/src/index.ts index b6ae2f1333..833878744e 100644 --- a/packages/backend-defaults/src/index.ts +++ b/packages/backend-defaults/src/index.ts @@ -20,5 +20,10 @@ * @packageDocumentation */ +// This import is here as a workaround for a cyclic dependency bug where +// backend-common must be loaded before backend-app-api +// TODO(Rugvip): Remove this once backend-common is no longer used by backend-app-api +import '@backstage/backend-common'; + export type { CreateBackendOptions } from './CreateBackend'; export { createBackend } from './CreateBackend'; diff --git a/yarn.lock b/yarn.lock index 6b7d97d53c..7ccb27fb64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3514,6 +3514,7 @@ __metadata: resolution: "@backstage/backend-defaults@workspace:packages/backend-defaults" dependencies: "@backstage/backend-app-api": "workspace:^" + "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" From 9c08ecbaa4be81663fb5c059a217f7aef805e56f Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 23 Feb 2023 11:07:03 +0100 Subject: [PATCH 413/417] chore: added changeset for pagerduty Signed-off-by: blam --- .changeset/short-mayflies-fix.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/short-mayflies-fix.md diff --git a/.changeset/short-mayflies-fix.md b/.changeset/short-mayflies-fix.md new file mode 100644 index 0000000000..9d68a85da7 --- /dev/null +++ b/.changeset/short-mayflies-fix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-pagerduty': patch +--- + +Update readme link for discord channel From e1aae2f5a0cf64f6ad5d93c8ecf430f4fc6a4710 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 23 Feb 2023 13:26:37 +0100 Subject: [PATCH 414/417] core-components: updated HeaderTabs aria-label Signed-off-by: Patrik Oldsberg --- .changeset/rich-wombats-rescue.md | 5 +++++ .../core-components/src/layout/HeaderTabs/HeaderTabs.tsx | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/rich-wombats-rescue.md diff --git a/.changeset/rich-wombats-rescue.md b/.changeset/rich-wombats-rescue.md new file mode 100644 index 0000000000..d62f38cb4a --- /dev/null +++ b/.changeset/rich-wombats-rescue.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Updated the `aria-label` of the `HeaderTabs` component. diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx index aac062c01b..48e0a8906a 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx @@ -104,7 +104,7 @@ export function HeaderTabs(props: HeaderTabsProps) { textColor="inherit" variant="scrollable" scrollButtons="auto" - aria-label="scrollable auto tabs example" + aria-label="tabs" onChange={handleChange} value={selectedTab} > From 9bf50a36674556fe37192bbe4d60b42d815288ce Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Thu, 23 Feb 2023 14:08:54 +0100 Subject: [PATCH 415/417] cli: update msw version in templates Signed-off-by: Johan Haals --- .changeset/metal-suns-rhyme.md | 5 +++++ .../cli/templates/default-backend-plugin/package.json.hbs | 2 +- packages/cli/templates/default-plugin/package.json.hbs | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/metal-suns-rhyme.md diff --git a/.changeset/metal-suns-rhyme.md b/.changeset/metal-suns-rhyme.md new file mode 100644 index 0000000000..3fefdca7c6 --- /dev/null +++ b/.changeset/metal-suns-rhyme.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Bumped the `msw` version in templates to 1.0.0 diff --git a/packages/cli/templates/default-backend-plugin/package.json.hbs b/packages/cli/templates/default-backend-plugin/package.json.hbs index 24c2bb8f0a..2b860260ac 100644 --- a/packages/cli/templates/default-backend-plugin/package.json.hbs +++ b/packages/cli/templates/default-backend-plugin/package.json.hbs @@ -41,7 +41,7 @@ "@backstage/cli": "{{versionQuery '@backstage/cli'}}", "@types/supertest": "{{versionQuery '@types/supertest' '2.0.12'}}", "supertest": "{{versionQuery 'supertest' '6.2.4'}}", - "msw": "{{versionQuery 'msw' '0.49.0'}}" + "msw": "{{versionQuery 'msw' '1.0.0'}}" }, "files": [ "dist" diff --git a/packages/cli/templates/default-plugin/package.json.hbs b/packages/cli/templates/default-plugin/package.json.hbs index d319b16449..de42f3cdef 100644 --- a/packages/cli/templates/default-plugin/package.json.hbs +++ b/packages/cli/templates/default-plugin/package.json.hbs @@ -48,7 +48,7 @@ "@testing-library/react": "{{versionQuery '@testing-library/react' '12.1.3'}}", "@testing-library/user-event": "{{versionQuery '@testing-library/user-event' '14.0.0'}}", "@types/node": "{{versionQuery '@types/node' '16.11.26'}}", - "msw": "{{versionQuery 'msw' '0.49.0'}}", + "msw": "{{versionQuery 'msw' '1.0.0'}}", "cross-fetch": "{{versionQuery 'cross-fetch' '3.1.5'}}" }, "files": [ From 76263aa31ef2b4fc21595a4dc135b6f3cc6031ab Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Feb 2023 13:54:34 +0000 Subject: [PATCH 416/417] fix(deps): update dependency @roadiehq/backstage-plugin-buildkite to v2.1.5 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6fc90659ab..1eb46c2bde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13117,8 +13117,8 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-buildkite@npm:^2.0.8": - version: 2.1.4 - resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.4" + version: 2.1.5 + resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.5" dependencies: "@backstage/catalog-model": ^1.1.5 "@backstage/core-components": ^0.12.3 @@ -13136,7 +13136,7 @@ __metadata: react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 6f45a9d4fe5429f5052ecae7547e608fe4b4c6b43e5ed7d113e9648d37fbe40ced92f51f29ffe719517de101e7821e14fd7d03cc588860a90392de6fafb6e9f6 + checksum: d5ed0560401c621ae08b5eab82d5a9ebb36427f60ed2794071a7afcbc417c39c224438680234136aaaa992df19ed6b279b0292a03bdacac79359690d02256bcd languageName: node linkType: hard From 9f1356a70195c8a671ee0950d13c7732e0ff62c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Feb 2023 13:55:06 +0000 Subject: [PATCH 417/417] fix(deps): update dependency @roadiehq/backstage-plugin-github-insights to v2.3.5 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6fc90659ab..950a090c87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13141,8 +13141,8 @@ __metadata: linkType: hard "@roadiehq/backstage-plugin-github-insights@npm:^2.0.5": - version: 2.3.4 - resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.4" + version: 2.3.5 + resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.5" dependencies: "@backstage/catalog-model": ^1.1.5 "@backstage/core-components": ^0.12.3 @@ -13164,7 +13164,7 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 - checksum: 20a633dc9731ccab4f49a376d272c4b710107eacadd253bfaa3e00f9b0196632fd6fb03f651cc5e44cc99d6838ffc5b9d83c03764c0bd3926a0c8f7b3614aff7 + checksum: 66e68cb85251df7be8d97e23810ab1d3b686ab99a76452e7daa8d4d3d44a0aee623defbbe83712601120af76d1d5a504fd62f6600edf6bfc623115d3a0f4ab00 languageName: node linkType: hard