From 0bd87308557406fb91d10cc88b31b3a5277f17df Mon Sep 17 00:00:00 2001 From: Jonathan Roebuck Date: Tue, 15 Oct 2024 14:07:11 +0100 Subject: [PATCH 1/8] Use theme values for OpenApiDefinition styles Signed-off-by: Jonathan Roebuck --- .../OpenApiDefinition.tsx | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx index 1505646dee..58b1a277a5 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx @@ -132,6 +132,48 @@ const useStyles = makeStyles(theme => ({ [`& span.prop-type`]: { color: theme.palette.success.light, }, + [`& .opblock-control-arrow svg, .authorization__btn .unlocked`]: { + fill: theme.palette.text.primary, + }, + [`& .json-schema-2020-12__title, + .json-schema-2020-12-keyword__name, + .json-schema-2020-12-property .json-schema-2020-12__title, + .json-schema-2020-12-keyword--description`]: { + color: theme.palette.text.primary, + }, + [`.json-schema-2020-12-accordion__icon svg`]: { + fill: theme.palette.text.primary, + }, + [`& .json-schema-2020-12-accordion, + .json-schema-2020-12-expand-deep-button`]: { + background: 'none', + appearance: 'none', + }, + [`& .json-schema-2020-12-expand-deep-button, + .json-schema-2020-12-keyword__name--secondary, + .json-schema-2020-12-keyword__value--secondary, + .json-schema-2020-12__attribute--muted, + .json-schema-2020-12-keyword__value--const, + .json-schema-2020-12-keyword__value--warning`]: { + color: theme.palette.text.secondary, + }, + [`& .json-schema-2020-12-body, + .json-schema-2020-12-keyword__value--const, + .json-schema-2020-12-keyword__value--warning`]: { + borderColor: theme.palette.text.secondary, + }, + [`.json-schema-2020-12__constraint--string`]: { + backgroundColor: theme.palette.primary.main, + }, + [`& .json-schema-2020-12__attribute--primary, + .json-schema-2020-12-property--required>.json-schema-2020-12:first-of-type>.json-schema-2020-12-head .json-schema-2020-12__title:after`]: + { + color: theme.palette.primary.main, + }, + [`& .json-schema-2020-12-property--required>.json-schema-2020-12:first-of-type>.json-schema-2020-12-head .json-schema-2020-12__title:after`]: + { + color: theme.palette.warning.dark, + }, }, }, })); From 3cd1deef6cb7396c2ecad452dc33e3a5e2264d31 Mon Sep 17 00:00:00 2001 From: Jonathan Roebuck Date: Tue, 15 Oct 2024 14:15:34 +0100 Subject: [PATCH 2/8] add changeset Signed-off-by: Jonathan Roebuck --- .changeset/mighty-jobs-unite.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/mighty-jobs-unite.md diff --git a/.changeset/mighty-jobs-unite.md b/.changeset/mighty-jobs-unite.md new file mode 100644 index 0000000000..868372196c --- /dev/null +++ b/.changeset/mighty-jobs-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': minor +--- + +Uses theme values to style the API definition schema so that theme overrides apply. From 8963eaa7a0029a866bc5fe988853b10e6b439936 Mon Sep 17 00:00:00 2001 From: Jonathan Roebuck Date: Tue, 15 Oct 2024 14:33:21 +0100 Subject: [PATCH 3/8] remove duplicated style Signed-off-by: Jonathan Roebuck --- .../OpenApiDefinitionWidget/OpenApiDefinition.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx index 58b1a277a5..ea1df525b7 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx @@ -94,7 +94,8 @@ const useStyles = makeStyles(theme => ({ .errors small`]: { color: theme.palette.text.secondary, }, - [`& .parameter__name.required:after`]: { + [`& .parameter__name.required:after, + .parameter__name.required span`]: { color: theme.palette.warning.dark, }, [`& table.model, @@ -165,11 +166,9 @@ const useStyles = makeStyles(theme => ({ [`.json-schema-2020-12__constraint--string`]: { backgroundColor: theme.palette.primary.main, }, - [`& .json-schema-2020-12__attribute--primary, - .json-schema-2020-12-property--required>.json-schema-2020-12:first-of-type>.json-schema-2020-12-head .json-schema-2020-12__title:after`]: - { - color: theme.palette.primary.main, - }, + [`& .json-schema-2020-12__attribute--primary`]: { + color: theme.palette.primary.main, + }, [`& .json-schema-2020-12-property--required>.json-schema-2020-12:first-of-type>.json-schema-2020-12-head .json-schema-2020-12__title:after`]: { color: theme.palette.warning.dark, From b3566bf0a353088d8edfabed565ed22ca4762f83 Mon Sep 17 00:00:00 2001 From: solimant Date: Wed, 16 Oct 2024 20:45:51 -0400 Subject: [PATCH 4/8] Fix typo in auth/index.md Signed-off-by: solimant --- docs/auth/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/auth/index.md b/docs/auth/index.md index 2384943c52..3e21877014 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -354,7 +354,7 @@ Passport-supported authentication method. ## Custom ScmAuthApi Implementation -The default `ScmAuthAPi` provides integrations for `github`, `gitlab`, `azure` and `bitbucket` and is created by the following code in `packages/app/src/apis.ts`: +The default `ScmAuthApi` provides integrations for `github`, `gitlab`, `azure` and `bitbucket` and is created by the following code in `packages/app/src/apis.ts`: ```ts ScmAuth.createDefaultApiFactory(); From 0064042aed2c7b0703e8284f361665fc8ca33598 Mon Sep 17 00:00:00 2001 From: solimant Date: Wed, 16 Oct 2024 21:04:22 -0400 Subject: [PATCH 5/8] Update index.md Signed-off-by: solimant --- docs/auth/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/auth/index.md b/docs/auth/index.md index 3e21877014..9f4c229e7f 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -379,7 +379,7 @@ export const apis: AnyApiFactory[] = [ ]; ``` -Then replace it with something like this, which will create an `ApiFactory` with only a github provider. +Then replace it with something like this, which will create an `ApiFactory` with only a GitHub provider. ```ts title="packages/app/src/apis.ts" export const apis: AnyApiFactory[] = [ From cf3d4edd304cb1881f579cf2dcc3c997cf2021cf Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 18 Oct 2024 14:29:03 +0200 Subject: [PATCH 6/8] Update .changeset/mighty-jobs-unite.md Signed-off-by: Patrik Oldsberg --- .changeset/mighty-jobs-unite.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/mighty-jobs-unite.md b/.changeset/mighty-jobs-unite.md index 868372196c..c8e880ba3e 100644 --- a/.changeset/mighty-jobs-unite.md +++ b/.changeset/mighty-jobs-unite.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-api-docs': minor +'@backstage/plugin-api-docs': patch --- Uses theme values to style the API definition schema so that theme overrides apply. From 873f89ad84efdf617799b7921e02004dae7b8d67 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 18 Oct 2024 15:02:22 +0200 Subject: [PATCH 7/8] catalog-client: fix case sensitive filters in mock api Signed-off-by: Patrik Oldsberg --- .changeset/two-donuts-float.md | 5 ++++ .../testUtils/InMemoryCatalogClient.test.ts | 24 +++++++++++++++++++ .../src/testUtils/InMemoryCatalogClient.ts | 19 +++++++++++---- 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 .changeset/two-donuts-float.md diff --git a/.changeset/two-donuts-float.md b/.changeset/two-donuts-float.md new file mode 100644 index 0000000000..d9df082910 --- /dev/null +++ b/.changeset/two-donuts-float.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': patch +--- + +Fix for certain filter fields in the `catalogApiMock` being case sensitive. diff --git a/packages/catalog-client/src/testUtils/InMemoryCatalogClient.test.ts b/packages/catalog-client/src/testUtils/InMemoryCatalogClient.test.ts index 3f3eaed477..b77fcd0676 100644 --- a/packages/catalog-client/src/testUtils/InMemoryCatalogClient.test.ts +++ b/packages/catalog-client/src/testUtils/InMemoryCatalogClient.test.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { CATALOG_FILTER_EXISTS } from '../types'; import { InMemoryCatalogClient } from './InMemoryCatalogClient'; import { Entity } from '@backstage/catalog-model'; @@ -25,6 +26,7 @@ const entity1: Entity = { name: 'e1', uid: 'u1', }, + relations: [{ type: 'relatedTo', targetRef: 'customkind:default/e2' }], }; const entity2: Entity = { @@ -42,10 +44,32 @@ const entities = [entity1, entity2]; describe('InMemoryCatalogClient', () => { it('getEntities', async () => { const client = new InMemoryCatalogClient({ entities }); + await expect(client.getEntities()).resolves.toEqual({ items: entities }); + + await expect( + client.getEntities({ filter: { 'metadata.name': 'E1' } }), + ).resolves.toEqual({ items: [entity1] }); + await expect( client.getEntities({ filter: { 'metadata.uid': 'u2' } }), ).resolves.toEqual({ items: [entity2] }); + + await expect( + client.getEntities({ filter: { 'metadata.uid': 'U2' } }), + ).resolves.toEqual({ items: [entity2] }); + + await expect( + client.getEntities({ + filter: { 'relations.relatedto': CATALOG_FILTER_EXISTS }, + }), + ).resolves.toEqual({ items: [entity1] }); + + await expect( + client.getEntities({ + filter: { 'relations.relatedTo': 'customkind:default/e2' }, + }), + ).resolves.toEqual({ items: [entity1] }); }); it('getEntitiesByRefs', async () => { diff --git a/packages/catalog-client/src/testUtils/InMemoryCatalogClient.ts b/packages/catalog-client/src/testUtils/InMemoryCatalogClient.ts index 355a10bf0e..13ce190e88 100644 --- a/packages/catalog-client/src/testUtils/InMemoryCatalogClient.ts +++ b/packages/catalog-client/src/testUtils/InMemoryCatalogClient.ts @@ -48,13 +48,22 @@ function buildEntitySearch(entity: Entity) { const rows = traverse(entity); if (entity.metadata?.name) { - rows.push({ key: 'metadata.name', value: entity.metadata.name }); + rows.push({ + key: 'metadata.name', + value: entity.metadata.name.toLocaleLowerCase('en-US'), + }); } if (entity.metadata?.namespace) { - rows.push({ key: 'metadata.namespace', value: entity.metadata.namespace }); + rows.push({ + key: 'metadata.namespace', + value: entity.metadata.namespace.toLocaleLowerCase('en-US'), + }); } if (entity.metadata?.uid) { - rows.push({ key: 'metadata.uid', value: entity.metadata.uid }); + rows.push({ + key: 'metadata.uid', + value: entity.metadata.uid.toLocaleLowerCase('en-US'), + }); } if (!entity.metadata.namespace) { @@ -64,8 +73,8 @@ function buildEntitySearch(entity: Entity) { // Visit relations for (const relation of entity.relations ?? []) { rows.push({ - key: `relations.${relation.type}`, - value: relation.targetRef, + key: `relations.${relation.type.toLocaleLowerCase('en-US')}`, + value: relation.targetRef.toLocaleLowerCase('en-US'), }); } From e4f5d9596bdf2c678522e66e0389e694d524b5b3 Mon Sep 17 00:00:00 2001 From: Matt Benson Date: Mon, 30 Sep 2024 18:11:19 -0500 Subject: [PATCH 8/8] Align with type declaration of template filter/global function by supporting undefined as return value. Signed-off-by: Matt Benson --- .changeset/ninety-shirts-float.md | 5 +++++ .../src/lib/templating/SecureTemplater.test.ts | 8 ++++++-- .../src/lib/templating/SecureTemplater.ts | 13 +++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 .changeset/ninety-shirts-float.md diff --git a/.changeset/ninety-shirts-float.md b/.changeset/ninety-shirts-float.md new file mode 100644 index 0000000000..4ff9a39560 --- /dev/null +++ b/.changeset/ninety-shirts-float.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Align with type declaration of template filter/global function by supporting undefined as return value. diff --git a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.test.ts b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.test.ts index 051096db57..53bf67fd87 100644 --- a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.test.ts +++ b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.test.ts @@ -107,8 +107,9 @@ describe('SecureTemplater', () => { const mockFilter1 = jest.fn(() => 'filtered text'); const mockFilter2 = jest.fn((var1, var2) => `${var1} ${var2}`); const mockFilter3 = jest.fn((var1, var2) => ({ var1, var2 })); + const mockFilter4 = jest.fn(() => undefined); const renderWith = await SecureTemplater.loadRenderer({ - templateFilters: { mockFilter1, mockFilter2, mockFilter3 }, + templateFilters: { mockFilter1, mockFilter2, mockFilter3, mockFilter4 }, }); const renderWithout = await SecureTemplater.loadRenderer(); @@ -131,6 +132,7 @@ describe('SecureTemplater', () => { var2: 'another extra arg', }), ); + expect(renderWith('${{ inputValue | mockFilter4 }}', ctx)).toBe(''); expect(() => renderWithout('${{ inputValue | mockFilter1 }}', ctx)).toThrow( /Error: filter not found: mockFilter1/, @@ -152,8 +154,9 @@ describe('SecureTemplater', () => { const mockGlobal1 = jest.fn(() => 'awesome global function'); const mockGlobal2 = 'foo'; const mockGlobal3 = 123456; + const mockGlobal4 = jest.fn(() => undefined); const renderWith = await SecureTemplater.loadRenderer({ - templateGlobals: { mockGlobal1, mockGlobal2, mockGlobal3 }, + templateGlobals: { mockGlobal1, mockGlobal2, mockGlobal3, mockGlobal4 }, }); const renderWithout = await SecureTemplater.loadRenderer(); @@ -164,6 +167,7 @@ describe('SecureTemplater', () => { ); expect(renderWith('${{ mockGlobal2 }}', ctx)).toBe('foo'); expect(renderWith('${{ mockGlobal3 }}', ctx)).toBe('123456'); + expect(renderWith('${{ mockGlobal4() }}', ctx)).toBe(''); expect(() => renderWithout('${{ mockGlobal1() }}', ctx)).toThrow( /Error: Unable to call `mockGlobal1`/, diff --git a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts index 6860902c78..b24d859bb7 100644 --- a/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts +++ b/plugins/scaffolder-backend/src/lib/templating/SecureTemplater.ts @@ -52,14 +52,17 @@ const { render, renderCompat } = (() => { }); compatEnv.addFilter('jsonify', compatEnv.getFilter('dump')); + const handleFunctionResult = (value) => { + return value === '' ? undefined : JSON.parse(value); + }; for (const name of JSON.parse(availableTemplateFilters)) { - env.addFilter(name, (...args) => JSON.parse(callFilter(name, args))); + env.addFilter(name, (...args) => handleFunctionResult(callFilter(name, args))); } for (const [name, value] of Object.entries(JSON.parse(availableTemplateGlobals))) { env.addGlobal(name, value); } for (const name of JSON.parse(availableTemplateCallbacks)) { - env.addGlobal(name, (...args) => JSON.parse(callGlobal(name, args))); + env.addGlobal(name, (...args) => handleFunctionResult(callGlobal(name, args))); } let uninstallCompat = undefined; @@ -187,7 +190,8 @@ export class SecureTemplater { if (!Object.hasOwn(templateFilters, filterName)) { return ''; } - return JSON.stringify(templateFilters[filterName](...args)); + const rz = templateFilters[filterName](...args); + return rz === undefined ? '' : JSON.stringify(rz); }, ); @@ -201,7 +205,8 @@ export class SecureTemplater { if (typeof global !== 'function') { return ''; } - return JSON.stringify(global(...args)); + const rz = global(...args); + return rz === undefined ? '' : JSON.stringify(rz); }, );