From c0d0e2bccb4fe26b79d220b2ed8d99e3499b3948 Mon Sep 17 00:00:00 2001 From: LvffY Date: Sat, 2 Apr 2022 15:39:17 +0200 Subject: [PATCH 1/8] =?UTF-8?q?[#10582]=20=F0=9F=90=9B=20Use=20getEntitySo?= =?UTF-8?q?urceLocation=20instead=20of=20custom=20method=20to=20get=20the?= =?UTF-8?q?=20entity=20source=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LvffY (cherry picked from commit f0e86e8ba349cf7056c64960b7ad39740dad4cf6) --- .../src/service/TodoReaderService.ts | 39 +------------------ 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index 4397f34045..1b3376dbfd 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -17,10 +17,7 @@ import { InputError, NotFoundError } from '@backstage/errors'; import { CatalogApi } from '@backstage/catalog-client'; import { - ANNOTATION_LOCATION, - ANNOTATION_SOURCE_LOCATION, - Entity, - parseLocationRef, + getEntitySourceLocation, stringifyEntityRef, } from '@backstage/catalog-model'; import { TodoReader } from '../lib'; @@ -75,7 +72,7 @@ export class TodoReaderService implements TodoService { ); } - const url = this.getEntitySourceUrl(entity); + const url = getEntitySourceLocation(entity).target; const todos = await this.todoReader.readTodos({ url }); let limit = req.limit ?? this.defaultPageSize; @@ -125,36 +122,4 @@ export class TodoReaderService implements TodoService { limit, }; } - - private getEntitySourceUrl(entity: Entity) { - const sourceLocation = - entity.metadata.annotations?.[ANNOTATION_SOURCE_LOCATION]; - if (sourceLocation) { - const parsed = parseLocationRef(sourceLocation); - if (parsed.type !== 'url') { - throw new InputError( - `Invalid entity source location type for ${stringifyEntityRef( - entity, - )}, got '${parsed.type}'`, - ); - } - return parsed.target; - } - - const location = entity.metadata.annotations?.[ANNOTATION_LOCATION]; - if (location) { - const parsed = parseLocationRef(location); - if (parsed.type !== 'url') { - throw new InputError( - `Invalid entity location type for ${stringifyEntityRef( - entity, - )}, got '${parsed.type}'`, - ); - } - return parsed.target; - } - throw new InputError( - `No entity location annotation found for ${stringifyEntityRef(entity)}`, - ); - } } From 1b13978d4d1ee85aaf09d092c3c8a021478244fc Mon Sep 17 00:00:00 2001 From: LvffY Date: Sat, 2 Apr 2022 17:19:33 +0200 Subject: [PATCH 2/8] =?UTF-8?q?[#10582]=20=F0=9F=92=9A=20Fix=20tests=20for?= =?UTF-8?q?=20todo-backend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LvffY (cherry picked from commit eba6328126af2e20a429c96081ae96c4615a7c9d) --- .../src/service/TodoReaderService.test.ts | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/plugins/todo-backend/src/service/TodoReaderService.test.ts b/plugins/todo-backend/src/service/TodoReaderService.test.ts index 943462bd63..f99a9b7502 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.test.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.test.ts @@ -310,7 +310,7 @@ describe('TodoReaderService', () => { }); }); - it('should throw if entity does not have a location', async () => { + it('should not throw if entity does not have a location', async () => { const todoReader = mockTodoReader([]); const catalogClient = mockCatalogClient({ ...mockEntity, @@ -320,14 +320,14 @@ describe('TodoReaderService', () => { await expect(service.listTodos({ entity: entityName })).rejects.toEqual( expect.objectContaining({ - name: 'InputError', + name: 'Error', message: - 'No entity location annotation found for component:default/my-component', + 'Entity \'component:default/my-component\' is missing location', }), ); }); - it('should throw if entity has an invalid location', async () => { + it('should not throw if entity has an invalid location', async () => { const todoReader = mockTodoReader([]); const catalogClient = mockCatalogClient({ ...mockEntity, @@ -340,15 +340,16 @@ describe('TodoReaderService', () => { }); const service = new TodoReaderService({ todoReader, catalogClient }); - await expect(service.listTodos({ entity: entityName })).rejects.toEqual( - expect.objectContaining({ - name: 'InputError', - message: `Invalid entity location type for component:default/my-component, got 'file'`, - }), + await expect(service.listTodos({ entity: entityName })).resolves.toEqual({ + items: [], + totalCount: 0, + offset: 0, + limit: 10, + } ); }); - it('should throw if entity has an invalid source location', async () => { + it('should not throw if entity has an invalid source location', async () => { const todoReader = mockTodoReader([]); const catalogClient = mockCatalogClient({ ...mockEntity, @@ -361,11 +362,12 @@ describe('TodoReaderService', () => { }); const service = new TodoReaderService({ todoReader, catalogClient }); - await expect(service.listTodos({ entity: entityName })).rejects.toEqual( - expect.objectContaining({ - name: 'InputError', - message: `Invalid entity source location type for component:default/my-component, got 'file'`, - }), + await expect(service.listTodos({ entity: entityName })).resolves.toEqual({ + items: [], + totalCount: 0, + offset: 0, + limit: 10, + } ); }); }); From 5da036264ba7b2114e9e8bb22f1b5c58e3312509 Mon Sep 17 00:00:00 2001 From: LvffY Date: Sat, 2 Apr 2022 17:29:40 +0200 Subject: [PATCH 3/8] =?UTF-8?q?[#10582]=20=E2=9C=A8=20Add=20changeset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LvffY (cherry picked from commit e16af648068bd0cc49999c5d078385f15aa7c49b) --- .changeset/gorgeous-donuts-float.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/gorgeous-donuts-float.md diff --git a/.changeset/gorgeous-donuts-float.md b/.changeset/gorgeous-donuts-float.md new file mode 100644 index 0000000000..9016b1117e --- /dev/null +++ b/.changeset/gorgeous-donuts-float.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-todo-backend': patch +--- + +Fix method to get source-location. + +See https://github.com/backstage/backstage/pull/10584 From 4e96e3fdb1ff3813cf1bf4f81970e8485b1312a3 Mon Sep 17 00:00:00 2001 From: LvffY Date: Sat, 2 Apr 2022 17:35:43 +0200 Subject: [PATCH 4/8] =?UTF-8?q?[#10582]=20=F0=9F=93=9D=20Fix=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LvffY (cherry picked from commit 1fad23ee1ece324b6026b399e8570552a11369cf) --- plugins/todo-backend/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/todo-backend/README.md b/plugins/todo-backend/README.md index 4015087b02..0f4342c19d 100644 --- a/plugins/todo-backend/README.md +++ b/plugins/todo-backend/README.md @@ -52,8 +52,9 @@ async function main() { ## Scanned Files -The included `TodoReaderService` and `TodoScmReader` works by reading source code of to the entity that is being viewed. The location source code is determined by the value of the [`backstage.io/source-location` -](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location) annotation of the entity, and if that is missing it falls back to the [`backstage.io/managed-by-location `](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiomanaged-by-location) annotation. Only `url` locations are currently supported, meaning locally configured `file` locations won't work. Also note that dot-files and folders are ignored. +The included `TodoReaderService` and `TodoScmReader` works by getting the entity source location from the catalog. + +The location source code is determined automatically. In case of the source code of the component is not in the same place of the entity YAML file, you can explicitly set the value of the [`backstage.io/source-location`](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location) annotation of the entity, and if that is missing it falls back to the [`backstage.io/managed-by-location `](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiomanaged-by-location) annotation. Only `url` locations are currently supported, meaning locally configured `file` locations won't work. Also note that dot-files and folders are ignored. ## Parser Configuration From 3399dfb8c075383b7e2151a6718c704b84adf1e0 Mon Sep 17 00:00:00 2001 From: LvffY Date: Sat, 2 Apr 2022 17:41:48 +0200 Subject: [PATCH 5/8] =?UTF-8?q?[#10582]=20=F0=9F=91=8C=20Pass=20prettier?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LvffY (cherry picked from commit a103befad1950863049a5711471500690d6eb2bd) --- plugins/todo-backend/README.md | 2 +- .../src/service/TodoReaderService.test.ts | 25 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/plugins/todo-backend/README.md b/plugins/todo-backend/README.md index 0f4342c19d..4686c2d39f 100644 --- a/plugins/todo-backend/README.md +++ b/plugins/todo-backend/README.md @@ -52,7 +52,7 @@ async function main() { ## Scanned Files -The included `TodoReaderService` and `TodoScmReader` works by getting the entity source location from the catalog. +The included `TodoReaderService` and `TodoScmReader` works by getting the entity source location from the catalog. The location source code is determined automatically. In case of the source code of the component is not in the same place of the entity YAML file, you can explicitly set the value of the [`backstage.io/source-location`](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiosource-location) annotation of the entity, and if that is missing it falls back to the [`backstage.io/managed-by-location `](https://backstage.io/docs/features/software-catalog/well-known-annotations#backstageiomanaged-by-location) annotation. Only `url` locations are currently supported, meaning locally configured `file` locations won't work. Also note that dot-files and folders are ignored. diff --git a/plugins/todo-backend/src/service/TodoReaderService.test.ts b/plugins/todo-backend/src/service/TodoReaderService.test.ts index f99a9b7502..b16f0ee669 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.test.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.test.ts @@ -321,8 +321,7 @@ describe('TodoReaderService', () => { await expect(service.listTodos({ entity: entityName })).rejects.toEqual( expect.objectContaining({ name: 'Error', - message: - 'Entity \'component:default/my-component\' is missing location', + message: "Entity 'component:default/my-component' is missing location", }), ); }); @@ -341,12 +340,11 @@ describe('TodoReaderService', () => { const service = new TodoReaderService({ todoReader, catalogClient }); await expect(service.listTodos({ entity: entityName })).resolves.toEqual({ - items: [], - totalCount: 0, - offset: 0, - limit: 10, - } - ); + items: [], + totalCount: 0, + offset: 0, + limit: 10, + }); }); it('should not throw if entity has an invalid source location', async () => { @@ -363,11 +361,10 @@ describe('TodoReaderService', () => { const service = new TodoReaderService({ todoReader, catalogClient }); await expect(service.listTodos({ entity: entityName })).resolves.toEqual({ - items: [], - totalCount: 0, - offset: 0, - limit: 10, - } - ); + items: [], + totalCount: 0, + offset: 0, + limit: 10, + }); }); }); From fe3c72181412f9d591ff87f03468c7dadff4589a Mon Sep 17 00:00:00 2001 From: LvffY Date: Fri, 8 Apr 2022 19:12:00 +0200 Subject: [PATCH 6/8] =?UTF-8?q?[#10582]=20=F0=9F=91=8C=20Fix=20changeset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/backstage/backstage/pull/10584#discussion_r841507071 Signed-off-by: LvffY (cherry picked from commit bd7e5271b1fe283fc1b304185c0d53115d1da172) --- .changeset/gorgeous-donuts-float.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/.changeset/gorgeous-donuts-float.md b/.changeset/gorgeous-donuts-float.md index 9016b1117e..72a28ba6f9 100644 --- a/.changeset/gorgeous-donuts-float.md +++ b/.changeset/gorgeous-donuts-float.md @@ -3,5 +3,3 @@ --- Fix method to get source-location. - -See https://github.com/backstage/backstage/pull/10584 From 75ab45d8b4d8988d5a52b3c1e0eb6a79d2c786d2 Mon Sep 17 00:00:00 2001 From: LvffY Date: Fri, 8 Apr 2022 19:49:37 +0200 Subject: [PATCH 7/8] =?UTF-8?q?[#10582]=20=F0=9F=91=8C=20Re-add=20tests=20?= =?UTF-8?q?and=20code=20to=20throw=20exceptions=20when=20entity=20type=20i?= =?UTF-8?q?s=20not=20url.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/backstage/backstage/pull/10584#discussion_r841505986 See https://github.com/backstage/backstage/pull/10584#discussion_r841502848 Signed-off-by: LvffY (cherry picked from commit 8a986150cc1e96b3150516ef36f24bdd89c55bff) --- .../src/service/TodoReaderService.test.ts | 32 +++++++++---------- .../src/service/TodoReaderService.ts | 11 +++++-- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/plugins/todo-backend/src/service/TodoReaderService.test.ts b/plugins/todo-backend/src/service/TodoReaderService.test.ts index b16f0ee669..3806895666 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.test.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.test.ts @@ -326,45 +326,45 @@ describe('TodoReaderService', () => { ); }); - it('should not throw if entity has an invalid location', async () => { + it('should throw if entity has an invalid location', async () => { const todoReader = mockTodoReader([]); const catalogClient = mockCatalogClient({ ...mockEntity, metadata: { ...mockEntity.metadata, annotations: { - ['backstage.io/managed-by-location']: 'file:../info.yaml', + ['backstage.io/managed-by-location']: 'file:../managed-by-location.yaml', }, }, }); const service = new TodoReaderService({ todoReader, catalogClient }); - await expect(service.listTodos({ entity: entityName })).resolves.toEqual({ - items: [], - totalCount: 0, - offset: 0, - limit: 10, - }); + await expect(service.listTodos({ entity: entityName })).rejects.toEqual( + expect.objectContaining({ + name: 'InputError', + message: `Invalid entity location type for component:default/my-component, got 'file' for location ../managed-by-location.yaml`, + }), + ); }); - it('should not throw if entity has an invalid source location', async () => { + it('should throw if entity has an invalid source location', async () => { const todoReader = mockTodoReader([]); const catalogClient = mockCatalogClient({ ...mockEntity, metadata: { ...mockEntity.metadata, annotations: { - ['backstage.io/source-location']: 'file:../info.yaml', + ['backstage.io/source-location']: 'file:../source-location.yaml', }, }, }); const service = new TodoReaderService({ todoReader, catalogClient }); - await expect(service.listTodos({ entity: entityName })).resolves.toEqual({ - items: [], - totalCount: 0, - offset: 0, - limit: 10, - }); + await expect(service.listTodos({ entity: entityName })).rejects.toEqual( + expect.objectContaining({ + name: 'InputError', + message: `Invalid entity location type for component:default/my-component, got 'file' for location ../source-location.yaml`, + }), + ); }); }); diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index 1b3376dbfd..20d633e409 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -71,8 +71,15 @@ export class TodoReaderService implements TodoService { `Entity not found, ${stringifyEntityRef(req.entity)}`, ); } - - const url = getEntitySourceLocation(entity).target; + const entitySourceLocation = getEntitySourceLocation(entity) + if (entitySourceLocation.type !== 'url') { + throw new InputError( + `Invalid entity location type for ${stringifyEntityRef( + entity, + )}, got '${entitySourceLocation.type}' for location ${entitySourceLocation.target}`, + ); + } + const url = entitySourceLocation.target; const todos = await this.todoReader.readTodos({ url }); let limit = req.limit ?? this.defaultPageSize; From 659ef6aaa9949b7ff6d638ae4750927059101111 Mon Sep 17 00:00:00 2001 From: LvffY Date: Fri, 8 Apr 2022 19:56:23 +0200 Subject: [PATCH 8/8] =?UTF-8?q?[#10582]=20=F0=9F=91=8C=20Pass=20prettier?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: LvffY (cherry picked from commit 90efbd7f197c999f7a067bb813ff5b0232307b2f) --- .../todo-backend/src/service/TodoReaderService.test.ts | 3 ++- plugins/todo-backend/src/service/TodoReaderService.ts | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/todo-backend/src/service/TodoReaderService.test.ts b/plugins/todo-backend/src/service/TodoReaderService.test.ts index 3806895666..6dd14afcb4 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.test.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.test.ts @@ -333,7 +333,8 @@ describe('TodoReaderService', () => { metadata: { ...mockEntity.metadata, annotations: { - ['backstage.io/managed-by-location']: 'file:../managed-by-location.yaml', + ['backstage.io/managed-by-location']: + 'file:../managed-by-location.yaml', }, }, }); diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index 20d633e409..35fd76b8be 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -71,12 +71,12 @@ export class TodoReaderService implements TodoService { `Entity not found, ${stringifyEntityRef(req.entity)}`, ); } - const entitySourceLocation = getEntitySourceLocation(entity) + const entitySourceLocation = getEntitySourceLocation(entity); if (entitySourceLocation.type !== 'url') { throw new InputError( - `Invalid entity location type for ${stringifyEntityRef( - entity, - )}, got '${entitySourceLocation.type}' for location ${entitySourceLocation.target}`, + `Invalid entity location type for ${stringifyEntityRef(entity)}, got '${ + entitySourceLocation.type + }' for location ${entitySourceLocation.target}`, ); } const url = entitySourceLocation.target;